定义: 定义了一个创建对象的类,由这个类来封装实例化对象的行为。
优点:
①产品的创建交给了工厂类,客户端无需自己创建产品,只需要提供对应的参数。工厂和产品的职责区分明确。
②客户端无需知道所创建具体产品的类名,只需知道参数即可。
③也可以引入配置文件(比如解析XML等),在不修改客户端代码的情况下更换和添加新的具体产品类。
缺点:
①工厂类单一,负责所有产品的创建,职责过重,一旦异常,整个系统将受影响。且工厂类代码会非常臃肿,违背高内聚责任分配原则。
②使用简单工厂模式会增加系统中类的个数(引入新的工厂类),增加系统的复杂度和理解难度。
③类的创建依赖工厂类,系统扩展困难,增加新的产品后必须修改工厂类,这违背了“开闭原则”
④简单工厂模式使用了 static 工厂方法,造成工厂角色无法形成基于继承的等级结构。
应用场景
①工厂类负责创建的对象比较少
②客户端只知道传入工厂类的参数,对于如何创建对象不关心
③具体工厂产品不会频繁改动
**典型案例:**Spring 中的 BeanFactory 的 getBean() 方法
// 基于读取配置类的形式定义Bean信息
// 通过@Bean的形式是使用的话, bean的默认名称是方法名,若@Bean(value="bean的名称") 那么bean的名称是指定的
AnnotationConfigApplicationContext atx = new AnnotationConfigApplicationContext(MainConfig.class);
atx.getBean("car1");
使用案例
收银案例,根据不同支付方式,选择不同支付渠道用户每次下单完成后,付款时会根据自身情况选择不同支付方式,后台服务会根据用户选中不同创建不同支付渠道的实例,这里创建支付渠道的实例可以采用工厂方法模式。真正使用时部分参数可以配置化进行,使用实例也可以根据参数配置从 Spring 容器中去获取无需 new 对象,代码量将大大减少,此处仅模拟支付场景,简易实现。
支付渠道(产品)
/**
* 支付渠道
*/
public abstract class PayChannel {
/**
* 付款
*/
abstract void pay();
}
具体支付方式(具体产品)
/**
* 支付宝支付
*/
public class AlipayPay extends PayChannel {
@Override
public void pay() {
System.out.println("支付宝支付成功!");
}
}
/**
* 银行卡支付
*/
public class BankPay extends PayChannel {
@Override
public void pay() {
System.out.println("银行卡支付成功!");
}
}
/**
* 微信支付
*/
public class WeChatPay extends PayChannel {
@Override
public void pay() {
System.out.println("微信支付成功!");
}
}
工厂类
/**
* 支付渠道实例化工厂
*/
public class PayChannelFactory {
public static PayChannel creatChannel(String type) {
if ("AlipayPay".equals(type)) {
return new AlipayPay();
} else if ("BankPay".equals(type)) {
return new BankPay();
} else if ("WeChatPay".equals(type)) {
return new BankPay();
}
return null;
}
}
客户端测试类
public class Test {
public static void main(String[] args) {
PayChannelFactory.creatChannel("AlipayPay").pay();
PayChannelFactory.creatChannel("BankPay").pay();
PayChannelFactory.creatChannel("WeChatPay").pay();
}
}
-------------------------------------
支付宝支付成功!
银行卡支付成功!
银行卡支付成功!