概述
仍然使用上一篇简单工厂模式中的例子,在水果农场中,FruitFactory
可以返回具体的水果实例,包括🍎和🍊等等,但是如果这个水果农场新增了一种水果,比如🍉,那么我们除了新增🍉类以外,还需要修改FruitFactory
的代码,使得整个设计违反了开闭原则。
因此我们不再使用一个FruitFactory
来统一负责所有水果实例的创建,而是交给专门的工厂子类去完成,相当于我们把水果农场拆分成了🍎厂和🍊厂等等。
工厂方法模式:定义一个用于创建对象的接口,但是让子类决定将哪一个类实例化,工厂方法模式让一个类的实例化延迟到其子类。
使用频率:★★★★★
结构与实现
相对于简单工厂模式,工厂方法模式将Factory(工厂角色)拆分成了
- Factory(抽象工厂角色)
- ConcreteFactory(具体工厂角色)
另外还包括
- Product (抽象产品角色)
- ConcreteProduct (具体产品角色)
一共4种角色。
实现上,ConcreteProduct 和 Product 角色与简单工厂模式一样,区别在于 Factory 和 ConcreteFactory 角色。
interface FruitFatory
{
public Fruit GetFruit();
}
class AppleFactory : FruitFatory
{
public Fruit GetFruit()
{
return new Apple();
}
}
客户端调用方式也发生变化,需要先指定具体工厂角色。
static void Main(string[] args)
{
FruitFatory fruitFatory = new AppleFactory();
Fruit fruit = fruitFatory.GetFruit();
fruit.MethodSame();
fruit.MethodDiff();
}
在这样的结构中,我们增加🍉类时就不需要修改FruitFactory
中的代码,而是增加一个专门生产🍉的工厂类,遵循了开闭原则。
优缺点
优点:
- 提供了专门的工厂方法来创建客户所需要的产品,同时还向客户隐藏了那种具体产品类将被实例化这一细节。客户只需要关心所需产品对应的工厂即可。
- 基于工厂角色和产品角色的多态性设计是此模式的关键。能够让工厂自主决定创建何种产品对象,而如何创建这个对象的细节完全封装在具体工厂内部。
- 再系统中加入新产品时,完全符合开闭原则。
缺点:
- 添加新产品时,类的个数将成对增加,增加系统复杂度。
- 引入抽象层增加理解难度。
适用场景
- 客户端不知道它所需要的对象的类。
- 抽象工厂类通过其子类来指定创建哪个对象。