设计模式之工厂模式
工厂模式
工厂模式是Java中最常用的设计模式之一。它属于创建型模式,通过工厂方式来替代new操作,以封装和管理对象的创建。在Java中,工厂模式常被用于创建具有相同接口或基类的对象,但具有不同实现或配置的实例。
工厂模式可分为:简单/静态工厂模式、工厂方法模式、抽象工厂模式三种。本文将一一介绍三种工厂模式的应用场景及其优缺点。
为什么要用工厂模式?
首先,我没来理解一下什么场景下可以使用工厂模式,以及使用工厂模式后有何好处。
场景
假设,公司做一个电商系统,需要对接不同支付渠道,比如:支付宝支付、微信支付、银行卡卡扣、会员卡卡扣等等。当用户选择不同支付渠道时,系统需要通过不同渠道来进行支付,执行不同支付渠道的业务逻辑。
如果采用硬编码方式,我们只需要在支付时进行判断用户选择的渠道,并处理相关业务即可。当有新的支付渠道需要对接时,此时我们就需要继续添加条件判断,并在原代码写相关业务逻辑。
此时,不仅我们的代码显得臃肿,且在任意支付渠道业务产生变动而需要改动相关代码时,有可能影响到其他支付渠道业务逻辑,凭空增加了更多工作量和风险。这时候,如果我们使用合适的设计来规避这些问题,不仅代码显得美丽,降低耦合度,更让系统变得更加健壮。
1.简单/静态工厂模式
简单/静态工厂模式是最简单的模式,仅将对象创建进行了简单封装,通过向工厂传递类型来指定要创建的对象。
1.1 编写支付接口
public interface Pay {
String pay();
}
1.2 编写支付逻辑
public class AlipayPay implements Pay {
@Override
public String pay() {
return "调用阿里支付成功!";
}
}
public class WeChatPay implements Pay{
@Override
public String pay() {
return "调用微信支付成功!";
}
}
1.3 创建工厂
public class PayFactory {
public Pay pay(String channel) {
Pay pay = null;
if (Objects.equals("alipay", channel)){
pay = new AlipayPay();
} else if (Objects.equals("weChat", channel)){
pay = new WeChatPay();
}
return pay;
}
}
1.4 使用工厂来实现业务逻辑
public static void main(String[] args) {
PayFactory payFactory = new PayFactory();
Pay alipay = payFactory.pay("alipay");
String alipayResult = alipay.pay();
System.out.println(alipayResult); // 调用阿里支付成功!
Pay weChat = payFactory.pay("weChat");
String weChatResult = weChat.pay();
System.out.println(weChatResult); // 调用微信支付成功!
}
1.5 优缺点
优点:
- 简单易懂,代码量小
- 避免了调用方和实现方的耦合
缺点:
- 扩展性差,添加新的支付渠道,需要修改工厂方法及调用方代码,不符合开闭原则。
- 对象创建逻辑没有抽象化,可维护性差
- 当工厂出现bug时,整个逻辑将会崩溃
2 工厂方法模式
工厂方法模式进一步将对象的创建和使用进行解耦。它定义了一个工厂接口,不再提供统一工厂来创建所有产品,而是将负责生成具体产品的任务分发给具体的产品工厂。
2.1 抽象化工厂
public interface PayFactory {
Pay initPay();
}
2.2 实现业务工厂逻辑
public class AlipayPayFactory implements PayFactory{
@Override
public Pay initPay() {
return new AlipayPay();
}
}
public class WeChatPayFactory implements PayFactory{
@Override
public Pay initPay() {
return new WeChatPay();
}
}
2.3 使用
public static void main(String[] args) {
PayFactory alipayFactory = new AlipayPayFactory();
Pay alipay = alipayFactory.initPay();
String alipayResult = alipay.pay();
System.out.println(alipayResult);
PayFactory weChatFactory = new WeChatPayFactory();
Pay weChat = weChatFactory.initPay();
String weChatResult = weChat.pay();
System.out.println(weChatResult);
}
2.4 优缺点
优点:
- 扩展性好:添加新的支付渠道时增加新的工厂类即可,不改变原有代码。符合开闭原则。
缺点:
- 代码量增大:需要定义工厂接口和实现类。
- 如果工厂类很多,代码结构变得复杂。
3 抽象工厂模式
抽象工厂为创建一组相关或相互依赖的对象提供一个接口,而且无需指定他们的具体类。通过抽象工厂模式,将客户端与具体的创建过程解耦,使得客户端可以通过工厂接口来创建一族产品。
例如:当调用支付后,我们要查询支付结果,此时需要先定义一个结果查询接口,并依次实现各渠道查询逻辑;当调用某一渠道支付业务后,稍后需要查询当前渠道的支付结果,而不能查询到其他渠道。
在这个例子中,支付和结果查询两个业务是相互匹配绑定的,不能出现交叉的情况。
3.1 定义查询支付结果接口
public interface Result {
String result();
}
3.2 实现查询逻辑
public class AlipayResult implements Result{
@Override
public String result() {
return "通过阿里支付付款成功!";
}
}
public class WeChatResult implements Result{
@Override
public String result() {
return "通过微信支付付款成功!";
}
}
3.3 定义抽象工厂类
public abstract class AbstractFactory {
public abstract Pay pay();
public abstract Result result();
}
3.4 实现工厂逻辑
public class AlipayFactory extends AbstractFactory{
@Override
public Pay pay() {
return new AlipayPay();
}
@Override
public Result result() {
return new AlipayResult();
}
}
public class WeChatFactory extends AbstractFactory{
@Override
public Pay pay() {
return new WeChatPay();
}
@Override
public Result result() {
return new WeChatResult();
}
}
3.5 使用
public static void main(String[] args) {
AbstractFactory alipayFactory = new AlipayFactory();
Pay alipay = alipayFactory.pay();
String pay = alipay.pay();
Result alipayResult = alipayFactory.result();
String result = alipayResult.result();
System.out.println(pay); // 调用阿里支付成功!
System.out.println(result); // 通过阿里支付付款成功!
AbstractFactory weChatFactory = new WeChatFactory();
Pay weChat = weChatFactory.pay();
String pay2 = weChat.pay();
Result weChatResult = weChatFactory.result();
String result2 = weChatResult.result();
System.out.println(pay2); // 调用微信支付成功!
System.out.println(result2); // 通过微信支付付款成功!
}
3.6 优缺点:
优点:
- 当一个产品族中多个对象被设计成一起工作时,他能保证客户端始终只使用同一个产品族中的对象。
- 当增加新的支付渠道时,只需要实现当前业务逻辑即可。
缺点:
- 产品族扩展困难,要增加族中产品时,既要抽象创建代码,又要实现具体代码。因此适合业务稳定,不会频繁增减业务的场景。
例如:支付接口改版为先下单,下单成功再支付,然后再获取支付结果,那么所有的产品族都需要改动。
- 本文标签: 设计模式 java
- 本文链接: https://www.58cto.cn/article/12
- 版权声明: 本文由程序言原创发布, 非商业性可自由转载、引用,但需署名作者且注明文章出处:程序言 》 设计模式之工厂模式 - https://www.58cto.cn/article/12