作者:汤圆
个人博客:javalover.cc
前言
工厂我们都知道,就是生产东西的地方;
以前的农业时代,我们需要啥东西,都是自己做,比如椅子、桌子;
后来到了工业时代,我们需要啥东西,大部分都是工厂做,你只需要告诉工厂需要的东西。
其实软件中的工厂设计模式,也是类似:不需要我们自己去创建对象,只需要告诉工厂类,需要啥对象,工厂类会帮你创建。
下面我们循序渐进来介绍下工厂模式
目录
- 制作一种椅子
- 制作多种椅子
- 创建一个椅子工厂(简单工厂模式)
- 创建多个椅子工厂(工厂方法模式)
- 创建多个椅子工厂(抽象工厂模式)
正文
1. 制作一种椅子
这个是最简单的了,就是谁需要,谁就创建一个,很方便;
package pattern.factory.nofactory;/** * 没有工厂,直接创建椅子 */public class NoFactory { public static void main(String[] args) { Chair chair = new Chair(); chair.prepare(); chair.make(); chair.box(); } static class Chair { public String name = "小椅子"; public void prepare() { System.out.println(name + "的原材料是:A,B,C"); } public void make(){ System.out.println(name + "制作中"); } public void box(){ System.out.println(name + "打包中"); } }}
2. 制作多种椅子
过了几天,小李觉得这种椅子不舒服,没有靠背,于是又创建了带靠背的椅子
package pattern.factory.nofactory;/** * 没有工厂,直接创建椅子(多种椅子) */public class NoFactory2 { public static void main(String[] args) { Chair chair = new ChairA(); chair.prepare(); chair.make(); chair.box(); Chair chairB = new ChairB(); chairB.prepare(); chairB.make(); chairB.box(); }}abstract class Chair { public String name; public abstract void prepare(); public void make(){ System.out.println(name + "制作中"); } public void box(){ System.out.println(name + "打包中"); }}class ChairA extends Chair { public ChairA() { this.name = "小椅子"; } @Override public void prepare() { System.out.println(name + "的原材料是:A,B,C"); }}class ChairB extends Chair { public ChairB() { this.name = "靠背椅"; } @Override public void prepare() { System.out.println(name + "的原材料是:A2,B2,C2"); }}
这样看来,好像问题也不大;
可以是如果不止两种,而是十几种几十种呢?
此时再一个个创建就很麻烦了;
于是就有了工厂模式。
其实不止类型的增加需要工厂,数量的增加同样也需要工厂(流水线制作提高效率)
3. 创建一个椅子工厂(简单工厂模式)
简单工厂模式:定义一个工厂类,它可以根据参数的不同返回不同类的实例,被创建的实例通常都具有共同的父类
小李花钱建了一个工厂,专门做各种各样的椅子,这样他每天都可以换不同的椅子坐;
大概的流程就是小李需要什么椅子,就告诉工厂,工厂来做(不再需要自己做)。
package pattern.factory.simple1;public class SimpleFactory1 { public static void main(String[] args) { SimpleChairFactory simpleChairFactory = new SimpleChairFactory(); simpleChairFactory.order("小椅子"); simpleChairFactory.order("靠背椅"); }}class SimpleChairFactory { public Chair chair; public void order(String name){ if(name == "小椅子"){ chair = new ChairA(); }else if(name == "靠背椅"){ chair = new ChairB(); }else{ chair = null; } if(chair != null){ chair.prepare(); chair.make(); chair.box(); }else{ System.out.println("找不到对应的椅子"); } }}abstract class Chair { public String name; public abstract void prepare(); public void make(){ System.out.println(name + "制作中"); } public void box(){ System.out.println(name + "打包中"); }}class ChairA extends Chair { public ChairA() { this.name = "小椅子"; } @Override public void prepare() { System.out.println(name + "的原材料是:A,B,C"); }}class ChairB extends Chair { public ChairB() { this.name = "靠背椅"; } @Override public void prepare() { System.out.println(name + "的原材料是:A2,B2,C2"); }}
上面这个就是简单工厂模式,通过把自己的需求告诉工厂,工厂去做出你想要的东西;
4. 创建多个椅子工厂(工厂方法模式)
工厂方法模式:定义一个用于创建对象的接口,让子类决定将哪一个类实例化。
上面的简单工厂模式,确实很简单,用起来也很方便;
但是有一个很大的缺点,就是如果需要增加椅子的种类,那么就需要修改工厂类的源代码;
这样一来就违背了开闭原则:对类的扩展开放,对类的修改关闭;
所以我们需要对其进行改进,创建多个工厂子类,来实现不同的创建任务。
package pattern.factory.method;/** * 工厂方法模式:将工厂类抽象出来,子类去实现对象的创建 */public class MethodFactory { public static void main(String[] args) { SmallChairFactory smallFactory = new SmallChairFactory(); smallFactory.order(); BackChairFactory backFactory = new BackChairFactory(); backFactory.order(); }}interface ChairFactory{ void order();}class SmallChairFactory implements ChairFactory{ public Chair chair; public void order(){ chair = new ChairA(); chair.prepare(); chair.make(); chair.box(); }}class BackChairFactory implements ChairFactory{ public Chair chair; public void order(){ chair = new ChairB(); chair.prepare(); chair.make(); chair.box(); }}abstract class Chair { public String name; public abstract void prepare(); public void make(){ System.out.println(name + "制作中"); } public void box(){ System.out.println(name + "打包中"); }}class ChairA extends Chair { public ChairA() { this.name = "小椅子"; } @Override public void prepare() { System.out.println(name + "的原材料是:A,B,C"); }}class ChairB extends Chair { public ChairB() { this.name = "靠背椅"; } @Override public void prepare() { System.out.println(name + "的原材料是:A2,B2,C2"); }}
5. 创建多个椅子工厂(抽象工厂模式)
抽象工厂模式:提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类。
上面的工厂方法模式,虽然解决了简单工厂模式的问题(不好扩展,单个类任务繁重),但是它本身也是有缺点的;
就是工厂方法模式中,一个工厂子类只负责生产一种产品,所以后期增加产品时,会导致工厂类过多;
这时就需要将产品进行一个简单的分类(按特定的属性分类,比如按材质分类):比如木头椅子,全都让一个厂去做;塑料椅子,让另一个厂去做。
然后每个材质的椅子,内部再按结构分类(小椅子,靠背椅);
这个就是抽象工厂模式的核心:将产品进行分类,然后分配到不同的工厂子类中。
下面这个例子是先按照材质进行大的分类,再按照结构进行小的分类:
package pattern.factory.abstract1;/** * 抽象工厂模式:将工厂类抽象出来,再把产品分类,每个子工厂生产特定类型的产品 * * 是工厂方法模式的升级版,工厂方法模式是一个工厂只做一个产品,而抽象工厂模式是一个工厂做一类产品 */public class AbstractFactory { public static void main(String[] args) { // 木头 WoodChairFactory woodChairFactory = new WoodChairFactory(); woodChairFactory.orderSmallChair(); woodChairFactory.orderBackChair(); // 塑料 PlasticChairFactory plasticChairFactory = new PlasticChairFactory(); plasticChairFactory.orderSmallChair(); plasticChairFactory.orderBackChair(); }}interface ChairFactory{ void orderSmallChair(); void orderBackChair();}// 木头椅子 工厂class WoodChairFactory implements ChairFactory{ public WoodChair chair; @Override public void orderSmallChair() { chair = new WoodSmallChair(); chair.prepare(); chair.make(); chair.box(); } @Override public void orderBackChair() { chair = new WoodBackChair(); chair.prepare(); chair.make(); chair.box(); }}// 塑料椅子 工厂class PlasticChairFactory implements ChairFactory{ public PlasticChair chair; @Override public void orderSmallChair() { chair = new PlasticSmallChair(); chair.prepare(); chair.make(); chair.box(); } @Override public void orderBackChair() { chair = new PlasticBackChair(); chair.prepare(); chair.make(); chair.box(); }}abstract class Chair { public String type; // 木头/塑料 public String name; // 小椅子/靠背椅 public void prepare(){ System.out.println(type+name + "的制作步骤是:A,B,C"); } public void make(){ System.out.println(type+name + "制作中"); } public void box(){ System.out.println(type+name + "打包中"); }}// 木头椅class WoodChair extends Chair { public WoodChair() { this.type = "木头-"; }}class WoodSmallChair extends WoodChair{ public WoodSmallChair(){ this.name = "小椅子"; }}class WoodBackChair extends WoodChair{ public WoodBackChair(){ this.name = "靠背椅"; }}// 塑料椅class PlasticChair extends Chair { public PlasticChair() { this.type = "塑料-"; }}class PlasticSmallChair extends PlasticChair{ public PlasticSmallChair(){ this.name = "小椅子"; }}class PlasticBackChair extends PlasticChair{ public PlasticBackChair(){ this.name = "靠背椅"; }}
上面的这个抽象工厂模式的例子,虽然现在增加椅子的种类很方便了,只需要扩展一个椅子的子类就可以(比如铁的椅子,只需要创建 IronChair 继承 Chair就可以了);
但是缺点也很明显,细心的朋友可能发现了,就是如果想要增加其他结构的椅子,比如躺椅,那么就需要先改动 椅子工厂接口(增加躺椅的制作过程),再在每个实现工厂类中去实现。
总结
简单工厂模式,简单好用,缺点是不易扩展,违反了开闭原则;
工厂方法模式,可扩展,但是工厂类过多,会导致代码繁重;
抽象工厂模式,可扩展,工厂类也不会很多,但是这里的扩展只是种类层面的扩展,如果是结构层面的还是不易扩展,也会违反开闭原则。
这三种工厂模式都属于创建者型模式。