1.工厂模式概念介绍
-
它提供了一种创建对象的最佳方式,我们在创建对象时,不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象
-
3种实现方式
- 简单工厂模式:通过传入相关的类型来返回对应的类,这种方式比较单一,可扩展性相对较差
- 工厂方法模式:通过实现类实现对应的方法来决定相应的返回结果,这种方式的可扩展项比较强
- 抽象工厂模式:基于上述两种模式的扩展,是工厂方法模式的升级版,当需要创建的产品有多个产品线时使用,抽象工厂模式是比较好的选择;抽象工厂模式是Spring中应用最为广泛的一种设计模式
-
优点
- 解耦:分离职责,把复杂对象的创建和使用的过程分开
- 复用代码,降低维护成本
-
应用场景
- 支付:统一下单和支付接口,具体支付实现可以微信、支付宝、银行卡等
2.简单工厂模式
-
简单工厂模式
- 又称静态工厂方法,可以根据参数的不同返回不同类的实例,专门定义一个类来负责创建其他类的实例,被创建的实例通常都具有共同的父类
- 由于工厂方法是静态方法,可通过类名直接调用,而且只需要传入简单的参数即可
-
核心组成
- Factory:工厂类,简单工厂模式的核心,它负责实现创建所有实例的内部逻辑
- IProduct:抽象产品类,简单工厂模式所创建的所有对象的父类,描述所有实例所共有的公共接口
- Product:具体产品类,是简单工厂模式的创建目标
-
优点
- 将对象的创建和对象本身业务处理分离,可以降低系统的耦合度,使得两者修改起来都相对容易
-
缺点
- 工厂类的职责相对过重,增加新的产品需要修改工厂类的判断逻辑,这一点与开闭原则相违背
- 开闭原则(Open Close Principle):对扩展开放,对修改关闭,在程序需要进行扩展的时候,不能去修改原有的代码,实现一个热插拔的效果
- 将会增加系统中类的个数,在一定程度上增加了系统的复杂度和理解难度,不利于系统的扩展和维护,对象创建简单不建议使用工厂模式
-
代码示例
/** * 接口:定义规范 */ interface Pay { /** * 统一下单方法 */ void unifiedOrder(); } /** * 支付宝 */ class AliPay implements Pay { @Override public void unifiedOrder() { System.out.println("支付宝支付"); } } /** * 微信支付 */ class WechatPay implements Pay { @Override public void unifiedOrder() { System.out.println("微信支付"); } } /** * 简单工厂模式 */ class SimplePayFactory { /** * 根据参数,返回对应的支付对象 * * @param payType * @return */ public static Pay createPay(String payType) { if ("ALI_PAY".equalsIgnoreCase(payType)) { return new AliPay(); } else if ("WECHAT_PAY".equalsIgnoreCase(payType)) { return new WechatPay(); } // TODO: 拓展时,增加if-else语句 return null; } } public class Main { public static void main(String[] args) { SimplePayFactory.createPay("WECHAT_PAY").unifiedOrder(); } }
3.工厂方法模式
-
工厂方法模式
- 又称工厂模式,是对简单工厂模式的进一步抽象化,其好处是可以使系统在不修改原来代码的情况下引进新的产品,即满足开闭原则
- 通过工厂父类定义负责创建产品的公共接口,通过子类来确定所需要创建的类型
- 相比简单工厂而言,此种方法具有更多的可扩展性和复用性,同时也增强了代码的可读性
- 将类的实例化(具体产品的创建)延迟到工厂类的子类(具体工厂)中完成,即由子类来决定应该实例化哪一个类
-
核心组成
-
IProduct:抽象产品类,描述所有实例所共有的公共接口
-
Product:具体产品类,实现抽象产品类的接口,工厂类创建对象,如果有多个需要定义多个
-
IFactory:抽象工厂类,描述具体工厂的公共接口
-
Factory:具体工厂类,实现创建产品类对象,实现抽象工厂类的接口,如果有多个需要定义多个
-
-
优点
- 符合开闭原则,增加一个产品类,只需要实现其它具体的产品类和具体的工厂类
- 符合单一职责原则,每个工厂只负责生产对应的产品
- 使用者只需要知道产品的抽象类,无需关心其他实现类,满足迪米特法则、依赖倒置原则和里氏替换原则
- 迪米特法则:最少知道原则,实体应当尽量少地与其他实体之间发生相互作用
- 依赖倒置原则:针对接口编程,依赖于抽象而不依赖于具体
- 里氏替换原则:俗称LSP,任何基类可以出现的地方,子类一定可以出现,对实现抽象化的具体步骤的规范
-
缺点
- 增加一个产品,需要实现对应的具体工厂类和具体产品类
- 每个产品需要对应的具体工厂和具体产品类
-
代码示例
/** * 接口:定义规范 */ interface Pay { /** * 统一下单方法 */ void unifiedOrder(); } /** * 支付宝 */ class AliPay implements Pay { @Override public void unifiedOrder() { System.out.println("支付宝支付"); } } /** * 微信支付 */ class WechatPay implements Pay { @Override public void unifiedOrder() { System.out.println("微信支付"); } } /** * 抽象工厂方法 */ interface PayFactory { Pay getPay(); } class AliPayFactory implements PayFactory { @Override public Pay getPay() { return new AliPay(); } } class WechatPayFactory implements PayFactory { @Override public Pay getPay() { return new WechatPay(); } } public class Main { public static void main(String[] args) { new AliPayFactory().getPay().unifiedOrder(); new WechatPayFactory().getPay().unifiedOrder(); } }
4.抽象工厂模式
-
背景
- 工厂方法模式引入工厂等级结构,解决了简单工厂模式中工厂类职责过重的问题
- 但工厂方法模式中每个工厂只创建一类具体类的对象,后续发展可能会导致工厂类过多,因此将一些相关的具体类组成一个“具体类族”,由同一个工厂来统一生产,强调的是一系列相关的产品对象
-
优点
- 当一个产品族中的多个对象被设计成一起工作时,它能保证使用方始终只使用同一个产品族中的对象
- 产品等级结构扩展容易,如果需要增加多一个产品等级,只需要增加新的工厂类和产品类即可,比如增加银行支付、退款
-
缺点
- 产品族扩展困难,要增加一个系列的某一产品,既要在抽象的工厂和抽象产品里修改代码,不是很符合开闭原则
- 增加了系统的抽象性和理解难度
-
代码示例
/** * 超级工厂,定义同个产品族的其他相关子工厂 */ interface OrderFactory { PayFactory createPay(); RefundFactory createRefund(); } /** * 支付抽象接口 */ interface PayFactory { void unifiedOrder(); } /** * 退款抽象接口 */ interface RefundFactory { void refund(); } /** * 支付宝支付 */ class AliPay implements PayFactory { @Override public void unifiedOrder() { System.out.println("支付宝支付"); } } /** * 支付宝退款 */ class AliRefund implements RefundFactory { @Override public void refund() { System.out.println("支付宝退款"); } } /** * 微信支付 */ class WechatPay implements PayFactory { @Override public void unifiedOrder() { System.out.println("微信支付"); } } /** * 微信退款 */ class WechatRefund implements RefundFactory { @Override public void refund() { System.out.println("微信退款"); } } /** * 产品族工厂 */ class AliOrderFactory implements OrderFactory { @Override public PayFactory createPay() { return new AliPay(); } @Override public RefundFactory createRefund() { return new AliRefund(); } } /** * 产品族工厂 */ class WechatOrderFactory implements OrderFactory { @Override public PayFactory createPay() { return new WechatPay(); } @Override public RefundFactory createRefund() { return new WechatRefund(); } } /** * 超级工厂生产器,简单工厂模式 */ class FactoryProducer { public static OrderFactory createFactory(String type) { if ("ALI".equalsIgnoreCase(type)) { return new AliOrderFactory(); } else if ("WECHAT".equalsIgnoreCase(type)) { return new WechatOrderFactory(); } return null; } } public class Main { public static void main(String[] args) { OrderFactory ali = FactoryProducer.createFactory("ALI"); ali.createPay().unifiedOrder(); ali.createRefund().refund(); OrderFactory wechat = FactoryProducer.createFactory("WECHAT"); wechat.createPay().unifiedOrder(); wechat.createRefund().refund(); } }