创建型:简单工厂模式、工厂方法模式和抽象工厂模式

工厂模式可以将对象的创建封装起来,以便于得到更松耦合,更有弹性的设计。所有工厂模式都通过减少应用程序和具体类之间的依赖促进耦合。

1.针对抽象编程,而不要针对具体类编程。
2.依赖倒置原则,指导避免依赖具体类型,而要尽量依赖抽象。

简单工厂模式

简单工厂模式不属于 GoF 23个经典设计模式。

简单工厂模式(Simple Factory Pattern)定义:定义一个工厂类,它可以根据传入的不同参数来返回不同的类的实例。

由于在简单工厂模式中用于创建实例的方法是静态方法,因而又被称为静态工厂方法模式,属于类创建型模式。


每更换一个生产的产品需要更改代码中传入的type参数,违反了“开闭原则”,可以通过将该参数存储在配置文件中。

简化的简单工厂模式:可以将抽象产品类 Product 和工厂类 Factory 合并,将静态工厂方法移至 Product 类中。

  1. 优点
    • 实现了对象创建和使用的分离。
    • 引入配置文件,可以在不修改代码的情况下更换 Product 实现类型,提高了灵活性。
  2. 缺点
    • 工厂类职责过重,集中了所有产品的创建逻辑,某一环节出错可能会影响整个系统。
    • 系统扩展和维护困难,添加新产品必须修改工厂逻辑。
  3. 适用场景
    • 工厂类负责创建的对象比较少,不会造成工厂方法中的业务逻辑过于复杂。

工厂方法模式

工厂方法模式(Factory Method Pattern):定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个。工厂方法让类把实例化推迟到子类。

工厂方法使用继承:把对象的创建委托给子类,子类实现工厂方法来创建对象,不再像简单工厂模式中将所有逻辑集中在一个工厂类里。

对于应该使用哪个具体的工厂类实现来生成具体的产品实例,可以通过配置文件存储工厂类的类名。

  1. 优点
    • 工厂方法隐藏了哪种具体产品类将被实例化。
    • 基于工厂角色和产品角色的多态性是工厂方法模式的关键,隐藏了产品被实例化的细节。
    • 新产品加入时,无须修改抽象工厂和抽象产品提供的接口,无须修改客户端,也无须修改其他具体工厂和具体产品,只需要添加一个具体产品和相应的具体工厂即可。扩展性好,符合“开闭原则”。
  2. 缺点
    • 添加新产品时,需要编写新的具体产品类及其具体工厂类,会导致系统中类的个数成对增加,增加了系统复杂度和额外开销。
    • 由于引入了抽象层,在客户端代码中均使用抽象层进行定义,增加了系统的抽象性和理解难度,实现时可能会使用反射、DOM等技术根据配置文件来实例化具体工厂,增加了实现难度。
  3. 使适用场景
    • 客户端不知道所需的具体产品类,只要知道所对应的工厂即可。
    • 抽象工厂类通过其子类来指定创建哪个对象,利用面向对象的多态性和里氏代换原则,使系统更容易扩展。

实例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package creator.factorymethod;
public abstract class PizzaStore {
public Pizza orderPizza(String type){
Pizza pizza = createPizza(type);
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
System.out.println(pizza);
return pizza;
}
/**
* factory method
* 1.工厂方法是抽象的,所以依赖子类来处理对象的创建。
* 2.工厂方法必须返回一个产品,超类中定义的方法通常用到工厂方法的返回值。
* 3.工厂方法将超类(客户)中的代码(例如orderPizza)和实际创建的具体产品代码分开。
* @param type
* @return
*/
protected abstract Pizza createPizza(String type);
}

1
2
3
4
5
6
public class ChicagoPizzaStore extends PizzaStore {
protected Pizza createPizza(String type) {
return new Pizza("Chicago: " + type);
}
}
1
2
3
4
5
6
public class NewYorkPizzaStore extends PizzaStore {
protected Pizza createPizza(String type) {
return new Pizza("NewYork: " + type);
}
}

抽象工厂模式

抽象工厂模式(Abstract Factory Pattern):提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类。为创建一组对象提供了解决方案,,而不是像工厂方法中为每个工厂只创建一个产品。

产品等级结构:即产品的继承结构。
产品族:指由一个工厂生产的,位于不同产品等级结构的一组产品,如海尔工厂生产海尔电视机、海尔电冰箱,电视机和电冰箱分别位于不同的产品等级结构,且构成了一个产品族。

抽象工厂使用对象组合:对象的创建被实现在工厂接口所暴露出来的方法中。

  1. 优点
    • 多个产品对象组成一个产品族,可以保证客户端始终只使用一个产品族。
    • 增加新的产品族很方便,符合“开闭原则”。
  2. 缺点
    • 增加新的产品等级结构比较麻烦,需要对原系统进行较大的修改,甚至需要修改抽象层的代码,这点违背了“开闭原则”。
  3. 适用场景
    • 系统不依赖于产品类如何创建、组合的细节,用户无需关心对象的创建过程。
    • 系统有多个产品族,每次只使用一个产品族,可以通过配置文件方式来动态改变产品族。
    • 产品的等级结构稳定。

实例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
package creator.abstractfactory;
public class Pizza {
/**
* 抽象工厂使用对象组合
*/
private PizzaIngredientFactory ingredientFactory;
public Pizza(PizzaIngredientFactory ingredientFactory) {
this.ingredientFactory = ingredientFactory;
}
public void prepare(){
System.out.println("prepare...");
System.out.println(ingredientFactory.createCheese());
System.out.println(ingredientFactory.createClams());
System.out.println(ingredientFactory.createSauce());
}
public void bake(){
System.out.println("bake...");
}
public void cut(){
System.out.println("cut...");
}
public void box(){
System.out.println("box...");
}
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package creator.abstractfactory;
import creator.abstractfactory.entity.Cheese;
import creator.abstractfactory.entity.Clams;
import creator.abstractfactory.entity.Sauce;
/**
* 定义工厂接口
*/
public interface PizzaIngredientFactory {
Clams createClams();
Cheese createCheese();
Sauce createSauce();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
package creator.abstractfactory;
import creator.abstractfactory.entity.Cheese;
import creator.abstractfactory.entity.Clams;
import creator.abstractfactory.entity.Sauce;
/**
* 工厂具体实现
*/
public class ChicagoPizzaIngredientFactory implements PizzaIngredientFactory {
@Override
public Clams createClams() {
return new Clams("Chicago Clams");
}
@Override
public Cheese createCheese() {
return new Cheese("Chicago Cheese");
}
@Override
public Sauce createSauce() {
return new Sauce("Chicago Sauce");
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
package creator.abstractfactory;
import creator.abstractfactory.entity.Cheese;
import creator.abstractfactory.entity.Clams;
import creator.abstractfactory.entity.Sauce;
/**
* 工厂具体实现
*/
public class NewYorkPizzaIngredientFactory implements PizzaIngredientFactory {
@Override
public Clams createClams() {
return new Clams("New York Clams");
}
@Override
public Cheese createCheese() {
return new Cheese("New York Cheese");
}
@Override
public Sauce createSauce() {
return new Sauce("New York Sauce");
}
}