这是我参与8月更文挑战的第27天,活动详情查看:8月更文挑战
1. 前言
对于工厂模式来说,相关的设计模式有三个,都是创建型的设计模式,先简单介绍一下:
- 简单工厂模式:在简单工厂模式中,把实例化的操作单独放到一个工厂类中,这个类就成为简单工厂类,让简单工厂类来决定应该用哪个具体子类来实例化。
- 工厂方法:定义了一个创建对象的接口,但由子类决定要实例化哪个类。工厂方法把实例化操作推迟到子类。
- 抽象工厂:抽象工厂模式创建的是对象家族,也就是很多对象而不是一个对象,并且这些对象是相关的,也就是说必须一起创建出来。
2 简单工厂模式
2.1 类图
如下图所示,在简单工厂模式中,把实例化的操作单独放到 SimpleFactory
中,这个类就成为简单工厂类,让简单工厂类来决定应该用哪个具体子类来实例化。
这样做能把客户类和具体子类的实现解耦,客户类不再需要知道有哪些子类以及应当实例化哪个子类。
2.2 实现方式
public interface IProduct {
}
public class Product1 implements Product {
}
public class Product2 implements Product {
}
以下是实例化对象的简单工厂类
public class SimpleFactory {
public Product createProduct(String type) {
if ("冰箱".equal(type)) {
return new Product1();
}
return new Product2();
}
}
以下是 Client 的调用方式
public class Client {
public static void main(String[] args) {
SimpleFactory simpleFactory = new SimpleFactory();
Product product = simpleFactory.createProduct("冰箱");
}
}
2.3 简单工厂模式小结
简单工厂模式的缺点:
- 由于工厂类集中了所有产品创建逻辑,一旦不能正常工作,整个系统都要受到影响。
- 使用简单工厂模式将会增加系统中类的个数,在一定程序上增加了系统的复杂度和理解难度。
- 系统扩展困难,一旦添加新产品就不得不修改工厂逻辑,同样破坏了“开闭原则”
- 简单工厂模式由于使用了静态工厂方法,造成工厂角色无法形成基于继承的等级结构。
只有工厂负责创建的对象比较少,才能使用这个设计模式,并且简单工厂模式在添加新类时是要修改原有代码的,这违背了开闭原则。
3. 工厂方法模式
3.1 类图
下图所示,在 Factory
中抽象出一个创建产品的方法,但是没有具体的实现逻辑,而是交给其子类去实现。
3.2 实现
假设有三个产品对象需要创建,Product
、Product1
、Product2
,创建三个工厂类分别去实现创建的具体逻辑,这样做的好处是当有新产品增加,只需要增加新的工厂类就行了。
public abstract class Factory {
abstract public Product factoryMethod();
public void doSomething() {
Product product = factoryMethod();
}
}
public class ConcreteFactory extends Factory {
public Product factoryMethod() {
return new Product();
}
}
public class ConcreteFactory1 extends Factory {
public Product factoryMethod() {
return new Product1();
}
}
public class ConcreteFactory2 extends Factory {
public Product factoryMethod() {
return new Product2();
}
}
3.3 简单工厂模式小结
工厂方法模式很好的体现了 依赖倒置原则:不能让高层组件依赖于低层组件,而且不管高层组件还是低层组件,都应该依赖于抽象。
工厂方法的缺点是当每次增加一个产品时,都需要增加一个具体类和对象实现工厂,使得系统中类的个数成倍增加,在一定程度上增加了系统的复杂度,同时也增加了系统具体类的依赖。
4. 抽象工厂模式
4.1 类图
抽象工厂模式用到了工厂方法模式来创建单一对象,AbstractFactory
中的 createProductA()
和 createProductB()
方法都是让子类来实现,这两个方法单独来看就是在创建一个对象,这符合工厂方法模式的定义。
至于创建对象的家族这一概念是在 Client
体现,Client
要通过 AbstractFactory
同时调用两个方法来创建出两个对象,在这里这两个对象就有很大的相关性,Client
需要同时创建出这两个对象。
从高层次来看,抽象工厂使用了组合,即 Cilent
组合了 AbstractFactory
,而工厂方法模式使用了继承。
4.2 实现
public class AbstractProductA {
}
public class AbstractProductB {
}
public class ProductA extends AbstractProductA {
}
public class ProductB extends AbstractProductB {
}
public abstract class AbstractFactory {
abstract AbstractProductA createProductA();
abstract AbstractProductB createProductB();
}
public class ConcreteFactory extends AbstractFactory {
AbstractProductA createProductA() {
return new ProductA();
}
AbstractProductB createProductB() {
return new ProductB();
}
}
在 Client
中使用 ConcreteFactory
同时创建了两个对象。
public class Client {
public static void main(String[] args) {
AbstractFactory abstractFactory = new ConcreteFactory();
AbstractProductA productA = abstractFactory.createProductA();
AbstractProductB productB = abstractFactory.createProductB();
}
}
4.3 抽象工厂小结
抽象工厂模式实现的关键点是定义工厂接口和产品接口,但如何实现工厂与产品本身需要留给具体的子类实现,客户端只和抽象工厂与抽象产品打交道