工厂模式

![](https://ss2.bdstatic.com/70cFvnSh_Q1YnxGkpoWK1HF6hhy/it/u=2616924884,1918105240&fm=26&gp=0.jpg) ## Java泛型 > 个人技术博客(IBLi) [CSDN](https://blog.csdn.net/IBLiplus) [Github](https://github.com/GaoLeiplus/javaDancer) [掘金](https://juejin.im/user/4424090522228919) > ## 简单工厂模式 > 简单工厂模式是指有一个工厂对象决定创建出哪一个产品类的实例;属于创建型模式,但它不属于GOF 23种设计模式。 UML类图 ![](https://oscimg.oschina.net/oscnet/up-2e06fcc599aa2313d88c542a32a125934fc.png) > 组成要素 1、一个抽象产品类 2、具体产品类 3、一个工厂 肥宅喜爱的各种快乐水(产品接口) ```java public interface Kls { String name(); } ``` 肥宅快乐水-可乐(具体产品) ```java public class Coke implements Kls { @Override public String name() { return "肥宅快乐水-可乐"; } } ``` 快乐水-雪碧(具体产品) ```java public class Sprite implements Kls { @Override public String name() { return "快乐水-雪碧"; } } ``` 快乐水生产工厂(工厂类) ```java public class KlsFactory { public static Kls getFzs(String type) throws Exception { Kls fzs = null; if ("coke".equalsIgnoreCase(type)) { fzs = new Coke(); } else if ("sprite".equalsIgnoreCase(type)) { fzs = new Sprite(); } if (Objects.isNull(fzs)) { throw new RuntimeException("没找到快乐水~"); } return fzs; } } ``` 客户端使用 ```java public class Fz { @Test public void drink() throws Exception { // 制造可乐 Kls coke = KlsFactory.getFzs("coke"); System.out.println("肥宅开始喝:" + coke.name()); // 制造雪碧 Kls sprite = KlsFactory.getFzs("sprite"); System.out.println("肥宅开始喝:" + sprite.name()); } } ``` ### 简单工厂优缺点 > 优点 - 对客户端隐藏的具体的实现,客户端只需要知道要创建什么对象即可,不用关心对象是怎么创建的 - 解耦,客户端不需要通过new来创建对象,如果后期产品类需要修改,则只需要修改工厂类即可,不用整个项目遍地去寻找哪里有new > 缺点 - 由一个专门的工厂负责生产,如果业务变得复杂,这个类将变得十分臃肿 - 工厂类生产什么产品都是写死在工厂中的,如果增加新的产品,还要修改工厂类的生产逻辑 ## 工厂方法模式 工厂方法模式(Factory Method)是简单工厂的仅一步深化, 在工厂方法模式中,我们不再提供一个统一的工厂类来创建所有的对象,而是针对不同的对象提供不同的工厂。也就是说每个对象都有一个与之对应的工厂。 ![](https://oscimg.oschina.net/oscnet/up-11fa4bfb1062c445c055e49bc1d00b7d9cf.png) > 组成要素 1、一个抽象产品类 2、多个具体产品类 3、一个抽象工厂 4、多个具体工厂 - 每一个具体产品对应一个具体工厂 5、符合 - OCP开放封闭原则 接着上面快乐水的例子。将 快乐水工厂 (KlsFactory) 抽象出共有方法,再分别实现具体的快乐水生产工厂。 快乐水总工厂 ```java public interface Factory { /** * 制造快乐水 * * @return Kls */ Kls create(); } ``` 可乐工厂 ```java public class CokeFactory implements Factory { @Override public Kls create() { return new Coke(); } } ``` 雪碧工厂 ```java public class SpriteFactory implements Factory { @Override public Kls create() { return new Sprite(); } } ``` 肥宅(客户端) ```java public class Fz { @Test public void drink() throws Exception { // 制造可乐 CokeFactory cokeFactory = new CokeFactory(); Kls coke = cokeFactory.create(); System.out.println("肥宅开始喝:" + coke.name()); // 制造雪碧 SpriteFactory spriteFactory = new SpriteFactory(); Kls sprite = spriteFactory.create(); System.out.println("肥宅开始喝:" + sprite.name()); } } ``` 扩展芬达快乐水 ```java public class Fanta implements Kls { @Override public String name() { return "快乐水-芬达"; } } ``` 复制代码芬达工厂 ```java public class FantaFactory implements Factory { @Override public Kls create() { return new Fanta(); } } ``` 肥宅使用添加 ``` FantaFactory fantaFactory = new FantaFactory(); Kls fanta = fantaFactory.create(); System.out.println("肥宅开始喝:" + fanta.name()); ``` ### 工厂方法模式优缺点 >优点 1、降低了代码耦合度,对象的生成交给子类去完成(这里的耦合度是相对于简单工厂模式的工厂类比较的) 2、降低了代码耦合度,对象的生成交给子类去完成 >缺点 1、增加了代码量,每个具体产品都需要一个具体工厂(在具体的业务中可能会产生大量的重复代码) 2、当增加抽象产品 也就是添加一个其他产品族 需要修改工厂 违背OCP ## 抽象工厂模式 ![](https://oscimg.oschina.net/oscnet/up-9121de8d650bac2739bb7ad27f1f4174a0c.png) > 组成要素 1、多个抽象产品类 2、具体产品类 3、抽象工厂类 - 声明(一组)返回抽象产品的方法 4、具体工厂类 - 生成(一组)具体产品 一个抽象产品类和两个具体的产品(可乐) ```java public abstract class Coke { public abstract void doCreate(); } public class LocalCoke extends Coke{ @Override public void doCreate() { System.err.println("生产本土可乐"); } } public class ForeignCoke extends Coke{ @Override public void doCreate() { System.out.println("生产外国可乐"); } } ``` 一个抽象产品类和两个具体的产品(雪碧) ```java public abstract class Sprite { public abstract void doCreate(); } public class LocalSprite extends Sprite{ @Override public void doCreate() { System.out.println("生产本地雪碧"); } } public class ForeignSprite extends Sprite{ @Override public void doCreate() { System.err.println("生产外国雪碧"); } } ``` 一个抽象工厂和两个具体的工厂 ```java public interface IAbstractFactory { /** * 成产可乐 * * @return 声明(一组)返回抽象产品的方法 */ Coke createCoke(); /** * 生产雪碧 * * @return 声明(一组)返回抽象产品的方法 */ Sprite createSprite(); } public class LocalFactory implements IAbstractFactory{ /** * 成产可乐 * * @return 生成(一组)具体产品 */ @Override public LocalCoke createCoke() { return new LocalCoke(); } /** * 生产雪碧 * * @return 生成(一组)具体产品 */ @Override public LocalSprite createSprite() { return new LocalSprite(); } } public class ForeignFactory implements IAbstractFactory{ /** * 成产可乐 * * @return 生成(一组)具体产品 */ @Override public ForeignCoke createCoke() { return new ForeignCoke(); } /** * 生产雪碧 * * @return 生成(一组)具体产品 */ @Override public ForeignSprite createSprite() { return new ForeignSprite(); } } ``` ### 抽象工厂的使用 ```java public class FactoryTest { public static void main(String[] args) { LocalFactory localFactory = new LocalFactory(); LocalCoke localCoke = localFactory.createCoke(); localCoke.doCreate(); ForeignFactory foreignFactory = new ForeignFactory(); ForeignSprite foreignSprite = foreignFactory.createSprite(); foreignSprite.doCreate(); } } ``` ### 抽象工厂的优缺点 > 优点 1、代码解耦 2、很好的满足OCP开放封闭原则 3、抽象工厂模式中我们可以定义实现不止一个接口,一个工厂也可以生成不止一个产品类 对于复杂对象的生产相当灵活易扩展 (相对于工厂方法模式的优化) > 缺点 1、扩展产品是需要修改所有工厂,违反违反OCP原则 2、整体实现也比较复杂 ## 参考文章 > - [设计模式-简单工厂、工厂方法模式、抽象工厂模式](https://juejin.im/post/6844903650641330189) > - [设计模式 —— 工厂模式](https://juejin.im/post/6844903780819927054) <br> > <p align="middle" > 还有多少个十年 继续做热血少年 </p>