听说微信搜索《Java鱼仔》会变更强哦!
本文收录于github和gitee ,里面有我完整的Java系列文章,学习或面试都可以看看哦
(一)、什么是工厂方法模式
有一个总工厂负责生产各种电视产品,此时来了一个生产小米电视的需求,就会分配出一个制作小米电视的工厂,然后就能用该工厂生产小米电视了。 上面这种通过工厂来实例化类的方式抽象到设计模式中就是工厂方法模式。
(二)、工厂方法模式中的角色
工厂方法模式中有四种角色,理解这四种角色就能理解工厂方法模式。
抽象工厂(Factory):也就是开题这个例子中的总工厂,抽象工厂是所有具体工厂的基类,在抽象工厂角色中,声明了生成产品实例的方法。抽象工厂的目的是为了让实例的生成不再通过new,而是通过生成实例的专用方法
具体工厂(ConcreteFactory):也就是开题这个例子中的制作小米电视的工厂,是抽象工厂的子类,实现抽象工厂中定义的生成产品实例的方法。
抽象产品(Product):也就是开题这个例子中的电视产品,是一个总的抽象产品,定义了一个产品的一系列方法。
具体产品(ConcreteProduct):也就是开题这个例子中的小米电视,是一个具体的产品,实现抽象产品的方法。
(三)、工厂方法模式代码案例
下面的代码描述的是工厂方法模式的案例,实现本文第一章的场景 抽象电视工厂类,提供一个produceTv的抽象方法。
publicabstractclassTvFactory { publicabstractTelevisionproduceTv(); }
抽象电视产品类,提供一个show方法。
publicabstractclassTelevision { publicabstractvoidshow(); }
具体的电视产品小米电视:
publicclassXiaomiTelevisionextendsTelevision{ publicvoidshow() { System.out.println("用小米电视看视频"); } }
具体工厂:用于生产小米电视:
publicclassXiaomiTvFactoryextendsTvFactory{ publicTelevisionproduceTv() { System.out.println("制造了小米电视"); returnnewXiaomiTelevision(); } }
最后写个测试方法:最后写个测试方法:
publicclassMain { publicstaticvoidmain(String[] args) { TelevisionXiaomiTelevision=newXiaomiTvFactory().produceTv(); XiaomiTelevision.show(); } }
这个时候又来了一个华为电视的需求,只需要和生产小米电视一样,生成华为电视具体工厂和华为电视具体类就可以了,如下:
publicclassHuaweiTvFactoryextendsTvFactory{ publicTelevisionproduceTv() { System.out.println("制造了一台华为电视"); returnnewHuaweiTelevision(); } }
publicclassHuaweiTelevisionextendsTelevision{ publicvoidshow() { System.out.println("使用华为电视看视频"); } }
然后就可以使用了
publicclassMain { publicstaticvoidmain(String[] args) { TelevisionXiaomiTelevision=newXiaomiTvFactory().produceTv(); XiaomiTelevision.show(); TelevisionHuaweiTelevision=newHuaweiTvFactory().produceTv(); HuaweiTelevision.show(); } }
(四)、为什么要用工厂方法模式
从上面的例子也能看出来,使用工厂方法模式后代码变得更加复杂了,并且想在项目中应用上貌似很困难。但是工厂方法模式却能带来一些不一样的东西
1、良好的扩展性
在设计一个项目的时候,首先要设计的是整体的代码架构。设计了顶层的抽象工厂和抽象产品之后,后续有其他的底层实现时,也只需要新增一个继承了抽象工厂的具体工厂类就行。
2、良好的封装性
以前创建一个类需要通过new方法创建,有了工厂类之后,创建的这个动作就交给工厂类去实现类。假设创建一个类的过程很复杂,有许多额外的逻辑,那么这些逻辑只需要在工厂类中实现一次,具体的产品都可以通过工厂类直接获取到。减少模块间的耦合。
3、框架和实现的隔离性
我们可以把抽象工厂和抽象产品定义为框架,而具体工厂和具体产品是实现。通过工厂方法模式,框架和实现之间是分离的。实现了底层的修改不会导致上层的改动。
(五)、工厂方法模式在源码中的应用
我们来看一下slf4j中是如何应用工厂方法模式的:
首先slf4j定义一个抽象工厂ILoggerFactory
publicinterfaceILoggerFactory { LoggergetLogger(Stringvar1); }
接着定义了一个抽象产品Logger:
publicinterfaceLogger { ... ... }
具体工厂有很多,都实现了抽象工厂,这里展示其中一个SubstituteLoggerFactory
具体工厂用于生产具体的产品,SubstituteLogger就是一种具体的产品,从上边的代码中就可以看到,SubstituteLoggerFactory工厂在生产SubstituteLogger具体产品时,做了一定的处理。而真正使用时,只需要通过getLogger方法就可以得到具体产品,这就是工厂方法模式的魅力。
(六)总结
工厂方法模式相比于适配器模式、迭代器模式或者模板方法模式更加难理解,也更加难应用到项目中。但是我们依旧可以从中学到设计的魅力,学到接口、抽象类存在的目的。