目录
一、 简单介绍
实际上我们可能常用的工厂模式只是简单工厂(静态方法工厂),严格说来这可能只是一种编程优化的习惯,不能说程为是一种设计模式,但是不管是简单工厂、工厂方法还是抽象工厂都是为软件架构服务的,具体选择哪一种需要仔细考量,绝对不能为用而用,不要装逼装高深,简单、易用、易于理解和维护才是目的。这篇文章对工厂模式进行一个大概的介绍,便于理解记忆
上图中的工厂方法和抽象工厂都包含了相同的角色,但是在具体的架构中是有所不同的。
二、简单工厂
简单工厂,也叫作静态方法工厂,包含了三个角色工厂类、抽象产品,具体产品,所有的产品都在工厂类类里面统一初始化,并通过工厂类的静态方法统一输出。
通过一个需求来切入。
2.1 新需求,要求根据简单工厂设计
BMW公司需要造车,包括320和520两款车型,除了汽车引擎外,其它零件都是自己生产,Engine的生产(很复杂)可以自己生产或者外包,整车从制造到交付客户的流程设计?
2.2 简单工厂流程图
2.3 简单工厂实例代码
public interface IBmwEngine {
void fire();
void run();
void stop();
}
public class Bmw320Engine implements IBmwEngine{
@Override
public void fire() {
System.out.println("BMW320, fire!over!");
}
@Override
public void run() {
System.out.println("BMW320, run!over!");
}
@Override
public void stop() {
System.out.println("BMW320, stop!over!");
}
}
public class Bmw520Engine implements IBmwEngine {
@Override
public void fire() {
System.out.println("BMW520, fire!over!");
}
@Override
public void run() {
System.out.println("BMW520, run!over!");
}
@Override
public void stop() {
System.out.println("BMW520, stop!over!");
}
}
public class BmwEngineFactory {
public final static int BMW_320 = 320;
public final static int BMW_520 = 520;
public static IBmwEngine createEngine(int type) {
IBmwEngine engine = null;
switch (type) {
case BMW_320:
engine = new Bmw320Engine();
break;
case BMW_520:
engine = new Bmw520Engine();
break;
}
return engine;
}
}
public class BmwMaker {
/**
* 准备Engine
*/
private IBmwEngine prepareEngine(int typeEngine) {
return BmwEngineFactory.createEngine(typeEngine);
}
public static void main(String[] args) {
BmwMaker maker = new BmwMaker();
IBmwEngine engine = maker.prepareEngine(BmwEngineFactory.BMW_320);
engine.fire();
engine.run();
engine.stop();
}
}
测试结果:
BMW320, fire!over!
BMW320, run!over!
BMW320, stop!over!
2.4 简单工厂总结
上面代码是一个很简单的例子,也十分方便运用到实际工作中,汽车需要发动机,不同型号的发动机作为被需要的对象,分为不同的种类,统一通过工厂类创建实例和管理,上面写的比较简单,实例的创建过程涉及到诸多方面,这些细节不对外暴露,试想一下如果我们直接在BmwMaker类中new出我们的对象,然后处理各种细节,那么我们在BmwMaker需要很多逻辑来管理不同实例,这是比较复杂的,但是如果通过工厂统一处理,那么BmwMaker只需要拿来用就行了,我不需要操心实例创建的细节。
由此可以总结出简单工厂的一些特点:
优点:简单工厂根据外界给定的信息选择创建哪个具体类的对象,明确区分了各自的职责和权力,有利于整个软件体系结构的优化。
上面只是320 和520 两个类型的,如果我们需要增加更多的类型的话,我们需要增加不同的Engine类型来实现IBmwEngine接口,然后在BmwEngineFactory工厂类中添加分支输出新类型,显然我们需要修改之前已经存在的BmwEngineFactory类,违反了软件设计的封闭原则,当然这里我们举例比较简单,修改起来也不费事,当然如果我们确实在开发中也是这样的情况,那么我们这样做也没有什么问题,以最简单的方式解决问题效率会更高。但是如果遇到交付的代码不允许修改,那么我们就需要考虑新的架构了。
缺点:
每增加一个新的类别都会在工厂类中的进行添加,也违背了软件设计的封闭原则;
工厂类集中了所有实例创建的逻辑,违反了高内聚的责任分配原则。
三、工厂方法模式
针对简单工厂的缺点,进一步对架构升级,引出工厂方法模式
3.1 工厂方法包括4个角色
1、抽象产品: Product
2、具体产品:ConcreteProduct
3、抽象工厂:Factory
4、具体工厂:ConcreateFactory
3.2 工厂方法实例结构图
3.3 工厂方法实例代码
public interface BmwEngineFactory {
public final static int BMW_320 = 320;
public final static int BMW_520 = 520;
IBmwEngine createEngine();
}
public class Bmw320EngineFactory implements BmwEngineFactory{
@Override
public Bmw320Engine createEngine() {
return new Bmw320Engine();
}
}
public class Bmw520EngineFactory implements BmwEngineFactory{
@Override
public Bmw520Engine createEngine() {
return new Bmw520Engine();
}
}
public interface IBmwEngine {
void fire();
void run();
void stop();
}
public class Bmw320Engine implements IBmwEngine {
@Override
public void fire() {
System.out.println("BMW320, fire!over!");
}
@Override
public void run() {
System.out.println("BMW320, run!over!");
}
@Override
public void stop() {
System.out.println("BMW320, stop!over!");
}
}
public class Bmw520Engine implements IBmwEngine {
@Override
public void fire() {
System.out.println("BMW520, fire!over!");
}
@Override
public void run() {
System.out.println("BMW520, run!over!");
}
@Override
public void stop() {
System.out.println("BMW520, stop!over!");
}
}
public class BmwMaker {
public static void main(String[] args) {
BmwMaker maker = new BmwMaker();
IBmwEngine engine = maker.prepareEngine320();
engine.fire();
engine.run();
engine.stop();
}
private IBmwEngine prepareEngine320() {
Bmw320EngineFactory bmwEngineFactory = new Bmw320EngineFactory();
return bmwEngineFactory.createEngine();
}
}
3.4 工厂方法实例代码分析
上面的实例代码包括:
抽象工厂类:BmwEngineFactory
实例工厂类:Bmw320EngineFactory、Bmw520EngineFactory,它们两个实现了抽象工厂BmwEngineFactory
抽象产品类:IBmwEngine
具体产品类:Bmw320Engine、Bmw520Engine,它们两个实现了抽产品IBmwEngine
测试类:BmwMaker
看起来我们的代码结构复杂了,似乎我们并不需要工厂,这是从代码量的角度来考虑问题,过于狭隘。换个角度,通过不同的工厂管控对应的不同类型的实例化过程,细节完全对外屏蔽,只是提供实例对象获取接口,从这个层面上让使用和创建分开,便于分层,便于对象创建的逻辑管理。将工厂抽象成接口,提升层级,具体的工厂分别实现,有助于扩展,并且完全符合软件设计的开放封闭原则。
3.5 工厂方法总结
工厂方法虽然在一定程度上对简单工厂的短板进行了弥补,但是由于具体工厂和抽象工厂的分层,让代码量也成倍增长了。上面只是单维度的发动机制造,如果我们进一步加入,车架(Frame)、轮胎(Tire)等种类的对象,继续使用工厂方法来设计架构,我们将遇到比较麻烦的问题,比如为了确保320系列的Engine、Frame和Tire的组合的正确性你需要在使用到的地方维护彼此的逻辑,不能让520系列的零件和320的组合,那么我们在增加730系列呢?整个逻辑的管控将会变的无比庞大和复杂,而实际上我们只想简单的使用,需要制造320系列的车型的时候,我希望有一个工厂将整套零件一起返回,我不需要管理复杂的搭配。
如下如,增加Frame后,继续使用工厂方法模式的架构如下,在BmwMaker类中需要添加维护320系列和520系列组件的逻辑,以确保不会被混搭。
四、抽象工厂
在组成角色中抽象工厂和工厂方法并没有什么不同,不同的只是两个架构的设计,在系统的复杂度增加,产品的维度增加的时候,为了流程的清晰和逻辑的维护简单,需要从产品维度上调整,比如,我们不再使用产品种类这个维度来划分工厂,而是以一个系列来划分,比如320系列的产品,统一通过Bmw320Factory来输出,其中包含createEngine、createFrame等方法,统一返回同一型号的组件,这样避免了组装车间混淆不同型号的组件。
4.1 抽象工厂包括4个角色
1、抽象产品: Product
2、具体产品:ConcreteProduct
3、抽象工厂:Factory
4、具体工厂:ConcreateFactory
4.2 抽象工厂实例结构图
4.2 抽象工厂实例代码
代码机构如下如,对照看:
public interface IBmwEngine {
void fire();
void run();
void stop();
}
public class Bmw320Engine implements IBmwEngine {
@Override
public void fire() {
System.out.println("BMW320, fire!over!");
}
@Override
public void run() {
System.out.println("BMW320, run!over!");
}
@Override
public void stop() {
System.out.println("BMW320, stop!over!");
}
}
public class Bmw520Engine implements IBmwEngine {
@Override
public void fire() {
System.out.println("BMW520, fire!over!");
}
@Override
public void run() {
System.out.println("BMW520, run!over!");
}
@Override
public void stop() {
System.out.println("BMW520, stop!over!");
}
}
public interface IBmwFrame {
void install();
}
public class Bmw320Frame implements IBmwFrame {
@Override
public void install() {
System.out.println("BMW320 Frame, install!over!");
}
}
public class Bmw520Frame implements IBmwFrame {
@Override
public void install() {
System.out.println("BMW520 Frame, install!over!");
}
}
public interface BmwFactory {
IBmwEngine createEngine();
IBmwFrame createFrame();
}
public class Bmw320Factory implements BmwFactory {
@Override
public IBmwEngine createEngine() {
return new Bmw320Engine();
}
@Override
public IBmwFrame createFrame() {
return new Bmw320Frame();
}
}
public class Bmw520Factory implements BmwFactory {
@Override
public IBmwEngine createEngine() {
return new Bmw520Engine();
}
@Override
public IBmwFrame createFrame() {
return new Bmw520Frame();
}
}
public class BmwMaker {
public static void main(String[] args) {
BmwMaker maker = new BmwMaker();
maker.prepareParts320();
}
private void prepareParts320() {
Bmw320Factory bmw320Factory = new Bmw320Factory();
IBmwEngine engine = bmw320Factory.createEngine();
engine.fire();
engine.run();
engine.stop();
IBmwFrame frame = bmw320Factory.createFrame();
frame.install();
}
}
4.4 抽象工厂实例代码分析
上面的逻辑分层相对于工厂方法模式进行了改变,可以用下面的图来区别,工厂方法以纵向划分成不同零件的工厂,抽象工厂以横向车型系列进行划分一次性返回同一型号的各种零件,从而避免了系列之间的逻辑控制的混乱。
图4-1:工厂方法的产品的划分,以产品种类划分,建立工厂
图4-2:抽象工厂的产品的划分,以产品系列划分,建立工厂