我们常说的工厂模式并不是一种具体的设计模式。在「GoF设计模式(23种经典设计模式)」里,具体的“工厂模式”是指:工厂方法模式(Factory Method Pattern)和抽象工厂模式(Abstract Factory Pattern)。但我们常把简单工厂模式(Simple Factory Pattern)、工厂方法模式、抽象工厂模式统一称为工厂模式。
简单工厂模式(Simple Factory Pattern)
简单工厂也叫静态工厂。简单工厂模式并不是一种设计模式,或者说它不在Gof归纳的设计模式里。它是我们的一种设计方法。当我们创建对象时,一般通过new的方式创建,而这种方式创建就是面向实现方式编程(当我们对象已经确定时,相关的功能就已经确定了)。
使用简单工厂模式创建对象的好处:
-
简单方便获取对象
-
可以使创建对象的细节与业务代码分割开来,封装并隐藏对象创建的细节
-
创建对象的方式修改了,只需要修改工厂里的方法,而不需要在每个调用方修改。
简单工厂方法实现起来,非常简单:
// 抽象产品接口
public interface IProduct {
void display();
}
//产品A
public class AProduct implements IProduct {
@Override
public void display() {
System.out.println("我是A产品");
}
}
// 产品B
public class BProduct implements IProduct {
@Override
public void display() {
System.out.println("我是B产品");
}
}
// 简单工厂
public class SimpleFactory {
public static IProduct createProduct(String type) {
if ("A".equals(type)) {
return new AProduct();
}
if ("B".equals(type)) {
return new BProduct();
}
return null;
}
public static void main(String[] args) {
// A产品
IProduct aProduct = SimpleFactory.createProduct("A");
aProduct.display();
// B产品
IProduct bProduct = SimpleFactory.createProduct("B");
bProduct.display();
}
}
输出结果:
我是A产品
我是B产品
简单工厂实现起来很简单,但也有一定弊端,主要是违法了开闭原则(对扩展开放,对修改关闭),当需要增加新的产品时,我们需要修改简单工厂里的静态方法。
工厂方法模式(Factory Method Pattern)
工厂方法模式(Factory Method Pattern):定义一个用于创建对象的接口,让子类决定将哪一个类实例化。工厂方法模式让一个类的实例化延迟到其子类。
工厂方法模式包含四种角色:抽象产品,具体产品,抽象工厂,具体工厂
具体产品(具体对象),由具体工厂方法创建。
用代码演示如下
// 抽象产品
public interface IProduct {
void display();
}
//具体产品A
public class AProduct implements IProduct {
@Override
public void display() {
System.out.println("我是A产品");
}
}
// 具体产品B
public class BProduct implements IProduct {
@Override
public void display() {
System.out.println("我是B产品");
}
}
// 抽象工厂
public interface IProductFactory {
IProduct createProduct();
}
// 具体工厂A
public class ProductAFactory implements IProductFactory {
@Override
public IProduct createProduct() {
return new AProduct();
}
}
// 具体工厂B
public class ProductBFactory implements IProductFactory {
@Override
public IProduct createProduct() {
return new BProduct();
}
}
// 客户端演示
public class Client {
public static void main(String[] args) {
// A产品工厂
IProductFactory aProductFactory = new ProductAFactory();
// 创建A产品
IProduct aProduct = aProductFactory.createProduct();
aProduct.display();
// B产品工厂
IProductFactory bProductFactory = new ProductBFactory();
// 创建B产品
IProduct bProduct = bProductFactory.createProduct();
bProduct.display();
}
}
输出结果:
我是A产品
我是B产品
如果我们需要新增「产品C」,只需要增加一个「产品C」的实现类和「产品C」的具体工厂。
工厂方法模式相对简单工厂方法来说,主要是实现了对修改关闭(若要修改,只需要新增一个子类)。
工厂方法模式中的「让一个类的实例化延迟到其子类」,是增加系统扩展性的重要方式。
当然,从演示代码来看,在添加新产品时,需要编写新的具体产品类,而且还要提供与之对应的具体工厂类,系统中类的个数将成对增加,在一定程度上增加了系统的复杂度,有更多的类需要编译和运行,会给系统带来一些额外的开销。
抽象工厂模式(Abstract Factory Pattern)
抽象工厂模式提供一个创建一系列相关或相互依赖对象的接口。
抽象工厂模式与工厂方法类似,都是通过具体工厂来创建具体产品。但抽象工厂不是创造一类产品(所有具体产品都是实现(继承)同一个抽象产品,所以归为一类产品),而是创建一系列相关或相互依赖的产品。什么是一系列或相互依赖的产品来说呢?举一个现实中例子,冰箱是一类产品,实际有海尔冰箱、美的冰箱等。而一系列产品就是同一品牌下的不同产品,比如海尔系列的:海尔冰箱、海尔空调、海尔洗衣机;美的系列的:美的冰箱、美的空调、美的洗衣机。通常,一系列的产品也被称为“产品族”
用代码演示抽象工厂演示如下:
// 抽象卡券
public interface ICard {
void display();
}
// 抽象产品
public interface IProduct {
void display();
}
// A系列产品
public class AProduct implements IProduct {
@Override
public void display() {
System.out.println("我是A产品");
}
}
// A系统卡券
public class ACard implements ICard {
@Override
public void display() {
System.out.println("我是A卡券");
}
}
// B系列产品
public class BProduct implements IProduct {
@Override
public void display() {
System.out.println("我是B产品");
}
}
// B系列卡券
public class BCard implements ICard {
@Override
public void display() {
System.out.println("我是B卡券");
}
}
// 抽象工厂,创建相互依赖或相关的产品
public interface AbstractFactory {
/**
* 创建商品
* @return
*/
IProduct createProduct();
/**
* 创建卡券
* @return
*/
ICard createCard();
}
// A系列工厂
public class AFactory implements AbstractFactory {
@Override
public IProduct createProduct() {
return new AProduct();
}
@Override
public ICard createCard() {
return new ACard();
}
}
// B系列工厂
public class BFactory implements AbstractFactory {
@Override
public IProduct createProduct() {
return new BProduct();
}
@Override
public ICard createCard() {
return new BCard();
}
}
// 客户端
public class Client {
public static void main(String[] args) {
// A系统产品
AbstractFactory aFactory = new AFactory();
IProduct aProduct = aFactory.createProduct();
ICard aCard = aFactory.createCard();
aProduct.display();
aCard.display();
// B系列产品
AbstractFactory bFactory = new BFactory();
IProduct bProduct = bFactory.createProduct();
ICard bCard = bFactory.createCard();
bProduct.display();
bCard.display();
}
}
输出结果:
我是A产品
我是A卡券
我是B产品
我是B卡券
抽象工厂可以创建一系列产品,但其有一个弊端,在产品族中新增一个产品,其所有具体工厂,都需要重新实现一个创建新产品的方法。