简介
⼯⼚模式介绍
它提供了⼀种创建对象的最佳⽅式,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使⽤⼀个共同的接⼝来指向新创建的对象
举例
需要购买⼀辆⻋,不⽤管⻋辆如何组装,且可以购买不同类型的⽐如轿⻋、SUV、跑⻋,直接去4s店购买就⾏(4s店就是⼯⼚)
⼯⼚⽣产电脑,除了A品牌、还可以⽣产B、C、D品牌电脑
业务开发中,⽀付很常⻅,⾥⾯有统⼀下单和⽀付接⼝,具体的⽀付实现可以微信、⽀付宝、银⾏卡等
实现方式概念
简单⼯⼚模式:通过传⼊相关的类型来返回相应的类,这种⽅式⽐较单 ⼀,可扩展性相对较差
⼯⼚⽅法模式:通过实现类实现相应的⽅法来决定相应的返回结果,这种⽅式的可扩展性⽐较强
抽象⼯⼚模式:基于上述两种模式的拓展,且⽀持细化产品
应用场景
解耦:分离职责,把复杂对象的创建和使⽤的过程分开
复⽤代码 降低维护成本:
如果对象创建复杂且多处需⽤到,如果每处都进⾏编写,则很多重复代码,如果业务逻辑发⽣了改变,需⽤四处修改
使⽤⼯⼚模式统⼀创建,则只要修改⼯⼚类即可,降低成本
简单工厂模式
概念
⼜称静态⼯⼚⽅法, 可以根据参数的不同返回不同类的实例,专⻔定义⼀个类来负责创建其他类的实例,被创建的实例通常都具有共同的⽗类
由于⼯⼚⽅法是静态⽅法,可通过类名直接调⽤,⽽且只需要传⼊简单的参数即可
核心组成
Factory:⼯⼚类,简单⼯⼚模式的核⼼,它负责实现创建所有实例的内部逻辑
IProduct:抽象产品类,简单⼯⼚模式所创建的所有对象的⽗类,描述所有实例所共有的公共接⼝
Product:具体产品类,是简单⼯⼚模式的创建⽬标
实现步骤
创建抽象产品类,⾥⾯有产品的抽象⽅法,由具体的产品类去实现
创建具体产品类,继承了他们的⽗类,并实现具体⽅法
创建⼯⼚类,提供了⼀个静态⽅法createXXX⽤来⽣产产品,只需要传⼊你想产品名称
demo
创建抽象产品类
public interface Pay {
/**
* 统一下单
*/
void unifiedorder();
}
具体产品类
public class AliPay implements Pay {
@Override
public void unifiedorder() {
System.out.println("支付宝支付 统一下单接口");
}
}
具体产品类
public class WechatPay implements Pay {
@Override
public void unifiedorder() {
System.out.println("微信支付支付 统一下单接口");
}
}
创建工厂类
public class SimplePayFactory {
/**
* 根据参数 返回对应的支付对象
*
* @param payType
* @return
*/
public static Pay createPay(String payType) {
if (payType == null) {
return null;
} else if (payType.equalsIgnoreCase("WECHAT_PAY")) {
return new WechatPay();
} else if (payType.equalsIgnoreCase("ALI_PAY")) {
return new AliPay();
}
//想拓展,直接编写更多
return null;
}
}
调用
public class Main {
public static void main(String[] args) {
//Pay pay = SimplePayFactory.createPay("WECHAT_PAY");
Pay pay = SimplePayFactory.createPay("ALI_PAY");
pay.unifiedorder();
}
}
优点
将对象的创建和对象本身业务处理分离可以降低系统的耦合度,使得两者修改起来都相对容易
缺点
⼯⼚类的职责相对过重,增加新的产品需要修改⼯⼚类的判断逻辑,这⼀点与开闭原则是相违背
即开闭原则(Open Close Principle)对扩展开放,对修改关闭,程序需要进⾏拓展的时候,不能去修改原有的代码,实现⼀个热插拔的效果
将会增加系统中类的个数,在⼀定程度上增加了系统的复杂度和理解难度,不利于系统的扩展和维护,创建简单对象就不⽤模式
工厂方法模式
概念
⼜称⼯⼚模式,是对简单⼯⼚模式的进⼀步抽象化,其好处是可以使系统在不修改原来代码的情况下引进新的产品,即满⾜开闭原则
通过⼯⼚⽗类定义负责创建产品的公共接⼝,通过⼦类来确定所需要创建的类型
相⽐简单⼯⼚⽽⾔,此种⽅法具有更多的可扩展性和复⽤性,同时也增强了代码的可读性
将类的实例化(具体产品的创建)延迟到⼯⼚类的⼦类(具体⼯⼚)中完成,即由⼦类来决定应该实例化哪⼀个类
核心组成
IProduct:抽象产品类,描述所有实例所共有的公共接⼝
Product:具体产品类,实现抽象产品类的接⼝,⼯⼚类创建对象,如果有多个需要定义多个
IFactory:抽象⼯⼚类,描述具体⼯⼚的公共接⼝
Factory:具体⼯场类,实现创建产品类对象,实现抽象⼯⼚类的接⼝,如果有多个需要定义多个
图片介绍
demo
创建抽象产品类
public interface Pay {
/**
* 统一下单
*/
void unifiedorder();
}
具体产品类
public class AliPay implements Pay {
@Override
public void unifiedorder() {
System.out.println("支付宝支付 统一下单接口");
}
}
具体产品类
public class WechatPay implements Pay {
@Override
public void unifiedorder() {
System.out.println("微信支付支付 统一下单接口");
}
}
创建抽象工厂类
/**
* 抽象工厂方法
*/
public interface PayFactory {
Pay getPay();
}
具体工厂类
public class AliPayFactory implements PayFactory {
@Override
public Pay getPay() {
return new AliPay();
}
}
具体工厂类
public class WechatPayFactory implements PayFactory {
@Override
public Pay getPay() {
return new WechatPay();
}
}
调用
public class Main {
public static void main(String[] args) {
PayFactory aliPayFactory = new AliPayFactory();
Pay aliPay = aliPayFactory.getPay();
aliPay.unifiedorder();
PayFactory wechatPayFactory = new WechatPayFactory();
Pay wechatPay = wechatPayFactory.getPay();
wechatPay.unifiedorder();
}
}
优点
符合开闭原则,增加⼀个产品类,只需要实现其他具体的产品类和具体的⼯⼚类
符合单⼀职责原则,每个⼯⼚只负责⽣产对应的产品
使⽤者只需要知道产品的抽象类,⽆须关⼼其他实现类,满⾜迪⽶特法则、依赖倒置原则和⾥⽒替换原则
迪⽶特法则:最少知道原则,实体应当尽量少地与其他实体之间发⽣相互作⽤
依赖倒置原则:针对接⼝编程,依赖于抽象⽽不依赖于具体
⾥⽒替换原则:俗称LSP, 任何基类可以出现的地⽅,⼦类⼀定可以出现, 对实现抽象化的具体步骤的规范
缺点
增加⼀个产品,需要实现对应的具体⼯⼚类和具体产品类
每个产品需要有对应的具体⼯⼚和具体产品类
抽象工厂方法模式
概念
简单⼯⼚模式:通过传⼊相关的类型来返回相应的类,这种⽅式⽐较单 ⼀,可扩展性相对较差;
⼯⼚⽅法模式:通过实现类实现相应的⽅法来决定相应的返回结果,这种⽅式的可扩展性⽐较强;
抽象⼯⼚模式:基于上述两种模式的拓展,是⼯⼚⽅法模式的升级版,当需要创建的产品有多个产品线时使⽤抽象⼯⼚模式是⽐较好的选择
抽象⼯⼚模式在 Spring 中应⽤得最为⼴泛的⼀种设计模式
背景
⼯⼚⽅法模式引⼊⼯⼚等级结构,解决了简单⼯⼚模式中⼯⼚类职责过重的问题
但⼯⼚⽅法模式中每个⼯⼚只创建⼀类具体类的对象,后续发展可能会导致⼯⼚类过多,因此将⼀些相关的具体类组成⼀个“具体类族”,由同⼀个⼯⼚来统⼀⽣产,强调的是⼀系列相关的产品对象!!!
图片介绍
核心组成
1、定义两个接⼝ Pay(付款)、Refund(退款)
2、创建具体的Pay产品、创建具体的Refund产品
3、创建抽象⼯⼚ OrderFactory 接⼝⾥⾯两个⽅法 createPay/createRefund
4、创建⽀付宝产品族AliOderFactory,实现OrderFactory抽象⼯⼚
5、创建微信⽀付产品族WechatOderFactory,实现OrderFactory抽象⼯⼚
6、定义⼀个超级⼯⼚创造器,通过传递参数获取对应的⼯⼚
demo
定义Pay(付款)、Refund(退款)两个接口
public interface PayFactory {
/**
* 统一下单
*/
void unifiedorder();
}
public interface RefundFactory {
/**
* 退款
*/
void refund();
}
创建具体的Pay产品、创建具体的Refund产品
ali产品
public class AliPay implements PayFactory {
@Override
public void unifiedorder() {
System.out.println("支付宝支付 统一下单接口");
}
}
public class AliRefund implements RefundFactory {
@Override
public void refund() {
System.out.println("支付宝 退款");
}
}
wechat产品
public class WechatPay implements PayFactory {
@Override
public void unifiedorder() {
System.out.println("微信支付支付 统一下单接口");
}
}
public class WechatRefund implements RefundFactory {
@Override
public void refund() {
System.out.println("微信支付 退款");
}
}
创建抽象⼯⼚ OrderFactory 接⼝⾥⾯两个⽅法 createPay/createRefund
public interface OrderFactory {
PayFactory createPay();
RefundFactory createRefund();
}
创建⽀付宝和微信支付产品族AliOderFactory/WechatOderFactory,实现OrderFactory抽象⼯⼚
public class AliOrderFactory implements OrderFactory {
@Override
public PayFactory createPay() {
return new AliPay();
}
@Override
public RefundFactory createRefund() {
return new AliRefund();
}
}
public class WechatOrderFactory implements OrderFactory {
@Override
public PayFactory createPay() {
return new WechatPay();
}
@Override
public RefundFactory createRefund() {
return new WechatRefund();
}
}
定义⼀个超级⼯⼚创造器,通过传递参数获取对应的⼯⼚
public class FactoryProducer {
public static OrderFactory getFactory(String type) {
if (type.equalsIgnoreCase("WECHAT")) {
return new WechatOrderFactory();
} else if (type.equalsIgnoreCase("ALI")) {
return new AliOrderFactory();
}
return null;
}
}
调用
public class Main {
public static void main(String[] args) {
OrderFactory orderFactory = FactoryProducer.getFactory("ALI");
orderFactory.createPay().unifiedorder();
orderFactory.createRefund().refund();
}
}
工厂方法模式跟抽象方法模式的关系
当抽象⼯⼚模式中每⼀个具体⼯⼚类只创建⼀个产品对象,抽象⼯⼚模式退化成⼯⼚⽅法模式
优点
当⼀个产品族中的多个对象被设计成⼀起⼯作时,它能保证使⽤⽅始终只使⽤同⼀个产品族中的对象
产品等级结构扩展容易,如果需要增加多⼀个产品等级,只需要增加新的⼯⼚类和产品类即可, ⽐如增加银⾏⽀付、退款
缺点
产品族扩展困难,要增加⼀个系列的某⼀产品,既要在抽象的⼯⼚和抽象产品⾥修改代码,不是很符合开闭原则
增加了系统的抽象性和理解难度