小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。
一、介绍
简单工厂模式是一种创建型的设计模式,又叫做静态工厂方法模式。简单工厂模式定义了产品(要创建的对象)和工厂(创建对象的类),其中产品又分为了抽象产品(描述了所有创建对象共同点的接口)和具体产品(具体创建出的对象实例),并由工厂对象决定创建出对象的具体类型。但是每次新增一种类型的产品时都需要去修改工厂类,因此简单工厂模式并不符合开闭原则。
二、结构
简单工厂模式有三部分组成:
-
简单工厂:负责创建所有产品的逻辑。
-
抽象产品:负责定义所有产品的共有接口。
-
产品:简单工厂具体生产的产品。
简单工厂模式的结构图如下:
三、实例
拿日常生活中的支付为例,假设现在有银联支付、支付宝支付和微信支付三种支付方式。那么可以将支付方法抽取出来创建一个抽象产品,然后创建三个具体产品来实现抽象产品并重写支付方法实现自己的支付逻辑,最后创建一个简单工厂来负责控制创建三个抽象产品的逻辑。具体代码如下:
支付接口--抽象产品:
public interface Pay {
/**
* 支付方法
*/
void pay();
}
支付宝支付--具体产品:
public class AliPay implements Pay {
/**
* 支付方法
*/
@Override
public void pay() {
// 忽略支付逻辑
System.out.println("支付宝支付");
}
}
银联支付--具体产品:
public class UnionPay implements Pay {
/**
* 支付方法
*/
@Override
public void pay() {
// 忽略支付逻辑
System.out.println("银联支付");
}
}
微信支付--具体产品:
public class WeChatPay implements Pay {
/**
* 支付方法
*/
@Override
public void pay() {
// 忽略支付逻辑
System.out.println("微信支付");
}
}
支付方式创建工厂--简单工厂
public class PayFactory {
/**
* 支付宝支付类型
*/
public static final String ALIPAY_TYPE = "aliPay";
/**
* 微信支付类型
*/
public static final String WECHATPAY_TYPE = "weChatPay";
/**
* 银联支付类型
*/
public static final String UNIONPAY_TYPE = "unionPay";
/**
* 创建具体产品
*
* @param payType 支付方式类型
* @return 具体产品
*/
public static Pay createPay(String payType) {
switch (payType) {
case ALIPAY_TYPE:
return new AliPay();
case WECHATPAY_TYPE:
return new WeChatPay();
case UNIONPAY_TYPE:
return new UnionPay();
default:
throw new RuntimeException("未找到支付类型");
}
}
}
测试类
public class Test {
public static void main(String[] args) {
PayFactory.createPay(PayFactory.ALIPAY_TYPE).pay();
}
}
四、拓展
1. 多个工厂方法
工厂类可以有多个工厂方法来创建不同的具体产品,例如:
java.text.DateFormat:
public final static DateFormat getTimeInstance()
public final static DateFormat getTimeInstance(int style)
public final static DateFormat getTimeInstance(int style, Locale aLocale)
public final static DateFormat getDateInstance()
public final static DateFormat getDateInstance(int style)
public final static DateFormat getDateInstance(int style, Locale aLocale)
public final static DateFormat getDateTimeInstance()
public final static DateFormat getDateTimeInstance(int dateStyle, int timeStyle)
public final static DateFormat getDateTimeInstance(int dateStyle, int timeStyle, Locale aLocale)
2. 省略抽象产品
如果系统仅有一个具体产品的情况下可以省略抽象产品,此时简单工厂中的工厂方法就是创建具体产品的方法。
3. 合并抽象产品和简单工厂
有时抽象产品也可以充当简单工厂角色,例如java.text.DateFormat
4. 合并三个角色
一个类也是创建自己的工厂,该类可以自行创建自己的实例。这种特殊的简单工厂模式和单例模式、多例模式有相似的地方。
5. 重复利用创建的产品
某些情况下,工厂可以不需要每次都创建新的产品,而是可以重复利用之前已经创建过的产品,工厂可以存储创建出的产品对象以供后续来重复使用。例如如果工厂一直重复使用一个产品对象,那么工厂就可以使用一个属性来存储这个产品对象这样就类似于单例模式了。
五、总结
1. 优点
简单工厂模式将工厂和产品的职责很好的区分开来,客户端无需考虑创建产品对象,可以更多的去关注如何使用产品。
2. 缺点
简单工厂类是该模式的核心,该类负责所有产品的创建,但是如果简单工厂类出了问题,那么会造成整个系统的瘫痪。简单工厂类的工厂方法是静态方法因此无法继承。新增产品类型时需要修改简单工厂类的源代码不符合开闭原则。