你了解的工厂模式可能有误!

>>强大,10k+点赞的 SpringBoot 后台管理系统竟然出了详细教程!

你了解的工厂模式可能有误!

作者:温安适

my.oschina.net/floor/blog/1818377

5月一个酷热的中午,我跟刚来不久的小兄弟,小当闲聊起了公司用的的设计模式。

我侃侃而谈道:“咱们公司,使用的设计模式不多,也就是 策略,门面,简单工厂,工厂,单例,命令,组合,模板等。”

小当:“什么是简单工厂啊?,跟工厂模式有区别吗?”

我一听,便双手交叉于胸前,略有深意的说:“你了解的工厂模式是什么?”

小当非常流利的说:“将创建的对象方法,抽取到一个类中,根据类型不同创建相应的对象。”

我叹了口气:“小当,你了解的工厂模式有误哦,这个是简单工厂”

小当充满疑惑的说:“那什么是工厂模式,什么又是简单工厂呢?”

我喝了一口水,娓娓道来:“

简单工厂不是设计模式,而是一种编程习惯。

将创建对象的方法,抽取到一个公共类中,根据类型不同创建相应的对象。

不属于23种GOF设计模式之一。

就拿获取算奖器的例子来说吧,PL3,DLT等都有自己的算奖器。简单工厂实现方式如下:

package factory;
public class SimpleCalculatorFactoryDemo {
    public static abstract class Calculator{
        private String type;
        public Calculator(String type) {
            this.type = type;
        }
        public void calculate(){
            System.out.println(" This "+type+" calculate is done");
        }
    }
    public static class PL3Calculator extends Calculator{
        public PL3Calculator() {
            super("PL3");
        }
    }
    public static class DLTCalculator extends Calculator{
        public DLTCalculator() {
            super("DLT");
        }
    }

    public static class SimpleCalculatorFactory{
        public  Calculator createCalculator(String type){
            if ("PL3".equals(type)) { return new PL3Calculator(); }
            else if ("DLT".equals(type)){ return new DLTCalculator(); }
            return null;
        }
    }

    public static class PrizeTicketHandler{
        SimpleCalculatorFactory factory;
        public PrizeTicketHandler(SimpleCalculatorFactory factory){
            this.factory=factory;
        }
        public Calculator getCalculator(String type){
            return factory.createCalculator(type);
        }
    }
    public static void main(String[] args) {
        SimpleCalculatorFactoryDemo. SimpleCalculatorFactory factory=new SimpleCalculatorFactory();
        PrizeTicketHandler prizeTicketHandler=new PrizeTicketHandler(factory);
        prizeTicketHandler.getCalculator("DLT").calculate();
    }
}

其类图如下:

你了解的工厂模式可能有误!

我正准备往下说简单工厂的缺点的时候,小当嚼着苹果不耐烦的说:"这个你不用细说的,我早就烂熟于心了。"

抿了抿嘴,一笑说道:“那这种方式存在什么问题?”

小当停止嚼苹果,思考了10几秒说:“每新增一个类,工厂中的if判断语句也相应增加,对系统的维护和扩展非常不利。”

我点头表示认可的说道:

“确实,随着具体的产品类增加,简单工厂的逻辑需要修改,逐渐变得不易扩展和维护,并没有做的对修改关闭,对扩展开发。”

小当吃了一大口苹果后,若有所思的说道:“咱们系统中可不是这样写的,获取算奖器是分数字彩和竞彩的。”

我喝了口水后,尝试引导小当,问道:“你还记得咱们系统是如何实现的吗?”

小当扔掉苹果核,擦擦手说道:“ 当然,其实现大致如下 ”

(注意:工厂模式的实现)

