zoukankan      html  css  js  c++  java
  • Java设计模式——工厂模式

    Java设计模式——工厂模式

    工厂模式(Factory Pattern)属于创建型模式,它提供了一种创建对象的最佳方式。

    在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。术业有专攻就能很好的解释工厂模式,工厂模式就是专业生产商,我们拿来用就好了,不需要自己粗制乱遭,也不需要购买假冒伪劣产品,正规渠道拿货,质量有保障,安全,放心。

    简单工厂模式

    简单工厂模式不属于23种设计模式。他是由一个工厂实例来创建我们所需要的实例,适用于工厂类创建对象较少的场景。客户端只需要传入合适的参数就能获取所需对象,不需要关心对象的创建逻辑。

    代码示例:

    /**
     * @description: 水果产品接口
     * @author: lmc
     * @create: 2019-03-19 21:28
     **/
    
    public interface IFruits {
    
        /**
         * 水果名称
         */
        void getName();
    
        /**
         * 水果颜色
         */
        void getColor();
    
        /**
         * 水果味道
         */
        void getTaste();
    
    }
    
    /**
     * @description: 苹果
     * @author: lmc
     * @create: 2019-03-19 21:33
     **/
    
    public class Apple implements IFruits {
    
        @Override
        public void getName() {
    
            System.out.println(" 我是苹果,水果的一种");
        }
    
        @Override
        public void getColor() {
            System.out.println(" 苹果是红色的");
        }
    
        @Override
        public void getTaste() {
            System.out.println(" 苹果馋起来很甜很脆");
        }
    }
    
    /**
     * @description: 香蕉
     * @author: lmc
     * @create: 2019-03-19 21:33
     **/
    
    public class Banana implements IFruits {
    
        @Override
        public void getName() {
    
            System.out.println(" 我是香蕉,水果的一种");
        }
    
        @Override
        public void getColor() {
            System.out.println(" 香蕉是黄色的");
        }
    
        @Override
        public void getTaste() {
            System.out.println(" 香蕉馋起来很甜很滑");
        }
    }
    
    /**
     * @description: 橙子
     * @author: lmc
     * @create: 2019-03-19 21:33
     **/
    
    public class Orange implements IFruits {
    
        @Override
        public void getName() {
    
            System.out.println(" 我是橙子,水果的一种");
        }
    
        @Override
        public void getColor() {
            System.out.println(" 橙子是橙色的");
        }
    
        @Override
        public void getTaste() {
            System.out.println(" 橙子馋起来很甜水分足");
        }
    }
    

    上面的代码 创建了一个水果接口,并且创建了三种水果分别实现了水果接口。

    /**
     * @description: 水果工厂
     * @author: lmc
     * @create: 2019-03-19 21:38
     **/
    
    public class FruitsFactory {
    
        /**
         * @description: 
         * @param fruitsName
         * @return com.lmc.gp12380.pattern.factory.fruits.IFruits
         * @date 2019/5/23 15:44
         * @author lmc
         */
        public IFruits product(String fruitsName){
    
            if(null != fruitsName && fruitsName != ""){
                System.out.println("客户需求的水果是"+fruitsName);
                if("苹果".equals(fruitsName)){
                    System.out.println("水果工厂生产了苹果");
                    return new Apple();
                }
                if("橙子".equals(fruitsName)){
                    System.out.println("水果工厂生产了橙子");
                    return new Orange();
                }
                if("香蕉".equals(fruitsName)){
                    System.out.println("水果工厂生产了香蕉");
                    return new Banana();
                }
                return null;
            }else{
                return null;
            }
        }
    }
    
    

    简单工厂测试类

    /**
     * @description: 水果工厂测试类
     * @author: lmc
     * @create: 2019-03-19 21:50
     **/
    
    public class SimpleFactoryTest {
    
        public static void main(String[] args) {
            IFruits ifruits=null;
            FruitsFactory ifruitsFactory =new FruitsFactory();
    
            ifruits = ifruitsFactory.product("香蕉");
            getFruitsName(ifruits,"香蕉");
    
            ifruits = ifruitsFactory.product("苹果");
            getFruitsName(ifruits,"苹果");
    
            ifruits = ifruitsFactory.product("橙子");
            getFruitsName(ifruits,"橙子");
    
            ifruits = ifruitsFactory.product("草莓");
            getFruitsName(ifruits,"草莓");
    
        }
    
        public static void getFruitsName(IFruits ifruits,String ifruitsName){
    
            if(null != ifruits){
                ifruits.getName();
            }else{
                if(null == ifruitsName || ifruitsName==""){
                    System.out.println("未指定水果让水果工厂生产");
                }else{
                    System.out.println("水果工厂暂时无法生产"+ifruitsName);
                }
    
            }
        }
    }
    
    

    测试结果

    客户需求的水果是香蕉
    水果工厂生产了香蕉
    我是香蕉,水果的一种
    
    客户需求的水果是苹果
    水果工厂生产了苹果
    我是苹果,水果的一种
    
    客户需求的水果是橙子
    水果工厂生产了橙子
    我是橙子,水果的一种
    
    客户需求的水果是草莓
    水果工厂暂时无法生产草莓
    

    上面的代码很简单,客户传入不同的参数,就能获取工厂对象能够生产的产品。业务需求中,工厂实例创建对象的业务逻辑往往是复杂的,运用简单工厂模式,客户端就不需要关心业务了,只要创建工厂对象,传入参数调用就能获取所需对象。

    利:客户端调用简单,对于简单的业务逻辑清晰明了。

    弊:

    • 需要传参,容易出错。
      • 传一个草莓参数,或者其他乱七八糟的参数,就得不到所需对象,出问题了
    • 业务需要新的对象,需要更改工厂类,违背了开闭原则。
      • 就像上面那样,我要一个草莓对象,工厂类暂时无法创建,需要修改代码。
    • 工厂类的职责过重,不利于扩展复杂的产品结构(产品族和产品等级结构的概念后面会有说到)。
      • 随着要生产的对象越来越多,工厂类变成了万能工厂了,违背了单一原则,不利于扩展和维护。

    简单工厂类图:

    工厂方法

    工厂方法模式(FactoryMethodPattern)是指定义一个创建对象的接口(工厂接口),但让实现这个
    接口的类(工厂具体实现类)来决定实例化哪个类,工厂方法让类的实例化推迟到子类中进行。

    现代化管理都是明确分工、专人干专事、团队协作。咱们的程序代码意思一样的。

    来一个水果工厂接口

    /**
     * @description: 水果工厂接口
     * @author: lmc
     * @create: 2019-03-20 20:14
     **/
    
    public interface IFruitsFactory {
        /**
         * 工厂的生产方法
         * @return IFruits
         */
        IFruits product();
    
    }
    
    /**
     * @description: 苹果工厂
     * @author: lmc
     * @create: 2019-03-20 20:19
     **/
    
    public class AppleFactory implements IFruitsFactory {
        @Override
        public IFruits product() {
    
            System.out.println("苹果工厂只生产苹果");
            return new Apple();
        }
    }
    
    /**
     * @description: 香蕉工厂
     * @author: lmc
     * @create: 2019-03-20 20:19
     **/
    
    public class BananaFactory implements IFruitsFactory {
        @Override
        public IFruits product() {
            System.out.println("香蕉工厂只生产香蕉");
            return new Banana();
        }
    }
    
    /**
     * @description: 橙子工厂
     * @author: lmc
     * @create: 2019-03-20 20:19
     **/
    
    public class OrangeFactory implements IFruitsFactory {
        @Override
        public IFruits product() {
            System.out.println("橙子工厂只生产橙子");
            return new Orange();
        }
    }
    
    
    /**
     * @description: 工厂方法测试
     * @author: lmc
     * @create: 2019-03-20 20:39
     **/
    
    public class MethodFactoryTest {
    
        public static void main(String[] args) {
    
            IFruitsFactory iFruitsFactory= new AppleFactory();
            iFruitsFactory.product().getName();
    
            iFruitsFactory = new BananaFactory();
            iFruitsFactory.product().getName();
    
            iFruitsFactory = new OrangeFactory();
            iFruitsFactory.product().getName();
        }
    }
    
    

    运行结果:

    苹果工厂只生产苹果
    我是苹果,水果的一种
    
    香蕉工厂只生产香蕉
    我是香蕉,水果的一种
    
    橙子工厂只生产橙子
    我是橙子,水果的一种
    

    专人做专事,具体的对象只有具体的工厂创建。用户只有选择权,不需要传入参数。对象的实例化推迟到了工厂实现类创建。

    利:

    • 专人专事,遵循单一原则,子类工厂实现具体业务。让业务更清晰
    • 遵循开闭原则,新增业务,只需要添加产品类和具体的产品工厂类就可以了,增加产品扩展性。
      • 新增草莓产品,我只需要新增草莓类和草莓工厂就可以了。

    弊:

    • 类的个数容易过多,增加复杂度。
    • 增加了系统的抽象性和理解难度。

    工厂方法模式类图

    抽象工厂模式

    抽象工厂模式(Abstract Factory Pattern)是指提供一个创建一系列相关或相互依赖对象的接口,无须指定他们具体的类。客户端(应用层)不依赖于产品类实例如何被创建、实现等细节,强调的是一系列相关的产品对象(属于同一产品族)一起使用创建对象需要大量重复的代码。需要提供一个产品类的库,所有的产品以同样的接口出现,从而使客户端不依赖于具体实现。

    现在了解下上面提到的产品族和产品等级结构的概念。

    产品族:属于一个产品工厂的所有产品。

    产品等级结构:不等产品工厂生产的相同的同类产品。

    现在水果工厂需求再次升级,之前又一个水果接口 IFruits ,那么我们再增加 水果果干接口IDriedFruits 、水果果汁接口 IJuice

    /**
     * @description: 水果干产品接口
     * @author: lmc
     * @create: 2019-03-19 21:28
     **/
    
    public interface IDriedFruits {
    
        void getName();
    
        void getColor();
    
        void getTaste();
    
    }
    
    
    
    /**
     * @description: 水果果汁品接口
     * @author: lmc
     * @create: 2019-03-19 21:28
     **/
    
    public interface IJuice {
    
        void getName();
    
        void getColor();
    
        void getTaste();
    
    }
    

    现在我们有实现类 苹果汁 AppleJuice 、 苹果干 DriedApple ......

    /**
     * @description: 苹果干
     * @author: lmc
     * @create: 2019-03-19 21:33
     **/
    
    public class DriedApple implements IDriedFruits {
    
    
        @Override
        public void getName() {
    
            System.out.println(" 我是苹果干,果干的一种");
        }
    
        @Override
        public void getColor() {
            System.out.println(" 苹果干大概也是白色的吧");
        }
    
        @Override
        public void getTaste() {
            System.out.println(" 苹果干没吃过,打个也是酸酸的吧");
        }
    }
    
    
    /**
     * @description: 苹果汁
     * @author: lmc
     * @create: 2019-03-19 21:33
     **/
    
    public class AppleJuice implements IJuice {
    
    
        @Override
        public void getName() {
            System.out.println(" 我是苹果汁,果汁的一种");
        }
    
        @Override
        public void getColor() {
            System.out.println(" 苹果汁大概是白色的吧");
        }
    
        @Override
        public void getTaste() {
            System.out.println(" 苹果汁酸酸的");
        }
    }
    
    /**
     * @description: 香蕉干
     * @author: lmc
     * @create: 2019-05-23 23:06
     **/
    
    public class DriedBanana implements IDriedFruits {
        @Override
        public void getName() {
            System.out.println(" 我是香蕉干,果干的一种");
        }
    
        @Override
        public void getColor() {
            System.out.println(" 香蕉干大概也是黄色的吧");
        }
    
        @Override
        public void getTaste() {
            System.out.println(" 香蕉干甜甜的");
        }
    }
    
    /**
     * @description: 香蕉汁
     * @author: lmc
     * @create: 2019-05-23 23:10
     **/
    
    public class BananaJuice implements IJuice {
        @Override
        public void getName() {
            System.out.println(" 我是香蕉汁,果汁的一种");
        }
    
        @Override
        public void getColor() {
            System.out.println(" 香蕉汁大概是白色的吧");
        }
    
        @Override
        public void getTaste() {
            System.out.println(" 香蕉汁甜甜的");
        }
    }
    
    /**
     * @description: 橙子干
     * @author: lmc
     * @create: 2019-05-23 23:08
     **/
    
    public class DriedOrange implements IDriedFruits{
        @Override
        public void getName() {
            System.out.println(" 我是橙子干,果干的一种");
        }
    
        @Override
        public void getColor() {
            System.out.println(" 橙子干大概也是橙黄色的吧");
        }
    
        @Override
        public void getTaste() {
            System.out.println(" 香蕉干没吃过 应该是甜甜的");
        }
    }
    
    /**
     * @description: 橙汁
     * @author: lmc
     * @create: 2019-05-23 23:12
     **/
    
    public class OrangeJuice implements IJuice {
        @Override
        public void getName() {
            System.out.println(" 我是橙汁,果汁的一种");
        }
    
        @Override
        public void getColor() {
            System.out.println(" 橙汁是橙色的吧");
        }
    
        @Override
        public void getTaste() {
            System.out.println(" 橙汁汁酸酸甜甜的");
        }
    }
    

    工厂类改造

    抽象工厂接口,也可以改成抽象类

    /**
     * @description: 抽象工厂
     * @author: lmc
     * @create: 2019-03-21 21:59
     **/
    
    public interface IAbstractFruitsFactory {
    
        /**
         * @description: 水果生产
         * @return com.lmc.gp12380.pattern.factory.fruits.IFruits
         * @date 2019/5/24 8:33
         * @author lmc
         */
        IFruits productFruits();
    
        /**
         * @description: 果酱生产
         * @return com.lmc.gp12380.pattern.factory.fruits.IDriedFruits
         * @date 2019/5/24 8:34
         * @author lmc
         */
        IDriedFruits productIDriedFruits();
    
        /**
         * @description: 果汁生产
         * @return com.lmc.gp12380.pattern.factory.fruits.IJuice
         * @date 2019/5/24 8:34
         * @author lmc
         */
        IJuice productJuice();
    }
    
    /**
     * @description: 苹果工厂
     * @author: lmc
     * @create: 2019-03-21 22:02
     **/
    
    public class AppleFactory implements IAbstractFruitsFactory {
    
        /**
         * @description:苹果生成
         * @return com.lmc.gp12380.pattern.factory.fruits.IFruits
         * @date 2019/5/23 15:14
         * @author lmc
         */
        @Override
        public IFruits productFruits() {
            return new Apple();
        }
    
        /**
         * @description: 苹果酱生产
         * @return com.lmc.gp12380.pattern.factory.fruits.IDriedFruits
         * @date 2019/5/23 15:15
         * @author lmc
         */
        @Override
        public IDriedFruits productIDriedFruits() {
            return new DriedApple();
        }
    
        /**
         * @description: 苹果汁生产
         * @return com.lmc.gp12380.pattern.factory.fruits.IJuice
         * @date 2019/5/23 15:15
         * @author lmc
         */
        @Override
        public IJuice productJuice() {
            return new AppleJuice();
        }
    }
    
    
    /**
     * @description: 香蕉工厂
     * @author: lmc
     * @create: 2019-05-24 08:35
     **/
    
    public class BananaFactory implements IAbstractFruitsFactory {
    
        @Override
        public IFruits productFruits() {
            return new Banana();
        }
    
        @Override
        public IDriedFruits productIDriedFruits() {
            return new DriedBanana();
        }
    
        @Override
        public IJuice productJuice() {
            return new BananaJuice();
        }
    }
    
    /**
     * @description: 橙子工厂
     * @author: lmc
     * @create: 2019-05-24 08:27
     **/
    
    public class OrangeFactory implements IAbstractFruitsFactory {
        @Override
        public IFruits productFruits() {
            return new Orange();
        }
    
        @Override
        public IDriedFruits productIDriedFruits() {
            return new DriedOrange();
        }
    
        @Override
        public IJuice productJuice() {
            return new OrangeJuice();
        }
    }
    

    抽象工厂其实是一个产品族,具体的实现抽象工厂类生产的产品实例所产生同一产品类型,比如所有的水果是一个产品等级结构,所有的果酱也是一个产品等级结构,所有的果汁是一个产品等级结构。

    /**
     * @description: 抽象工厂方法测试
     * @author: lmc
     * @create: 2019-03-20 20:39
     **/
    
    public class AbstractFactoryTest {
    
        public static void main(String[] args) {
    
            AppleFactory appleFactory=new AppleFactory();
            IFruits apple= appleFactory.productFruits();
            apple.getName();
            apple.getColor();
            apple.getTaste();
    
            IDriedFruits appleDriedFruits=appleFactory.productIDriedFruits();
            appleDriedFruits.getColor();
            appleDriedFruits.getName();
            appleDriedFruits.getTaste();
    
            IJuice appleJuice=appleFactory.productJuice();
            appleJuice.getName();
            appleJuice.getColor();
            appleJuice.getTaste();
    
            System.out.println("_________________________________________");
            OrangeFactory orangeFactory=new OrangeFactory();
            IFruits orange= orangeFactory.productFruits();
            orange.getName();
            orange.getColor();
            orange.getTaste();
    
            IDriedFruits orangeDriedFruits=orangeFactory.productIDriedFruits();
            orangeDriedFruits.getColor();
            orangeDriedFruits.getName();
            orangeDriedFruits.getTaste();
    
            IJuice orangeJuice=orangeFactory.productJuice();
            orangeJuice.getName();
            orangeJuice.getColor();
            orangeJuice.getTaste();
    
            System.out.println("_________________________________________");
            BananaFactory bananaFactory=new BananaFactory();
            IFruits banana= bananaFactory.productFruits();
            banana.getName();
            banana.getColor();
            banana.getTaste();
    
            IDriedFruits bananaDriedFruits=bananaFactory.productIDriedFruits();
            bananaDriedFruits.getColor();
            bananaDriedFruits.getName();
            bananaDriedFruits.getTaste();
    
            IJuice bananaJuice=appleFactory.productJuice();
            bananaJuice.getName();
            bananaJuice.getColor();
            bananaJuice.getTaste();
    
        }
    }
    
    

    测试结构

     我是苹果,水果的一种
     苹果干大概也是白色的吧
     我是苹果干,果干的一种
     苹果干没吃过,打个也是酸酸的吧
     我是苹果汁,果汁的一种
     苹果汁大概是白色的吧
     苹果汁酸酸的
    _________________________________________
     我是橙子,水果的一种
     橙子干大概也是橙黄色的吧
     我是橙子干,果干的一种
     橙子干没吃过 应该是酸酸甜甜的
     我是橙汁,果汁的一种
     橙汁是橙色的吧
     橙汁汁酸酸甜甜的
    _________________________________________
     我是香蕉,水果的一种
     香蕉是黄色的
     香蕉馋起来很甜很滑
     香蕉干大概也是黄色的吧
     我是香蕉干,果干的一种
     香蕉干甜甜的
     我是香蕉汁,果汁的一种
     香蕉汁大概是白色的吧
     香蕉汁甜甜的
    

    抽象工厂利弊

    利:

    • 适合复杂业务需求,清晰描述复杂关系。
    • 专职专事,子类实现具体产品族业务。

    弊:

    • 违背开闭原则,新增产品族或者产品等级需要修改代码(产品迭代升级是有周期的)
    • 增加系统的抽象性和理解难度。

    抽象工厂类图

    总结

    工厂模式是一种面向对象程序封装,属于设计模式的创建型模式。客户端或者调用者需要的对象由工厂创建,不需要知道创建对象复杂的业务逻辑。简单工厂模式到工厂方法模式,再到抽象工厂模式。其实是一种社会进步的表现。

    简单工厂就是一个小作坊,只要是工厂有这种产品都可以去生产。这就造成了管理不规范,维护困难。注定的简单工厂就是简单工厂,发展壮大不起来。当是呢方便,就好比你需要一箱牛奶,你去小超市就可以拿了,肯定不需要费九牛二虎之力去大草原找牛去挤奶吧。

    工厂方法模式对应流水线生产企业。他们的产品比较少,管理规范,维护简单。这样的公司能够做大,出名,就好像那些只做单一产品的企业,比如服装工厂,塑料工厂。但是呢,产品单一,面临的竞争压力大,面临更复杂的业务束手无策,很容易被别人取而代之。对于新的产品,就要新建工程,新增流水线,投入成本太高。

    抽象工厂模式:对应现代化产业链代工厂,生产、管理规范。强调的是产业链,一系列相互关联的产品。形成了一个产品生态。让用户不可或缺,绝对是世界级的大企业,比如华为,以及一些世界500强公司。他面临的是一个产业链的生产管理。抽象工厂模式封装的是复杂的产品关系业务。

  • 相关阅读:
    Zabbix学习
    Ping 不通的原因分析
    【FAQ】P3. 为什么 torch.cuda.is_available() 是 False
    【PyTorch教程】P2. Python编辑器的选择、安装及配置
    PyTorch环境配置及安装
    更改文件夹图标
    卸载OpenIV
    一次写文,多平台直接粘贴&打造最流畅的写作流程
    Python字符串中删除特定字符
    Python字符串中添加、插入特定字符
  • 原文地址:https://www.cnblogs.com/programmerkaixin/p/10918844.html
Copyright © 2011-2022 走看看