抽象工厂模式基本思想:将一些相关的产品组成一个“产品族”,由同一个工厂来统一生产。
产品等级结构与产品族示意图如图所示:
抽象工厂模式示意图如图所示:
抽象工厂模式(Abstract Factory Pattern):提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类。抽象工厂模式又称为Kit模式,它是一种对象创建型模式。
在抽象工厂模式中,每一个具体工厂都提供了多个工厂方法用于产生多种不同类型的产品,这些产品构成了一个产品族,抽象工厂模式结构如图所示:
在抽象工厂模式结构图中包含如下几个角色:
● AbstractFactory(抽象工厂):它声明了一组用于创建一族产品的方法,每一个方法对应一种产品。
//抽象类
abstract class AbstractFactory
{
public abstract AbstractProductA createProductA(); //工厂方法一
public abstract AbstractProductB createProductB(); //工厂方法二
... ...
}
//接口
interface AbstractFactory
{
AbstractProductA createProductA(); //工厂方法一
AbstractProductB createProductB(); //工厂方法二
... ...
}
● ConcreteFactory(具体工厂):它实现了在抽象工厂中声明的创建产品的方法,生成一组具体产品,这些产品构成了一个产品族,每一个产品都位于某个产品等级结构中。
class ConcreteFactory1: AbstractFactory
{
//工厂方法一
public AbstractProductA createProductA()
{
return new ConcreteProductA1();
}
//工厂方法二
public AbstractProductB createProductB()
{
return new ConcreteProductB1();
}
... ...
}
● AbstractProduct(抽象产品):它为每种产品声明接口,在抽象产品中声明了产品所具有的业务方法。
● ConcreteProduct(具体产品):它定义具体工厂生产的具体产品对象,实现抽象产品接口中声明的业务方法。
完整解决方案
Sunny公司开发人员使用抽象工厂模式来重构界面皮肤库的设计,其基本结构如图6所示:
C#代码片段:
//界面皮肤工厂接口:抽象工厂
interface SkinFactory
{
Button CreateButton();
TextField CreateTextField();
ComboBox CreateComboBox();
}
//Spring皮肤工厂:具体工厂
class SpringSkinFactory : SkinFactory
{
public Button CreateButton()
{
return new SpringButton();
}
public ComboBox CreateComboBox()
{
return new SpringComboBox();
}
public TextField CreateTextField()
{
return new SpringTextField();
}
}
//Summer皮肤工厂:具体工厂
class SummerSkinFactory : SkinFactory
{
public Button CreateButton()
{
return new SummerButton();
}
public ComboBox CreateComboBox()
{
return new SummerComboBox();
}
public TextField CreateTextField()
{
return new SummerTextField();
}
}
//按钮接口:抽象产品
interface Button
{
void Display();
}
//文本框接口:抽象产品
interface TextField
{
void Display();
}
//组合框接口:抽象产品
interface ComboBox
{
void Display();
}
//Spring按钮:具体产品
class SpringButton : Button
{
public void Display()
{
//... ...
}
}
//Summer按钮:具体产品
class SummerButton :Button
{
public void Display()
{
//... ...
}
}
//Spring文本框:具体产品
class SpringTextField :TextField
{
public void Display()
{
//... ...
}
}
//Summer文本框:具体产品
class SummerTextField :TextField
{
public void Display()
{
//... ...
}
}
//Spring组合框:具体产品
class SpringComboBox :ComboBox
{
public void Display()
{
//... ...
}
}
//Summer组合框:具体产品
class SummerComboBox :ComboBox
{
public void Display()
{
//... ...
}
}
class Client
{
static void Main(string[] args)
{
SkinFactory factory=new SpringSkinFactory();
Button btn = factory.CreateButton();
btn.Display();
ComboBox cbx = factory.CreateComboBox();
cbx.Display();
}
}
在抽象工厂模式中,增加新的产品族很方便,但是增加新的产品等级结构很麻烦,抽象工厂模式的这种性质称为“开闭原则”的倾斜性。
抽象工厂模式的主要优点:
- 抽象工厂模式隔离了具体类的生成,使得客户并不需要知道什么被创建。由于这种隔离,更换一个具体工厂就变得相对容易,所有的具体工厂都实现了抽象工厂中定义的那些公共接口,因此只需改变具体工厂的实例,就可以在某种程度上改变整个软件系统的行为。
- 当一个产品族中的多个对象被设计成一起工作时,它能够保证客户端始终只使用同一个产品族中的对象。
- 增加新的产品族很方便,无须修改已有系统,符合“开闭原则”。
抽象工厂模式的主要缺点:
- 增加新的产品等级结构麻烦,需要对原有系统进行较大的修改,甚至需要修改抽象层代码,这显然会带来较大的不便,违背了“开闭原则”。
在以下情况下可以考虑使用抽象工厂模式:
- 一个系统不应当依赖于产品类实例如何被创建、组合和表达的细节,这对于所有类型的工厂模式都是很重要的,用户无须关心对象的创建过程,将对象的创建和使用解耦。
- 系统中有多于一个的产品族,而每次只使用其中某一产品族。可以通过配置文件等方式来使得用户可以动态改变产品族,也可以很方便地增加新的产品族。
- 属于同一个产品族的产品将在一起使用,这一约束必须在系统的设计中体现出来。同一个产品族中的产品可以是没有任何关系的对象,但是它们都具有一些共同的约束,如同一操作系统下的按钮和文本框,按钮与文本框之间没有直接关系,但它们都是属于某一操作系统的,此时具有一个共同的约束条件:操作系统的类型。
- 产品等级结构稳定,设计完成之后,不会向系统中增加新的产品等级结构或者删除已有的产品等级结构。
【学习于刘伟-设计模式】
【完整:https://blog.csdn.net/lovelion/article/details/9319571】
【完整:https://blog.csdn.net/lovelion/article/details/9319423】