简单工厂其实并不属于23种GOF设计模式之一,该模式是工厂方法模式的弱化(或者说是工厂方法模式的一种特例),因为简单,所以称为简单工厂模式(Simple Factory Pattern),也叫做静态工厂模式。虽然不是"标准"的设计模式(更像是一种编程习惯),但在实际项目中,采用该方法的案例还是比较多的。
简单工厂模式没有严格的定义,我们姑且使用以下描述:
提供一个创建对象实例的功能,而无须关心其具体实现。被创建实例的类型可以是接口、抽象类,也可以是具体的类
创建产品的工厂方法
public interface Product {
void doSomething();
void doAnything();
}
public class ConcreteProductA implements Product {
@Override
public void doSomething() {
System.out.println("ConcreteProductA doSomething");
}
@Override
public void doAnything() {
System.out.println("ConcreteProductA doAnything");
}
}
public class ConcreteProductB implements Product {
@Override
public void doSomething() {
System.out.println("ConcreteProductB doSomething");
}
@Override
public void doAnything() {
System.out.println("ConcreteProductB doAnything");
}
}
public class Creator {
public static Product createProduct(String type) {
Product product = null;
switch (type) {
case "A":
product = new ConcreteProductA();
break;
case "B":
product = new ConcreteProductB();
break;
}
return product;
}
}
public class Client {
public static void main(String[] args) {
Product productA = Creator.createProduct("A");
productA.doSomething();
productA.doAnything();
Product productB = Creator.createProduct("B");
productB.doSomething();
productB.doAnything();
}
}
解耦
工厂类的扩展比较困难,每增加一个产品,就要在工厂中添加相应的分支,对扩展开放的同时对修改也开放了,不符合开闭原则。如果有很多产品,那么工厂方法会显得特别"臃肿",降低可读性且不易维护。
定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。
public interface Product {
void doSomething();
void doAnything();
}
public class ConcreteProductA implements Product {
@Override
public void doSomething() {
System.out.println("ConcreteProductA doSomething");
}
@Override
public void doAnything() {
System.out.println("ConcreteProductA doAnything");
}
}
public class ConcreteProductB implements Product {
@Override
public void doSomething() {
System.out.println("ConcreteProductB doSomething");
}
@Override
public void doAnything() {
System.out.println("ConcreteProductB doAnything");
}
}
public interface Creator {
Product createProduct();
}
public class ConcreteCreatorA implements Creator {
@Override
public Product createProduct() {
return new ConcreteProductA();
}
}
public class ConcreteCreatorB implements Creator {
@Override
public Product createProduct() {
return new ConcreteProductB();
}
}
public static void main(String[] args) {
Creator creatorA = new ConcreteCreatorA();
Product productA = creatorA.createProduct();
productA.doSomething();
productA.doAnything();
Creator creatorB = new ConcreteCreatorB();
Product productB = creatorB.createProduct();
productB.doSomething();
productB.doAnything();
}
良好的封装性,代码结构清晰
一个对象创建是有条件约束的,如一个调用者需要一个具体的产品对象,只要知道这个产品的类名(或约束字符串)就可以了,不用知道创建对象的艰辛过程,降低模块间的耦合。
工厂方法模式的扩展性非常优秀
在增加产品类的情况下,只要适当地修改具体的工厂类或扩展一个工厂类,就可以完成“拥抱变化”。
每增加一个产品类,就需要增加一个对应的工厂类,增加了额外的开发量。
利用反射机制来解决"每增加一个产品类,就需要增加一个对应的工厂类"的问题
public interface Creator {
<T extends Product> T createProduct(Class<T> clazz);
}
public class ConcreteCreator implements Creator {
@Override
public <T extends Product> T createProduct(Class<T> clazz) {
Product product= null;
try {
product = (Product) Class.forName(clazz.getName()).newInstance();
} catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) {
e.printStackTrace();
}
return (T) product;
}
}
public class Client {
public static void main(String[] args) {
Creator creator = new ConcreteCreator();
Product productA = creator.createProduct(ConcreteProductA.class);
productA.doSomething();
productA.doAnything();
Product productB = creator.createProduct(ConcreteProductB.class);
productB.doSomething();
productB.doAnything();
}
}
工厂方法模式是对简单工厂的进一步抽象和解耦。和简单工厂比:
为创建一组相关或相互依赖的对象提供一个接口,而且无须指定它们的具体类。
产品A家族
public interface ProductA {
void doSomething();
void doAnything();
}
产品B家族
public interface ProductB {
void doSomething();
void doAnything();
}
产品A家族,产品等级1
public class ConcreteProductA1 implements ProductA {
@Override
public void doSomething() {
System.out.println("ConcreteProductA1 doSomething");
}
@Override
public void doAnything() {
System.out.println("ConcreteProductA1 doAnything");
}
}
产品A家族,产品等级2
public class ConcreteProductA2 implements ProductA {
@Override
public void doSomething() {
System.out.println("ConcreteProductA2 doSomething");
}
@Override
public void doAnything() {
System.out.println("ConcreteProductA2 doAnything");
}
}
产品B家族,产品等级2
public class ConcreteProductB1 implements ProductB {
@Override
public void doSomething() {
System.out.println("ConcreteProductB1 doSomething");
}
@Override
public void doAnything() {
System.out.println("ConcreteProductB1 doAnything");
}
}
产品B家族,产品等级2
public class ConcreteProductB2 implements ProductB {
@Override
public void doSomething() {
System.out.println("ConcreteProductB2 doSomething");
}
@Override
public void doAnything() {
System.out.println("ConcreteProductB2 doAnything");
}
}
public interface Creator {
/**
* 创建A产品家族
* @return
*/
ProductA createProductA();
/**
* 创建B产品家族
* @return
*/
ProductB createProductB();
// ...
// 有N个产品族,在抽象工厂类中就应该有N个创建方法
}
有N个产品族,在抽象工厂类中就应该有N个创建方法
public class ConcreteCreator1 implements Creator {
@Override
public ProductA createProductA() {
return new ConcreteProductA1();
}
@Override
public ProductB createProductB() {
return new ConcreteProductB1();
}
}
public class ConcreteCreator2 implements Creator {
@Override
public ProductA createProductA() {
return new ConcreteProductA2();
}
@Override
public ProductB createProductB() {
return new ConcreteProductB2();
}
}
有M个产品等级,就应该有M个具体工厂实现
public class Client {
public static void main(String[] args) {
Creator creator1 = new ConcreteCreator1();
ProductA productA1 = creator1.createProductA();
productA1.doSomething();
productA1.doAnything();
ProductB productB1 = creator1.createProductB();
productB1.doSomething();
productB1.doAnything();
Creator creator2 = new ConcreteCreator2();
ProductA productA2 = creator2.createProductA();
productA2.doSomething();
productA2.doAnything();
ProductB productB2 = creator2.createProductB();
productB2.doSomething();
productB2.doAnything();
}
}
抽象工厂模式的最大缺点就是产品族扩展非常困难,以上面的通用代码为例,如果要增加一个产品C,也就是说产品家族由原来的2个增加到3个,抽象工厂类Creator要增加一个方法createProductC(),然后每个实现类都要修改,违反了开闭原则。
抽象工厂模式是工厂方法模式的升级版本,在有多个业务品种、业务分类时,通过抽象工厂模式产生需要的对象是一种非常好的解决方式。
工厂方法模式生产一个产品,抽象工厂模式生产多个产品(一系列产品);在编程中,通常表现为一个接口或者抽象类,也就是说,工厂方法模式提供的所有产品都是衍生自同一个接口或抽象类,而抽象工厂模式所提供的产品则是衍生自不同的接口或抽象类。
简单工厂、工厂方法、抽象工厂这三种模式是逐步抽象的,后者适用于更为一般的场景,而前者是后者的特例。但它们的目标是殊途同归的,目的都是灵活地创建所需的对象并且对客户端隐藏对象创建细节,三者的扩展性和开发量有所不同,可以根据实际情况选择合适的模式来代替以new的方式创建对象的过程:
如果一个产品族都有相同的约束(在有多个业务品种、业务分类时,即:具有产品族&产品等级结构的概念),则可以使用抽象工厂模式
例如一个文本编辑器和一个图片处理器,都是软件实体,但是*nix下的文本编辑器和Windows下的文本编辑器虽然功能和界面都相同,但是代码实现是不同的,图片处理器也有类似情况。也就是具有了共同的约束条件:操作系统类型。于是我们可以使用抽象工厂模式,产生不同操作系统下的编辑器和图片处理器。
源码地址: https://gitee.com/tianranll/java-design-patterns.git
参考文献:《设计模式之禅》、《大话设计模式》