设计模式——抽象工厂模式
需求
在工厂方法模式中,一个具体的工厂负责创建一个单一的产品。如果有多个产品要创建,就需要多个不同的工厂类,即使这些产品有某些必然的联系,如多个产品家族或者多个配套产品系列,也是需要多个看起来分散的工厂类。
举个实际的例子,游戏中男孩的帽子、鞋、衣服区别与女孩的帽子、鞋、衣服,各成一个系列,如果使用工厂方法模式来实现,那么那些实体工厂类就在代码上不能体现其配套的内在来年西,看起来太分散了。而抽象工厂模式就是针对多个产品结构而言的,它主要帮助客户一次创建一个家族的多个产品对象。
定义
抽象工厂模式为创建一组相关或相互依赖的对象提供一个接口,而且无需指定他们的具体类。又称为Kit模式。
抽象工厂模式主要由4部分组成:(1)多个抽象产品类:描述产品家族的规格,每个抽象产品类定义每项产品的规格;(2)多个配套的实体产品类:每套实体产品类组成一个实体产品家族,其中的每个实体产品类,实现其相应的抽象产品;(3)抽象工厂类:描述创建家族中各产品的规格;(4)多个实体工厂类:每个实体工厂类都实现抽象工厂类,负责创建一套具有相关性或者依赖性的家族产品。
案例
class Program
{
static voidMain(string[] args)
{
// 客户程序
IClothesFactory factory1 = new BoyClothesFactory();
ICap boyCap = factory1.CreateCap();
IShoes boyShoes = factory1.CreateShoes();
boyCap.Show();
boyShoes.Show();
IClothesFactory factory2 = new GirlClothesFactory();
ICap girlCap = factory2.CreateCap();
IShoes girlShoes = factory2.CreateShoes();
girlCap.Show();
girlShoes.Show();
}
}
// 等级式的产品家族:帽子、靴子
// 抽象产品:帽子
public interface ICap { void Show(); }
// 抽象产品:靴子
public interface IShoes { void Show(); }
// 实体产品:男孩帽子
public class BoyCap : ICap
{
public void Show() { Console.WriteLine("男孩的帽子"); }
}
// 实体产品男孩靴子
public class BoyShoes : IShoes
{
public void Show() { Console.WriteLine("男孩的鞋子"); }
}
// 实体产品:女孩帽子
public class GirlCap : ICap
{
public void Show() { Console.WriteLine("女孩的帽子"); }
}
// 实体产品:女孩靴子
public class GirlShoes : IShoes
{
public void Show() { Console.WriteLine("女孩的鞋子"); }
}
// 工厂等级
// 抽象工厂:服装工厂
public interface IClothesFactory
{
ICap CreateCap();
IShoes CreateShoes();
}
// 实体工厂:男孩服装工厂
public class BoyClothesFactory : IClothesFactory
{
public ICap CreateCap() { return new BoyCap(); }
public IShoes CreateShoes() { return new BoyShoes(); }
}
// 实体工厂:女孩服装工厂
public class GirlClothesFactory : IClothesFactory
{
public ICap CreateCap() { return new GirlCap(); }
public IShoes CreateShoes() { return new GirlShoes(); }
}
优缺点
优点:
封装性,像其它创建型模式一样,实现了创建与使用的分离,明确了各个类的职责。当一系列相互关联的产品被设计到一个工厂类里后,客户端的调用将会变的更加简单。如果需要更换一系列产品,只要更换用另一个工厂类即可。
实现了产品族内的约束,注意是非公开实现的。
缺点:
抽象工厂模式的最大缺点就是产品族扩展非常困难,如果有新的产品需要加进原来的产品系列,那么需要修改抽象工厂类的设计,并修改实现各个实现这个抽象工厂类的具体工厂类,需要增加新的代码,维护麻烦。
适用场景
(1)系统不依赖于产品类实例如何被创建、组合和表达的细节。
(2)系统的产品有多于一个的产品族,而系统只消费其中某一族的产品。
(3)同属于同一个产品族是在一起使用的。这一约束必须在系统的设计中体现出来。
(4)系统提供一个产品类的库,所有产品以同样的接口出现,从而使客户端不依赖于实现。
补充