#yyds干货盘点#设计模式之工厂模式

少年恃险若平地,独倚长剑凌清秋。这篇文章主要讲述#yyds干货盘点#设计模式之工厂模式相关的知识,希望能为你提供帮助。
作者:汤圆
个人博客: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就可以了);
但是缺点也很明显,细心的朋友可能发现了,就是如果想要增加其他结构的椅子,比如躺椅,那么就需要先改动 椅子工厂接口(增加躺椅的制作过程),再在每个实现工厂类中去实现。
总结简单工厂模式,简单好用,缺点是不易扩展,违反了开闭原则;
工厂方法模式,可扩展,但是工厂类过多,会导致代码繁重;
抽象工厂模式,可扩展,工厂类也不会很多,但是这里的扩展只是种类层面的扩展,如果是结构层面的还是不易扩展,也会违反开闭原则。
【#yyds干货盘点#设计模式之工厂模式】这三种工厂模式都属于创建者型模式。

    推荐阅读