package factory;
public class FactoryCalculatorDemo {
    public static abstract class Calculator{
        private String type;
        public Calculator(String type) {
            this.type = type;
        }
        public void calculate(){
            System.out.println(" This "+type+" calculate is done");
        }
    }
    public static class PL3Calculator extends Calculator {
        public PL3Calculator() {
            super("PL3");
        }
    }
    public static class DLTCalculator extends Calculator {
        public DLTCalculator() super("DLT"); }
    }
    public static class BSKCalculator extends Calculator {
        public BSKCalculator() {
            super("BSK");
        }
    }
    public static class FTCalculator extends Calculator {
        public FTCalculator() {
            super("FT");
        }
    }

    public static abstract class CalculatorFactory{
        public abstract Calculator createCalculator(String type);
    }

    public static class NumberLotteryCalculatorFactory extends CalculatorFactory {
        @Override
            public Calculator createCalculator(String type){
                if ("PL3".equals(type))
                { return new PL3Calculator(); }
                else if ("DLT".equals(type))
                { return new DLTCalculator(); }
                return null;
            }
    }

    public static class JCCalculatorFactory extends CalculatorFactory {
        @Override
        public Calculator createCalculator(String type){
            if ("BSK".equals(type))
            { return new BSKCalculator(); }
            else if ("FT".equals(type))
            { return new FTCalculator(); }
            return null;
        }
    }

    public static void main(String[] args) {
        //调用者,知悉使用的子类
        CalculatorFactory calculatorFactory=new NumberLotteryCalculatorFactory();
        calculatorFactory.createCalculator("PL3").calculate();
        calculatorFactory=new JCCalculatorFactory();
        calculatorFactory.createCalculator("FT").calculate();
    }
}

其类图如下:

你了解的工厂模式可能有误!

我看后很欣慰他掌握的挺好,我可以放心的走了。随后不等小当说话,强行总结说道:

“这个就是工厂模式了,定义了一个创建对象的接口,但由子类觉得要实例化的类是哪一个,即由NumberLotteryCalculatorFactory 和JCCalculatorFactory 决定实例化的类”。

小当抢着说:“NumberLotteryCalculatorFactory 和JCCalculatorFactory也实现了平行层级关系,若果有新加入的类,加入一个对应的工厂子类就好,不需要修改原来的代码”。

“是的” 我点头说道。

小当摸了摸下巴,又问道:“工厂模式了解了,那为什么系统中还会使用简单工厂呢?”

我一笑说道:“咱们校验器部分就是使用的简单工厂,校验器只有3个:注数,格式,金额,基本上不会变。所以使用简单工厂就好,记住实现功能越简单越好,Keep it Simple is best”

总结:

工厂模式:定义了一个创建对象的接口,但由子类觉得要实例化的类是哪一个。

至于选择具体选择简单工厂还是工厂模式,完全看业务需要,实现功能越简单越好。

Keep it Simple is best。

设计模式扩展

设计模式是什么鬼(初探)
设计模式是什么鬼(原型)
设计模式是什么鬼(单例)
设计模式是什么鬼(适配器)
设计模式是什么鬼(策略)
设计模式是什么鬼(状态)
设计模式是什么鬼(模板方法)
设计模式是什么鬼(门面)
设计模式是什么鬼(装饰)
设计模式是什么鬼(中介)
设计模式是什么鬼(组合)
设计模式是什么鬼(迭代器)
设计模式是什么鬼(备忘录)
设计模式是什么鬼(责任链)
设计模式是什么鬼(观察者)
设计模式是什么鬼(代理)
设计模式是什么鬼(工厂方法)
设计模式是什么鬼(桥接)
设计模式是什么鬼(抽象工厂)
设计模式是什么鬼(建造者)
设计模式是什么鬼(命令模式)
设计模式是什么鬼(访问者)
设计模式是什么鬼(解释器)
设计模式什么鬼?(终章)

END

推荐好文

>>【练手项目】基于SpringBoot的ERP系统,自带进销存+财务+生产功能

>>分享一套基于SpringBoot和Vue的企业级中后台开源项目,代码很规范!

>>能挣钱的,开源 SpringBoot 商城系统,功能超全,超漂亮!

你了解的工厂模式可能有误!

原文始发于微信公众号(Java知音):你了解的工厂模式可能有误!