创建型模式之抽象工厂模式
1. 简介
抽象工厂模式(Abstract Factory Pattern)本质上是简单工厂模式和工厂方法模式的结合体。
简单工厂模式和工厂方法模式面向的创建单一对象, 而抽象工厂模式面向的多元化的产品, 提供多种对象的创建。
以服装举例来说,在很久之前,服装都是有用户自己在家里自产自;随着需求的提升,就有了专门的工厂来生产服装,也就有了简单工厂; 随着用户对服装个性化的差异性需求提升,简单工厂越做越大,实现将产品根据不同的款式由不同的工厂生产,总厂只负责定制服装的规范,这就有了工厂方法;但是随着人们对服装的要求越来越高,他们不满足衣服,现在还希望工厂生产鞋子、帽子等其他副产业,工厂再次扩容,不再生产单一的服装,还需要生产关于服装方面的多元化产品,这也就是抽象工厂模式。
2. 代码展示
场景描述:
支付服务商一般除了提供支付功能以外, 还需要提供支付的结果通知。这里工厂不但定义了支付服务的创建规范,还需要提供通知服务的创建规范。
2.1 类图
2.2 代码
PayService 支付服务基类
package com.inconspicuousy.pattern.simplefactory;
/**
* 支付基类
* @author inconspicuousy
*/
public interface PayService {
/** 支付 */
void doPay();
}
AliPayService 支付宝支付服务提供类
package com.inconspicuousy.pattern.simplefactory;
/**
* 支付宝支付
* @author inconspicuousy
*/
public class AliPayService implements PayService {
@Override
public void doPay() {
System.out.println("使用支付宝支付");
}
}
WeiXinPayService 微信支付服务提供类
package com.inconspicuousy.pattern.simplefactory;
/**
* 微信支付
* @author inconspicuousy
*/
public class WeiXinPayService implements PayService {
@Override
public void doPay() {
System.out.println("使用微信支付");
}
}
BaseNotifyService 通知服务基类
package com.inconspicuousy.pattern.abstractfactory;
/**
* 基础通知服务
* @author peng.yi
*/
public interface BaseNotifyService {
/** 通知服务 */
void doNotify();
}
SmsNotifyServiceImpl 短信通知服务提供类
package com.inconspicuousy.pattern.abstractfactory;
/**
* @author peng.yi
*/
public class SmsNotifyServiceImpl implements BaseNotifyService {
/**
* 通知服务
*/
@Override
public void doNotify() {
System.out.println("短信通知服务");
}
}
EmailNotifyServiceImpl 邮件通知服务提供类
package com.inconspicuousy.pattern.abstractfactory;
/**
* @author peng.yi
*/
public class EmailNotifyServiceImpl implements BaseNotifyService {
/**
* 通知服务
*/
@Override
public void doNotify() {
System.out.println("邮件通知服务");
}
}
BasePayServiceFactory 抽象工厂类
package com.inconspicuousy.pattern.abstractfactory;
import com.inconspicuousy.pattern.simplefactory.PayService;
import java.util.Objects;
/**
* @author peng.yi
*/
public interface BasePayServiceFactory {
String TYPE_SMS = "SMS";
String TYPE_EMAIl = "EMAIL";
/**
* 获取通知服务对象, 这里采用简单工厂的方式用于创建对象
*/
default BaseNotifyService createNotifyService(String type) {
if (Objects.isNull(type)) {
return null;
}
switch (type) {
case TYPE_SMS:
return new SmsNotifyServiceImpl();
case TYPE_EMAIl:
return new EmailNotifyServiceImpl();
default:
return null;
}
}
/** 获取支付服务对象(提供规范, 实现由子工厂实现), 这里采用工厂方法创建对象 */
PayService createPayService();
}
AliPayServiceFactory 支付宝支付服务工厂类,默认就继承来自于父类的通知服务提供工厂。
package com.inconspicuousy.pattern.abstractfactory;
import com.inconspicuousy.pattern.simplefactory.AliPayService;
import com.inconspicuousy.pattern.simplefactory.PayService;
/**
* @author peng.yi
*/
public class AliPayServiceFactory implements BasePayServiceFactory {
/**
* 获取支付服务对象(提供规范, 实现由子工厂实现), 这里采用工厂方法创建对象
*/
@Override
public PayService createPayService() {
return new AliPayService();
}
}
WxPayServiceFactory 微信支付服务工厂类,默认就继承于父类的通知服务提供工厂。
package com.inconspicuousy.pattern.abstractfactory;
import com.inconspicuousy.pattern.simplefactory.PayService;
import com.inconspicuousy.pattern.simplefactory.WeiXinPayService;
/**
* @author peng.yi
*/
public class WxPayServiceFactory implements BasePayServiceFactory {
/**
* 获取支付服务对象(提供规范, 实现由子工厂实现), 这里采用工厂方法创建对象
*/
@Override
public PayService createPayService() {
return new WeiXinPayService();
}
}
2.3 测试
2.3.1 Story 测试类
package com.inconspicuousy.pattern.abstractfactory;
import com.inconspicuousy.pattern.simplefactory.PayService;
/**
*
* 商店, 具体的测试类
* @author peng.yi
*/
public class Story {
public static void main(String[] args) {
// 商店采用支付宝并采用短信的方式进行通知
BasePayServiceFactory aliPayServiceFactory = new AliPayServiceFactory();
PayService payService = aliPayServiceFactory.createPayService();
payService.doPay();
BaseNotifyService notifyService = aliPayServiceFactory.createNotifyService(BasePayServiceFactory.TYPE_SMS);
notifyService.doNotify();
}
}
2.3.2 测试结果
使用支付宝支付
短信通知服务
Process finished with exit code 0
3. 优点
封装性
- 客户端直接使用对应的工厂就可以获取到对应的对象,而无须关心对象是怎么生成的。可扩展性
- 当增加新产品时只需要修改抽象工厂和增加对应的产品工厂类即可,面对客户来说不需要修改任何代码,满足开闭原则
。
4. 缺点
开闭原则的倾斜性
- 添加新的产品只需要添加对应的产品工厂即可,但是对于添加新的服务,就需要修改抽象工厂,添加新的方法,这样会影响所有的子工厂。