精华内容
下载资源
问答
  • 抽象工厂类的用法
    2021-10-16 17:43:07

    目录

    前言 

    一、没用spring之前,一般我的工厂类是这么实现的 。

    1.这样实现可以不可以?

    2.有什么缺点?

    二、如何使用SpringBoot如何改造?

    1.为了方便后期增加新的handler,先定义一个Person枚举。

    2.PeronHandler接口

    3.headMasterHandler实现类 ,@Compont 需要加上让spring管理 

    4.teacherHandler实现类,@Compont 需要加上让spring管理 

     5. PersonHandlerFactory工厂

     6.测试

    总结


    前言 

    对于程序员来说,23种设计模式最常用的估计就是工厂模式,不管是简单工厂还是抽象工厂。例如:在日常的业务编码handler类必不可少,为了易维护,好扩展,方便管理等。一般都会用抽象工厂对同一组handler进行统一封装。



    一、没用spring之前,一般我的工厂类是这么实现的 。

    public class Factory {
        /**
         * Object 就是抽象出来的父接口
         */
        private static final Map<Integer,Object> MAP = new HashMap<>();
    
        /**
         * 通过静态代码块来填充MAP
         */
        static {
    
        }
        
        public static Object getHandle(Integer code){
            return MAP.get(code);
        }
    }

    1.这样实现可以不可以?

            肯定是可以的。用的时候只要用调用静态方法就行。

    2.有什么缺点?

    1. 一般这么做,具体的handler都不会给spring管理。有可能我们的handler要用到spring管理的类。这种情况下就需要借助工具类。
    2. 现在的java程序员,大半都可以叫spring工程师。既然我们用了spring这么写就违背了IOC思想。
    3. 如果我们需要新增handler,需要改动工厂类。在static代码块中增加新增的handler。


    二、如何使用SpringBoot如何改造?

    我们先假设,我们需要为学校里不同职位的人写处理器,先抽出顶层接口PersonHandler,具体实现类先假设有两个

    1. HeadMasterHandler(校长处理器)
    2. TeacherHandler (老师处理器)

    1.为了方便后期增加新的handler,先定义一个Person枚举。

    package com.dreamland.springstudy.enums;
    
    import lombok.Getter;
    import lombok.ToString;
    
    /**
     * @author zhangyifeng
     * @date 2021-10-16 16:52
     */
    @Getter
    @ToString
    public enum PersonEnum {
        /**
         * 老师
         */
        TEACHER(10),
    
        /**
         * 校长
         */
        HEADMASTER(20),
    
      
    
        private final int code;
    
    
        PersonEnum(int code) {
            this.code = code;
        }
    
    }
    


    2.PeronHandler接口

    package com.dreamland.springstudy.handler;
    
    import com.dreamland.springstudy.enums.PersonEnum;
    
    /**
     * @author zhangyifeng
     * @date 2021-10-16 16:50
     */
    public interface PersonHandler {
    
        /**
         * 枚举
         * @return {@link PersonEnum}
         */
        PersonEnum getPersonEnum();
    
        /**
         * <pre>
         *   具体的校验逻辑,由子类实现
         *     一般都会携带入参,根据具体的业务需求定义。
         *     这里主要是为了让spring管理,所以不带入参。
         * </pre>
         *
         * @return true or false
         */
        boolean handle();
    }
    

    3.headMasterHandler实现类 ,@Compont 需要加上让spring管理 

    package com.dreamland.springstudy.handler.impl;
    
    import com.dreamland.springstudy.enums.PersonEnum;
    import com.dreamland.springstudy.handler.PersonHandler;
    import org.springframework.stereotype.Component;
    
    /**
     * @author zhangyifeng
     * @date  2021-10-16 16:59
     */
    @Component
    public class HeadmasterHandler implements PersonHandler {
    
        @Override
        public PersonEnum getPersonEnum() {
            return PersonEnum.HEADMASTER;
        }
    
        @Override
        public boolean handle() {
            System.out.println("校长校验器工作~~~~");
            // 写自己的校验逻辑
            return true;
        }
    }
    

    4.teacherHandler实现类,@Compont 需要加上让spring管理 

    package com.dreamland.springstudy.handler.impl;
    
    import com.dreamland.springstudy.enums.PersonEnum;
    import com.dreamland.springstudy.handler.PersonHandler;
    import org.springframework.stereotype.Component;
    
    /**
     * @author zhangyifeng
     * @date  2021-10-16 16:58
     */
    @Component
    public class TeacherHandler implements PersonHandler {
        @Override
        public PersonEnum getPersonEnum() {
            return PersonEnum.TEACHER;
        }
    
        @Override
        public boolean handle() {
            System.out.println("老师校验器工作~~~~");
            // 写自己的校验逻辑
            return true;
        }
    }
    

     5. PersonHandlerFactory工厂,@Compont 需要加上让spring管理 

    最重要的工厂类如下 有两个重要的接口需要实现,有两个重要的方法

    1. InitializingBean  接口中 afterPropertiesSet()   作用:用于初始化替代 静态代码块
    2. ApplicationContetAware 接口中 setApplicationContext(ApplicationContext var1) 作用:获取ApplicationContext对象

    这两个接口中的方法就是关键,想知道这两个接口中方法的作用,有兴趣的可用去看下源码,官方的解释更好。

    package com.dreamland.springstudy.handler;
    
    import lombok.NonNull;
    import org.springframework.beans.BeansException;
    import org.springframework.beans.factory.InitializingBean;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.ApplicationContextAware;
    import org.springframework.stereotype.Component;
    
    import java.util.HashMap;
    import java.util.Map;
    import java.util.function.Supplier;
    
    /**
     * @author zhangyifeng
     * @date 2021-10-16 17:03
     */
    @Component
    public class PersonHandlerFactory implements InitializingBean, ApplicationContextAware {
    
        private static final Map<Integer, Supplier<PersonHandler>> MAP = new HashMap<>();
    
    
        private ApplicationContext applicationContext;
    
    
        public PersonHandler createHandler(Integer personCode) {
            Supplier<PersonHandler> p = MAP.get(personCode);
            if (p != null) {
                return p.get();
            }
            throw new IllegalArgumentException("No such PersonHandler by code:" + personCode);
        }
    
        @Override
        public void afterPropertiesSet() throws Exception {
            applicationContext.getBeansOfType(PersonHandler.class)
                    .values()
                    .forEach(c -> MAP.put(c.getPersonEnum().getCode(), () -> c));
        }
    
        @Override
        public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
            this.applicationContext = applicationContext;
        }
    }
    

     6.测试

    检验是否可用通过工厂拿到具体的handler,我写个接口测试,方便一点: 

    package com.dreamland.springstudy.Controller;
    
    import com.dreamland.springstudy.handler.PersonHandler;
    import com.dreamland.springstudy.handler.PersonHandlerFactory;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RequestParam;
    import org.springframework.web.bind.annotation.RestController;
    
    /**
     * @author zhangyifeng
     * @date 2021-10-16 17:25
     */
    @RestController
    @Slf4j
    public class TestController {
    
        @Autowired
        PersonHandlerFactory personHandlerFactory;
    
        @GetMapping("/handler")
        public void testHandler(@RequestParam("code")Integer code){
            log.info("/handler code:{}",code);
            PersonHandler handler = personHandlerFactory.createHandler(code);
            handler.handle();
        }
    }
    

     测试结果证明可用从工厂类中拿到不同的handler:


    总结

    1. 这么实现很好扩展,例如我们在加一个学生处理器(studentHandler),只要写2步,就可以使用了。
      1. 枚举中增加相关定义
      2. 实现父接口
    2. 具体handler是给spring管理的,非常方面我们用srping管理的其他类

    更多相关内容
  • 主要介绍了Java设计模式之工厂模式,结合实例形式分析了简单工厂、工厂方法、抽象工厂等相关功能、实现与使用方法,需要的朋友可以参考下
  • 本文实例讲述了Python设计模式之抽象工厂模式原理与用法。分享给大家供大家参考,具体如下: 抽象工厂模式(Abstract Factory Pattern):提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们的 下面是一个...
  • 浅析JS抽象工厂模式

    2020-11-26 11:32:25
    抽象工厂模式(Abstract Factory)就是通过的抽象使得业务适用于一个产品簇的创建,而不负责某一产品的实例。 JS中是没有直接的抽象的,abstract是个保留字,但是还没有实现,因此我们需要在方法中抛出...
  • 主要介绍了Java使用抽象工厂模式实现的肯德基消费案例,较为详细的分析了抽象工厂模式的定义、原理并结合实例形式分析了Java使用抽象工厂模式实现肯德基消费案例的步骤与相关操作技巧,需要的朋友可以参考下
  • 在面向对象的编程中,一般通过继承和虚函数来提供抽象能力,多态让程序在执行期,调用者只需要看到父类类型,而不需要关心继承的子类类型。举个例子: 比如有个游戏,里面的游戏的活动对象为动物,比如有老虎和猫,会...

    在面向对象的编程中,一般通过继承和虚函数来提供抽象能力,多态让程序在执行期,调用者只需要看到父类类型,而不需要关心继承的子类类型。举个例子: 比如有个游戏,里面的游戏的活动对象为动物,比如有老虎和猫,会对主人公进行攻击。那么可能会实现为如下:
    在这里插入图片描述
    代码如下:

    class Animal
    {
    public:
    	virtual void Attack() = 0;
    };
    
    class Tiger : public Animal
    {
    public:
    	virtual void Attack() { std::cout << "Tiger Attack!" << std::endl; };
    };
    
    class Cat : public Animal
    {
    public:
    	virtual void Attack() { std::cout << "Cat Attack!" << std::endl; };
    };
    

    那如果在外面有个方法,并不需要关心具体的对象类型,只需要使用基类Animal的指针去操作对象, 利用多态机制变可以实现对具体对象类型的方法调用:

    void Attack(Animal* pAnimal)
    {
    	pAnimal->Attack();
    }
    

    比如这个时候采用如下方法进行调用(忽略里面内存释放的问题):

    	Animal* pAnimal = new Tiger;
    	Attack(pAnimal);
    	pAnimal = new Cat;
    	Attack(pAnimal);
    

    输出结果为:

    Tiger Attack!
    Cat Attack!
    

    上面多态例子说明了在程序实现的时候只需要操控Animal,知道其方法即可操作继承自Animal的对象。那么也就是说:

    1. 继承自AnimalCatTiger的不需要暴露给使用者
    2. 可以屏蔽CatTiger的创建过程,不需要被调用者所关心

    那么这个时候模块化和工厂设计模式可以对其进行实现:

    1. 比如将Animal, Cat, Tiger的实现都放进一个动态链接库的模块中,并且只暴露Animal的头文件给调用者
    2. 工厂方法设计模式,可以使用一个工厂方法创建具体的对象,返回的时候只返回基类Animal的指针。

    本文将先从简单工厂说起,然后再谈一谈工厂方法以及抽象工厂

    简单工厂

    我相信这个是大家最常见的一种实现方法,如下:
    在这里插入图片描述

    class AnimalFactory
    {
    public:
    	enum class AnimalType
    	{
    		TIGER,
    		CAT
    	};
    
    	static Animal* CreateAnimal(const AnimalType type)
    	{
    		if (AnimalType::TIGER == type)
    		{
    			return new Tiger;
    		}
    		else if (AnimalType::CAT == type)
    		{
    			return new Cat;
    		}
    		return nullptr;
    	}
    };
    

    调用方法如下:

    Animal* pAnimal = AnimalFactory::CreateAnimal(AnimalFactory::AnimalType::TIGER);
    Attack(pAnimal);
    pAnimal = AnimalFactory::CreateAnimal(AnimalFactory::AnimalType::CAT);
    Attack(pAnimal);
    

    但是这种方式违背了软件开发原则的开闭原则(Open-Closed Principle, OCP),如果你需要新增一个叫做Dog的对象,则需要在CreateAnimal方法中修改分支判断逻辑。简单来说这种扩展方式,破坏了原有的逻辑,扩展中可能对软件的原有的稳定性产生影响。

    可能有些人是不能够容忍代码,但也有人认为这种书写方式比较简单。从我个人在工程实践经验,认为软件开发设计原则是有非常好的指导性意义,但是也并不是所有的代码一定要符合软件开发的设计原则。个人的理解大致如下:

    1. 工程实践中有时候为了代码完全遵循软件开发设计原则,反而是有负担的,比如过度设计问题,一来有些代码模块可能甚至几年都不会对其进行修改扩展了,二来当逻辑实现比较简单的时候,过度设计也会让代码维护的人阅读代码实际是更加费劲的。毕竟大多数人都只是普通的程序员。
    2. 往往可扩展的代码编写时间是更长的,但是压在程序员头上的还有软件开发时间,对于一般的程序员来说,在规定时间内,有质量的完成需求是第一位的,而这个时候很可能就不会完全照顾软件开发设计原则了。

    如果要符合开闭原则,那么我们可以实现工厂方法模式,让我们一起来看看吧。

    工厂方法

    工厂方法的主要是通过继承一个AnimalFactory来实现具体的工厂,比如CatFatory主要负责生产Cat,而TigerFacotory主要负责生产Tiger,其类图如下:
    在这里插入图片描述
    代码如下:

    class AnimalFactory
    {
    public:
    	virtual Animal* CreateAnimal() = 0;
    };
    
    class CatFactory : public AnimalFactory
    {
    public:
    	virtual Animal* CreateAnimal()
    	{
    		return new Cat;
    	}
    };
    
    class TigerFactory : public AnimalFactory
    {
    public:
    	virtual Animal* CreateAnimal()
    	{
    		return new Tiger;
    	}
    };
    

    调用方式如下代码:

    AnimalFactory* pFactory = new TigerFactory;
    Animal* pAnimal = pFactory->CreateAnimal();
    Attack(pAnimal);
    
    pFactory = new CatFactory;
    pAnimal = pFactory->CreateAnimal();
    Attack(pAnimal);
    

    可以发现工厂方法模式如果需要扩展一个新的动物类型,也可以对应扩展一个新的工厂,比如增加一个新的DogFactory继承AnimalFactory去生产Dog,从而符合开闭原则,更加安全的进行扩展。但是这种方式也可以看出来,每增加一个新的动物类型就得新增一个Fatory。个人对这种模式理解如下:

    1. 当这种动物类型创建并不是很繁琐的时候,采用这种方式相比较简单工程而言会繁琐一些;但是当初始化过程比较多的时候,用工厂方法模式方式扩展会显得更加清晰;
    2. 这种设计模式的本身实现是取消了条件判断的逻辑,但是其实是把这个条件判断任务交给了使用者去判断选择哪个工厂了。

    抽象工厂

    对于新手来说可能不太好理解抽象工厂模式,容易和工厂方法模式混淆起来。工厂方法模式中的每一个工厂是生产一个动物角色,而在抽象工厂中是生产一类动物角色的抽象。
    一个动物角色比较好理解,就是我们上面的CatFactory生产Cat角色, 而TigerFactory生产Tiger角色。
    一类动物角色,我们可以理解在这个游戏中,这些动物角色的攻击性也分普通模式和困难模式。

    那么我们首先要将Tiger分成SimpleModeTigerHardModeTiger; Cat分为SimpleModeCatHardModeCat。然后抽象工厂提供CreateAnimal的接口,继承的SimpleModeFactory可以生产简单模式的Cat角色和Tiger角色,继承的HardModeFactory可以生产困难模式的Cat角色和Tiger角色。
    在这里插入图片描述
    实现的代码如下所示:

    #include <iostream>
    
    class Animal
    {
    public:
    	virtual void Attack() = 0;
    };
    
    class AbstructTiger : public Animal
    {
    public:
    	virtual void Attack() = 0;
    };
    
    class SimpleModeTiger : public AbstructTiger
    {
    public:
    	virtual void Attack()  { std::cout << "Tiger Simple Attack!" << std::endl; }
    };
    
    class HardModeTiger : public AbstructTiger
    {
    public:
    	virtual void Attack()  { std::cout << "Tiger Hard Attack!" << std::endl; }
    };
    
    class AbstructCat : public Animal
    {
    public:
    	virtual void Attack() = 0;
    };
    
    class SimpleModeCat : public AbstructCat
    {
    public:
    	virtual void Attack()  { std::cout << "Cat Simple Attack!" << std::endl; }
    };
    
    class HardModeCat : public AbstructCat
    {
    public:
    	virtual void Attack()  { std::cout << "Cat Hard Attack!" << std::endl; }
    };
    
    enum class AnimalType
    {
    	TIGER,
    	CAT
    };
    
    class AbscractAnimalFactory
    {
    public:
    	virtual Animal* CreateAnimal(const AnimalType type) = 0;
    };
    
    class SimpleModeAnimalFactory : public AbscractAnimalFactory
    {
    public:
    	virtual Animal* CreateAnimal(const AnimalType type)
    	{
    		if (AnimalType::TIGER == type)
    		{
    			return new SimpleModeTiger;
    		}
    		else if (AnimalType::CAT == type)
    		{
    			return new SimpleModeCat;
    		}
    		return nullptr;
    	}
    };
    
    class HardModeAnimalFactory : public AbscractAnimalFactory
    {
    public:
    	virtual Animal* CreateAnimal(const AnimalType type)
    	{
    		if (AnimalType::TIGER == type)
    		{
    			return new HardModeTiger;
    		}
    		else if (AnimalType::CAT == type)
    		{
    			return new HardModeCat;
    		}
    		return nullptr;
    	}
    };
    
    void Attack(Animal* pAnimal)
    {
    	pAnimal->Attack();
    }
    
    int main()
    {
    	//简单模式
    	AbscractAnimalFactory* pFactory = new SimpleModeAnimalFactory;
    	Animal* pAnimal = pFactory->CreateAnimal(AnimalType::TIGER);
    	Attack(pAnimal);
    
    	pAnimal = pFactory->CreateAnimal(AnimalType::CAT);
    	Attack(pAnimal);
    
    	//困难模式
    	pFactory = new HardModeAnimalFactory;
    	pAnimal = pFactory->CreateAnimal(AnimalType::TIGER);
    	Attack(pAnimal);
    
    	pAnimal = pFactory->CreateAnimal(AnimalType::CAT);
    	Attack(pAnimal);
    }
    

    为了让结构简单便于读者理解抽象工厂模式,以及和工厂方法模式的区别,上面的SimpleModeFactoryHardModeFactory用的是简单工厂的形式实现的,如果需要符合开闭原则,可以再对SimpleModeFactoryHardModeFactory进行工厂方法的实现。可以想象如果抽象工厂再加上工厂方法这个类的结构是有多么的庞大,而且这还仅仅只是两个游戏角色的描述。所以笔者认为在做工程实践的时候,尽量不要做过度设计,有时候反而不利于代码阅读,修改也未必简单。自己要权衡好工程和理论的平衡点。

    参考

    1. <<C++设计新思维>>中的两个章节对象工厂抽象工厂
    2. 秦小波<<设计模式之禅>>
    3. Does the Factory Pattern violate the Open/Closed Principle?
    展开全文
  • 主要介绍了Java设计模式编程中的工厂方法模式和抽象工厂模式,设计模式的建立有利于团队协作时代码的共同维护,需要的朋友可以参考下
  • Java实现抽象工厂模式

    千次阅读 2022-02-24 23:23:54
    抽象工厂模式提供一个创建一系列相关或者相互依赖对象的接口。

    什么是抽象工厂模式

    定义:抽象工厂模式提供一个创建一系列相关或者相互依赖对象的接口。

    对比 简单工厂、工厂方法、抽象工厂

    模式优点缺点
    简单工厂将创建对象的逻辑封装在一个静态方法中,外部人员不需要关注内部实现逻辑创建对象的逻辑存在一个静态方法中不方便扩展、不能被继承、违背开闭原则
    工厂方法通过提供多个工厂类来创建不同对象,解决了简单工厂模式中职责过重问题,方便扩展、可以被继承、符合开闭原则对象太多的时候就会创建很多工厂类
    抽象工厂通过提供多个工厂类来创建同一产品族对象,方便扩展、可以被继承、符合开闭原则,并且减少了工厂类数量实现起来比较复杂,不如简单工厂模式使用简单,产品族需要划分

    下面通过一个例子来实现抽象工厂模式。

    需求描述

    宝马品牌车有宝马X1、X3、X5等系列,每个系列车又配有各自的系列车标X1、X3、X5(车标只能由自己工厂创建),这三个系列车和车标分别由三个工厂创建,下面通过抽象工厂模式来实现该例子。

    UML图
    在这里插入图片描述IBMWFactory接口定义了createCar(生产车)和createLogo(生产车标)方法,X1Factory、X3Factory、X5Factory造车工厂实现该接口,同时提供生产车型和车标的方法。

    X1Car、X3Car、X5Car都实现实体BMWCar接口,并实现run方法。

    代码实现

    创建系列车类

    创建IBMWCar接口,并定义run方法。

    public interface IBMWCar {
        void run();
    }
    

    创建宝马X1车类,并实现IBMWCar接口,实现run方法。

    public class X1Car implements IBMWCar {
        @Override
        public void run() {
            System.out.println("X1Car run");
        }
    }
    

    创建宝马X3车类,并实现IBMWCar接口,实现run方法。

    public class X3Car implements IBMWCar {
        @Override
        public void run() {
            System.out.println("X3Car run");
        }
    }
    

    创建宝马X5类,并实现IBMWCar接口,实现run方法。

    public class X5Car implements IBMWCar {
        @Override
        public void run() {
            System.out.println("X5Car run");
        }
    }
    

    创建Logo车标类

    创建ILogo接口,并定义create方法。

    public interface ILogo {
        void create();
    }
    

    创建宝马X1Logo车标类,并实现ILogo接口,实现create方法。

    public class X1Logo implements ILogo {
        @Override
        public void create() {
            System.out.println("创建X1Logo");
        }
    }
    

    创建宝马X3Logo车标类,并实现ILogo接口,实现create方法。

    public class X3Logo implements ILogo {
        @Override
        public void create() {
            System.out.println("创建X3Logo");
        }
    }
    

    创建宝马X5Logo车标类,并实现ILogo接口,实现create方法。

    public class X5Logo implements ILogo {
        @Override
        public void create() {
            System.out.println("创建X5Logo");
        }
    }
    

    创建工厂接口和工厂子类

    创建工厂接口,定义createCar方法。

    public interface IBMWFactory {
        public IBMWCar createCar();
    }
    

    创建X1工厂类,并实现工厂接口,实现createCar方法,创建X1Car对象,实现createLogo方法创建X1车标对象。

    public class X1Factory implements IBMWFactory {
    
        @Override
        public IBMWCar createCar() {
            return new X1Car();
        }
    
        @Override
        public ILogo createLogo() {
            return new X1Logo();
        }
    }
    

    创建X3工厂类,并实现工厂接口,实现createCar方法,创建X3Car对象,实现createLogo方法创建X3车标对象。

    public class X3Factory implements IBMWFactory {
    
        @Override
        public IBMWCar createCar() {
            return new X3Car();
        }
    
        @Override
        public ILogo createLogo() {
            return new X3Logo();
        }
    }
    

    创建X5工厂类,并实现工厂接口,实现createCar方法,创建X5Car对象,实现createLogo方法创建X5车标对象。

    public class X5Factory implements IBMWFactory {
    
        @Override
        public IBMWCar createCar() {
            return new X5Car();
        }
    
        @Override
        public ILogo createLogo() {
            return new X5Logo();
        }
    }
    

    测试

    public class Test {
    
        public static void main(String[] args) {
            // 创建X1工厂类,并创建X1车和X1车标
            X1Factory x1Factory = new X1Factory();
            IBMWCar carX1 = x1Factory.createCar();
            carX1.run();
            ILogo logo1 = x1Factory.createLogo();
            logo1.create();
    
            // 创建X3工厂类,并创建X3车和X3车标
            X3Factory x3Factory = new X3Factory();
            IBMWCar carX3 = x3Factory.createCar();
            carX3.run();
            ILogo logo3 = x3Factory.createLogo();
            logo3.create();
    
            // 创建X5工厂类,并创建X5车和X5车标
            X5Factory x5Factory = new X5Factory();
            IBMWCar carX5 = x5Factory.createCar();
            carX5.run();
            ILogo logo5 = x5Factory.createLogo();
            logo5.create();
        }
    }
    

    运行结果:

    X1Car run
    创建X1Logo
    X3Car run
    创建X3Logo
    X5Car run
    创建X5Logo
    

    以上便是抽象工厂模式的原理和代码实现,相比工厂方法模式,多了车标产品,所以可以把品牌和车标统称为一系列产品族,这种场景便可以使用抽象工厂模式来实现。

    示例代码:abstract_factory

    开源库示例

    Mybatis库做Java服务开发的都不陌生,在Mybatis库中创建SqlSession时就是使用了抽象工厂模式,类路径:org.apache.ibatis.session.SqlSessionFactory

    public interface SqlSessionFactory {
      SqlSession openSession();
      SqlSession openSession(boolean autoCommit);
      SqlSession openSession(Connection connection);
      SqlSession openSession(TransactionIsolationLevel level);
      SqlSession openSession(ExecutorType execType);
      SqlSession openSession(ExecutorType execType, boolean autoCommit);
      SqlSession openSession(ExecutorType execType, TransactionIsolationLevel level);
      SqlSession openSession(ExecutorType execType, Connection connection);
      Configuration getConfiguration();
    }
    

    它的子类有SqlSessionManagerSqlSessionManager都提供了打开Session的方法和getConfiguration方法。

    创建的对象是SqlSession和Configuration两个相关对象,Configuration为相关配置信息,SqlSession类路径为:org.apache.ibatis.session.SqlSession,源码如下:

    public interface SqlSession extends Closeable {
      <T> T selectOne(String statement);
      <T> T selectOne(String statement, Object parameter);
      <E> List<E> selectList(String statement);
      <E> List<E> selectList(String statement, Object parameter);
      ......
    }
    

    这里提供了常用的sql执行接口。SqlSession的子类有:DefaultSqlSession、SqlSessionManager、SqlSessionTemplate,子类在创建后会提供对应的Sql执行接口。

    个人公众号,喜欢的可以关注一下:
    在这里插入图片描述

    展开全文
  • 主要介绍了Java设计模式编程中简单工厂与抽象工厂模式的使用实例,简单工厂与抽象工厂都可以归类于设计模式中的创建型模式,需要的朋友可以参考下
  • 逻辑模型:物理模型:抽象工厂的目的是要提供一个创建一系列相关或相互依赖对象的接口,而不需要指定它们具体的。这种模式可以汽车制造厂所使用的金属冲压设备中找到。这种冲压设备可以制造汽车车身部件。同样的...
  • 抽象工厂模式Demo实例

    2019-04-27 14:17:53
    抽象工厂模式Demo实例,如有想了解抽象工厂模式,可参考原博文:https://blog.csdn.net/lzb348110175/article/details/89597958,该Demo配套原博文使用
  • 主要介绍了PHP设计模式之抽象工厂模式,结合实例形式分析了php抽象工厂模式的概念、原理、使用方法及相关操作注意事项,需要的朋友可以参考下
  • 主要介绍了Java设计模式之抽象工厂模式,结合实例形式分析了抽象工厂模式的概念、功能、定义与使用方法,需要的朋友可以参考下
  • 主要介绍了iOS应用开发中使用设计模式中的抽象工厂模式,示例代码为传统的Objective-C,需要的朋友可以参考下
  • 工厂模式将目的将创建对象的具体过程屏蔽隔离起来,从而达到更高的灵活性,工厂模式可以分为三:简单工厂模式、工厂方法模式、抽象工厂模式;简单工厂模式的核心是定义一个创建对象的接口,将对象的创建和本身的...

            在面向对象编程中,创建对象实例最常用的方式就是通过 new 操作符构造一个对象实例,但在某些情况下,new 操作符直接生成对象会存在一些问题。举例来说,对象的创建需要一系列的步骤:可能需要计算或取得对象的初始位置、选择生成哪个子对象实例、或在生成之前必须先生成一些辅助对象。 在这些情况,新对象的建立就是一个 “过程”,而不仅仅是一个操作,就像一部大机器中的一个齿轮传动。

            针对上面这种情况,我们如何轻松方便地构造对象实例,而不必关心构造对象示例的细节和复杂过程?解决方案就是使用一个工厂类来创建对象。

    一、什么是工厂模式:

            工厂模式将目的将创建对象的具体过程屏蔽隔离起来,从而达到更高的灵活性,工厂模式可以分为三类:

    • 简单工厂模式(Simple Factory)
    • 工厂方法模式(Factory Method)
    • 抽象工厂模式(Abstract Factory)

    这三种模式从上到下逐步抽象,并且更具一般性。《设计模式》一书中将工厂模式分为两类:工厂方法模式与抽象工厂模式。将简单工厂模式看为工厂方法模式的一种特例,两者归为一类。 我们先从以下案例对工厂模式做个初步的了解:

    (1)在没有工厂的时代,如果客户需要一款宝马车,那么就需要客户去创建一款宝马车,然后拿来用。

    (2)简单工厂模式:后来出现了工厂,用户不再需要去创建宝马车,由工厂进行创建,想要什么车,直接通过工厂创建就可以了。比如想要320i系列车,工厂就创建这个系列的车。

    (3)工厂方法模式:为了满足客户,宝马车系列越来越多,如320i、523i等等系列,一个工厂无法创建所有的宝马系列,于是又单独分出来多个具体的工厂,每个具体工厂创建一种系列,即具体工厂类只能创建一个具体产品。但是宝马工厂还是个抽象,你需要指定某个具体的工厂才能生产车出来。

    (4)抽象工厂模式:随着客户要求越来越高,宝马车必须配置空调,于是这个工厂开始生产宝马车和需要的空调。最终是客户只要对宝马的销售员说:我要523i空调车,销售员就直接给他523i空调车了。而不用自己去创建523i空调车宝马车。

    下面我们就针对几种不同的工厂模式进行详细的说明:

    二、简单工厂模式:

            简单工厂模式的核心是定义一个创建对象的接口,将对象的创建和本身的业务逻辑分离,降低系统的耦合度,使得两个修改起来相对容易些,当以后实现改变时,只需要修改工厂类即可。

    如果不使用工厂,用户将自己创建宝马车,具体UML图和代码如下:

    public class BMW320 {
    	public BMW320(){
    		System.out.println("制造-->BMW320");
    	}
    }
     
    public class BMW523 {
    	public BMW523(){
    		System.out.println("制造-->BMW523");
    	}
    }
     
    public class Customer {
    	public static void main(String[] args) {
    		BMW320 bmw320 = new BMW320();
    		BMW523 bmw523 = new BMW523();
    	}
    }

            用户需要知道怎么创建一款车,这样子客户和车就紧密耦合在一起了,为了降低耦合,就出现了简单工厂模式,把创建宝马的操作细节都放到了工厂里,而客户直接使用工厂的创建方法,传入想要的宝马车型号就行了,而不必去知道创建的细节。

    1、简单工厂模式的UML图:

    • 工厂类角色: 该模式的核心,用来创建产品,含有一定的商业逻辑和判断逻辑
    • 抽象产品角色:它一般是具体产品继承的父类或者实现的接口。   
    • 具体产品角色:工厂类所创建的对象就是此角色的实例。在java中由一个具体类实现。

    2、代码实现:

    产品类:

    abstract class BMW {
    	public BMW(){}
    }
     
    public class BMW320 extends BMW {
    	public BMW320() {
    		System.out.println("制造-->BMW320");
    	}
    }
    public class BMW523 extends BMW{
    	public BMW523(){
    		System.out.println("制造-->BMW523");
    	}
    }
    

    工厂类:

    public class Factory {
    	public BMW createBMW(int type) {
    		switch (type) {
    		
    		case 320:
    			return new BMW320();
     
    		case 523:
    			return new BMW523();
     
    		default:
    			break;
    		}
    		return null;
    	}
    }

    用户类:

    public class Customer {
    	public static void main(String[] args) {
    		Factory factory = new Factory();
    		BMW bmw320 = factory.createBMW(320);
    		BMW bmw523 = factory.createBMW(523);
    	}
    }

    3、简单工厂模式的优缺点:

            简单工厂模式提供专门的工厂类用于创建对象,实现了对象创建和使用的职责分离,客户端不需知道所创建的具体产品类的类名以及创建过程,只需知道具体产品类所对应的参数即可,通过引入配置文件,可以在不修改任何客户端代码的情况下更换和增加新的具体产品类,在一定程度上提高了系统的灵活性。

            但缺点在于不符合“开闭原则”,每次添加新产品就需要修改工厂类。在产品类型较多时,有可能造成工厂逻辑过于复杂,不利于系统的扩展维护,并且工厂类集中了所有产品创建逻辑,一旦不能正常工作,整个系统都要受到影响。

            为了解决简单工厂模式的问题,出现了工厂方法模式。

    三、工厂方法模式:

            工厂方法模式将工厂抽象化,并定义一个创建对象的接口。每增加新产品,只需增加该产品以及对应的具体实现工厂类,由具体工厂类决定要实例化的产品是哪个,将对象的创建与实例化延迟到子类,这样工厂的设计就符合“开闭原则”了,扩展时不必去修改原来的代码。在使用时,用于只需知道产品对应的具体工厂,关注具体的创建过程,甚至不需要知道具体产品类的类名,当我们选择哪个具体工厂时,就已经决定了实际创建的产品是哪个了。

            但缺点在于,每增加一个产品都需要增加一个具体产品类和实现工厂类,使得系统中类的个数成倍增加,在一定程度上增加了系统的复杂度,同时也增加了系统具体类的依赖。

    1、工厂方法的 UML 结构图如下:

    • 抽象工厂 AbstractFactory: 工厂方法模式的核心,是具体工厂角色必须实现的接口或者必须继承的父类,在 Java 中它由抽象类或者接口来实现。 
    • 具体工厂 Factory:被应用程序调用以创建具体产品的对象,含有和具体业务逻辑有关的代码
    • 抽象产品 AbstractProduct:是具体产品继承的父类或实现的接口,在 Java 中一般有抽象类或者接口来实现。 
    • 具体产品 Product:具体工厂角色所创建的对象就是此角色的实例。

    2、代码实现:

    产品类:

    abstract class BMW {
    	public BMW(){}
    }
    public class BMW320 extends BMW {
    	public BMW320() {
    		System.out.println("制造-->BMW320");
    	}
    }
    public class BMW523 extends BMW{
    	public BMW523(){
    		System.out.println("制造-->BMW523");
    	}
    }
    

    工厂类:

    interface FactoryBMW {
    	BMW createBMW();
    }
     
    public class FactoryBMW320 implements FactoryBMW{
     
    	@Override
    	public BMW320 createBMW() {
    		return new BMW320();
    	}
     
    }
    public class FactoryBMW523 implements FactoryBMW {
    	@Override
    	public BMW523 createBMW() {
    		return new BMW523();
    	}
    }
    

    客户类:

    public class Customer {
    	public static void main(String[] args) {
    		FactoryBMW320 factoryBMW320 = new FactoryBMW320();
    		BMW320 bmw320 = factoryBMW320.createBMW();
     
    		FactoryBMW523 factoryBMW523 = new FactoryBMW523();
    		BMW523 bmw523 = factoryBMW523.createBMW();
    	}
    }
    

    四、抽象工厂模式:

            在工厂方法模式中,我们使用一个工厂创建一个产品,一个具体工厂对应一个具体产品,但有时候我们需要一个工厂能够提供多个产品对象,而不是单一的对象,这个时候我们就需要使用抽象工厂模式。

            在介绍抽象工厂模式前,我们先厘清两个概念:

    • 产品等级结构:产品等级结构指的是产品的继承结构,例如一个空调抽象类,它有海尔空调、格力空调、美的空调等一系列的子类,那么这个空调抽象类和他的子类就构成了一个产品等级结构。
    • 产品族:产品族是指由同一个工厂生产的,位于不同产品等级结构中的一组产品。比如,海尔工厂生产海尔空调、海尔冰箱,那么海尔空调则位于空调产品族中。

    产品等级结构和产品族结构示意图如下:

    1、什么是抽象工厂模式:

            抽象工厂模式主要用于创建相关对象的家族。当一个产品族中需要被设计在一起工作时,通过抽象工厂模式,能够保证客户端始终只使用同一个产品族中的对象;并且通过隔离具体类的生成,使得客户端不需要明确指定具体生成类;所有的具体工厂都实现了抽象工厂中定义的公共接口,因此只需要改变具体工厂的实例,就可以在某种程度上改变整个软件系统的行为。

            但该模式的缺点在于添加新的行为时比较麻烦,如果需要添加一个新产品族对象时,需要更改接口及其下所有子类,这必然会带来很大的麻烦。

    2、UML结构图:

    • 抽象工厂 AbstractFactory:定义了一个接口,这个接口包含了一组方法用来生产产品,所有的具体工厂都必须实现此接口。
    • 具体工厂 ConcreteFactory:用于生产不同产品族,要创建一个产品,用户只需使用其中一个工厂进行获取,完全不需要实例化任何产品对象。
    • 抽象产品 AbstractProduct:这是一个产品家族,每一个具体工厂都能够生产一整组产品。
    • 具体产品 Product

    3、代码实现:

            通过抽象工厂模式,我们可以实现以下的效果:比如宝马320系列使用空调型号A和发动机型号A,而宝马230系列使用空调型号B和发动机型号B,在为320系列生产相关配件时,就无需制定配件的型号,它会自动根据车型生产对应的配件型号A。

            也就是说,当每个抽象产品都有多于一个的具体子类的时候(空调有型号A和B两种,发动机也有型号A和B两种),工厂角色怎么知道实例化哪一个子类呢?抽象工厂模式提供两个具体工厂角色(宝马320系列工厂和宝马230系列工厂),分别对应于这两个具体产品角色,每一个具体工厂角色只负责某一个产品角色的实例化,每一个具体工厂类只负责创建抽象产品的某一个具体子类的实例。

    产品类:

    //发动机以及型号  
    public interface Engine {}  
    
    public class EngineA implements Engine{  
        public EngineA(){  
            System.out.println("制造-->EngineA");  
        }  
    }  
    public class EngineB implements Engine{  
        public EngineB(){  
            System.out.println("制造-->EngineB");  
        }  
    }  
     
    
    //空调以及型号  
    public interface Aircondition {} 
     
    public class AirconditionA implements Aircondition{  
        public AirconditionA(){  
            System.out.println("制造-->AirconditionA");  
        }  
    }  
    public class AirconditionB implements Aircondition{  
        public AirconditionB(){  
            System.out.println("制造-->AirconditionB");  
        }  
    } 
    

    创建工厂类:

    //创建工厂的接口  
    public interface AbstractFactory {  
        //制造发动机
        public Engine createEngine();
        //制造空调 
        public Aircondition createAircondition(); 
    }  
     
    //为宝马320系列生产配件  
    public class FactoryBMW320 implements AbstractFactory{     
        @Override  
        public Engine createEngine() {    
            return new EngineA();  
        }  
        @Override  
        public Aircondition createAircondition() {  
            return new AirconditionA();  
        }  
    }  
    //宝马523系列
    public class FactoryBMW523 implements AbstractFactory {  
         @Override  
        public Engine createEngine() {    
            return new EngineB();  
        }  
        @Override  
        public Aircondition createAircondition() {  
            return new AirconditionB();  
        }  
    } 
    

    客户:

    public class Customer {  
        public static void main(String[] args){  
            //生产宝马320系列配件
            FactoryBMW320 factoryBMW320 = new FactoryBMW320();  
            factoryBMW320.createEngine();
            factoryBMW320.createAircondition();
              
            //生产宝马523系列配件  
            FactoryBMW523 factoryBMW523 = new FactoryBMW523();  
            factoryBMW523.createEngine();
            factoryBMW523.createAircondition();
        }  
    }
    

    工厂模式小结:

    1、工厂方法模式与抽象工厂模式的区别在于:

    (1)工厂方法只有一个抽象产品类和一个抽象工厂类,但可以派生出多个具体产品类和具体工厂类,每个具体工厂类只能创建一个具体产品类的实例。

    (2)抽象工厂模式拥有多个抽象产品类(产品族)和一个抽象工厂类,每个抽象产品类可以派生出多个具体产品类;抽象工厂类也可以派生出多个具体工厂类,同时每个具体工厂类可以创建多个具体产品类的实例


    设计模式系列文章:

    Java设计模式之创建型:工厂模式详解(简单工厂+工厂方法+抽象工厂)

    Java设计模式之创建型:建造者模式

    Java设计模式之创建型:单例模式

    Java设计模式之创建型:原型模式

    Java设计模式之结构型:适配器模式

    Java设计模式之结构型:装饰器模式

    Java设计模式之结构型:代理模式

    Java设计模式之结构型:桥接模式

    Java设计模式之结构型:外观模式

    Java设计模式之结构型:组合模式

    Java设计模式之结构型:享元模式

    Java设计模式之行为型:策略模式

    Java设计模式之行为型:模板方法模式

    Java设计模式之行为型:责任链模式

    Java设计模式之行为型:观察者模式

    Java设计模式之行为型:访问者模式

    Java设计模式之行为型:中介者模式

    Java设计模式之行为型:命令模式

    Java设计模式之行为型:状态模式

    Java设计模式之行为型:备忘录模式

    Java设计模式之行为型:迭代器模式

    Java设计模式之行为型:解释器模式


    参考文章:

    设计模式读书笔记----简单工厂模式_chenssy 的技术博客-CSDN博客

    设计模式读书笔记----工厂方法模式_chenssy 的技术博客-CSDN博客

    设计模式读书笔记----抽象工厂模式_chenssy 的技术博客-CSDN博客

    JAVA设计模式之抽象工厂模式_一个本科小生的奋斗史-CSDN博客_java抽象工厂模式

    展开全文
  • 工厂系列 定义: 工厂模式主要是为创建对象提供过渡接口,以便将创建对象的具体过程屏蔽隔离...GOF 在《设计模式》一书中将工厂模式分为两:工厂方法模式(Factory Method)与抽象工厂模式(Abstract Factory)。将简
  • 主要介绍了Java设计模式笔记之抽象工厂代码示例,见解独到,代码详细,具有一定参考价值,需要的朋友可以了解下。
  • 本文实例讲述了JavaScript设计模式之工厂模式和抽象工厂模式定义与用法。分享给大家供大家参考,具体如下: 1、工厂模式: 虽然Object构造函数和对象字面量都可以用来创建单个对象,但这个方式有个明显的缺点:使用...
  • Spring常用设计模式--抽象工厂模式

    千次阅读 2022-03-15 16:54:45
      抽象工厂模式是指提供一个创建一系列相关或相互依赖对象的接口,无需指定他们的具体。客户端(应用层)不依赖于产品实体如何被创建、如何被实现等细节,强调的是一系列相关的产品对象(属于同一产品族)一起...
  • 使用简单工厂模式模拟女娲(Nvwa)造人(Person),如果传入参数M,则返回一个Man对象,如果传入参数W,则返回一个Woman对象,请实现该场景。现需要增加一个新的Robot,如果传入参数R,则返回一个Robot对象,对...
  • 大话设计模式之抽象工厂抽象工厂 + 反射 + 配置文件) 提供一个创建一系列相关或互相依赖的对象的接口,而无需指定他们具体的 2.抽象工厂的结构图
  • 抽象工厂模式 使用场景:例如如生产不同品牌旗下的一系列产品 例如我之前拥有奔驰这一品牌,但是我又想创建宝马品牌,它们都分别拥有A(低端车),B(高端车)系列生产线。 如图: 品牌 A(低端车) B(高端车) ...
  • 文章目录定义举个栗子抽象工厂模式的优点抽象工厂模式的缺点简单工厂、工厂模式、抽象工厂小结简单工厂工厂方法模式抽象工厂模式 Provide an interface for creating families of related or dependent objects ...
  • 简单工厂没有抽象类,只有一个具体工厂类如MyFactory,然后MyFactory里面有个工厂方法CreateProduct返回一个基类产品,具体返回什么具体实例通过传入参数然后用case判断。 用手机生产做个例子: 比如Nokia简单工厂...
  • 抽象工厂模式 模式的定义与特点 模式的结构 代理模式 代理模式的定义与特点 代理模式的结构与实现 前面介绍的工厂方法模式中考虑的是一产品的生产,如畜牧场只养动物、电视机厂只生产电视机、计算机软件学院...
  • 1 简单工厂(Simple Factory) 1.1 问题引出 假如有一个披萨店,Pizza的种类有很多,如CheesePizza、VeggiePizza、PepperPizza等。披萨店根据收到的订单制作Pizza,披萨的制作流程有材料的准备材料、烤、切、包装几步...
  • 抽象工厂模式的详解

    千次阅读 2020-11-06 00:47:40
    此时,我们可以考虑将一些相关的具体组成一个“具体族”,由同一个工厂来统一生产,这就是我们需要抽象工厂模式的原因。 2.抽象工厂模式的定义 抽象工厂模式: 是一种为用户提供一个创建一组相关或相互依赖的...
  • 一、抽象工厂模式简介、 二、抽象工厂模式适用场景、 三、抽象工厂模式优缺点、 四、产品等级结构和产品族、 五、抽象工厂模式代码示例、 1、冰箱抽象、 2、美的冰箱实现、 3、格力冰箱实现、 4、空调抽象、...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 178,251
精华内容 71,300
关键字:

抽象工厂类的用法