抽象工厂和工厂模式的区别
工厂方法模式:每个抽象产品派生多个具体产品类,每个抽象工厂类派生多个具体工厂类,每个具体工厂类负责一个具体产品的实例创建;
抽象工厂模式:每个抽象产品派生多个具体产品类,每个抽象工厂派生多个具体工厂类,每个具体工厂负责多个(一系列)具体产品的实例创建。
工厂方法模式通过引入工厂等级结构,解决了简单工厂模式中工厂类职责太重的问题,但由于工厂方法模式中的每个工厂只生产一类产品,可能会导致系统中存在大量的工厂类,势必会增加系统的开销。抽象工厂模式就是将一些相关的产品组成一个“产品族”,由同一个工厂来统一生产。
什么是产品等级结构,什么是产品族?
产品等级结构:产品等级结构即产品的继承结构,如一个抽象类是电视机,其子类有海尔电视机、海信电视机、TCL电视机,则抽象电视机与具体品牌的电视机之间构成了一个产品等级结构,抽象电视机是父类,而具体品牌的电视机是其子类。
产品族:在抽象工厂模式中,产品族是指由同一个工厂生产的,位于不同产品等级结构中的一组产品,如海尔电器工厂生产的海尔电视机、海尔电冰箱,海尔电视机位于电视机产品等级结构中,海尔电冰箱位于电冰箱产品等级结构中,海尔电视机、海尔电冰箱构成了一个产品族。
定义
抽象工厂模式(Abstract Factory Pattern):提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类。抽象工厂模式又称为Kit模式,它是一种对象创建型模式。
类图
角色
(1)AbstractFactory(抽象工厂):它声明了一组用于创建一族产品的方法,每一个方法对应一种产品。还以计算机实现加减运算为例:
/// <summary>
/// 抽象工厂类,提供创建两种语言的加减的接口
/// 抽象工厂提供创建一系列产品的接口
/// </summary>
public abstract class AbstractFactory
{
public abstract Add OperationAdd();
public abstract Sub OperationSub();
}
(2)ConcreteFactory(具体工厂):它实现了在抽象工厂中声明的创建产品的方法,生成一组具体产品,这些产品构成了一个产品族,每一个产品都位于某个产品等级结构中。
中文加和中文减是一个产品族,英文加和英文减是一个产品族。
中文加和英文加是一个产品等级,中文减和英文减是一个产品等级。
/// <summary>
/// 中文算法工厂负责生成中文加减
/// </summary>
public class ChineseFactory : AbstractFactory
{
// 生成中文加
public override Add OperationAdd()
{
return new ChineseAdd();
}
// 生成中文减
public override Sub OperationSub()
{
return new ChineseSub();
}
}
/// <summary>
/// 英语工厂负责生成英语加减
/// </summary>
public class EnglishFactory : AbstractFactory
{
// 生成英文加
public override Add OperationAdd()
{
return new EnglishAdd();
}
// 生成英文减
public override Sub OperationSub()
{
return new EnglishSub();
}
}
(3)AbstractProduct(抽象产品):它为每种产品声明接口,在抽象产品中声明了产品所具有的业务方法。
/// <summary>
/// 加号抽象类,共多种语言的加号类继承
/// </summary>
public abstract class Add
{
/// <summary>
/// 打印方法,用于输出信息
/// </summary>
public abstract void Print();
}
/// <summary>
/// 减号抽象类,共多种语言的减号类继承
/// </summary>
public abstract class Sub
{
/// <summary>
/// 打印方法,用于输出信息
/// </summary>
public abstract void Print();
}
(4)ConcreteProduct(具体产品):它定义具体工厂生产的具体产品对象,实现抽象产品接口中声明的业务方法
/// <summary>
/// 中文“+”
/// </summary>
public class ChineseAdd : Add
{
public override void Print()
{
Console.WriteLine("中文“+”");
}
}
/// <summary>
/// 英文“+”
/// </summary>
public class EnglishAdd : Add
{
public override void Print()
{
Console.WriteLine("英文“+”");
}
}
/// <summary>
/// 中文“-”
/// </summary>
public class ChineseSub : Sub
{
public override void Print()
{
Console.WriteLine("中文“-”");
}
}
/// <summary>
/// 英文“-”
/// </summary>
public class EnglishSub : Sub
{
public override void Print()
{
Console.WriteLine("英文“-”");
}
}
客户端代码如下
static void Main(string[] args)
{
// 中文工厂制作中文加减
AbstractFactory ChineseFactory = new ChineseFactory();
Add ChineseAdd = ChineseFactory.OperationAdd();
ChineseAdd.Print();
Sub ChineseSub = ChineseFactory.OperationSub();
ChineseSub.Print();
// 上海工厂制作上海的鸭脖和鸭架
AbstractFactory EnglishFactory = new EnglishFactory();//实例抽象工厂
EnglishFactory.OperationAdd().Print();//实例抽象产品
EnglishFactory.OperationSub().Print();
Console.Read();
}
总结
优点
符合开闭原则,增加新的具体工厂和产品族很方便,无须修改已有系统
符合高内聚,低耦合,具体的创建实例过程和客户端分离,客户端通过抽象接口操纵实例,。
缺点
抽象工厂模式很难支持新种类产品的变化。这是因为抽象工厂接口中已经确定了可以被创建的产品集合,如果需要添加新产品,此时就必须去修改抽象工厂的接口,这样就涉及到抽象工厂类的以及所有子类的改变,这样也就违背了“开发——封闭”原则
适用场景
当需要创建的对象是一系列相互关联或相互依赖的产品族时,便可以使用抽象工厂模式。说的更明白一点,就是一个继承体系中,如果存在着多个等级结构(即存在着多个抽象类),并且分属各个等级结构中的实现类之间存在着一定的关联或者约束,就可以使用抽象工厂模式。假如各个等级结构中的实现类之间不存在关联或约束,则使用多个独立的工厂来对产品进行创建,则更合适一点。
结语
抽象工厂模式符合闭合原则,但也正是因为符合闭合原则而产生了缺点:添加新产品,需要添加相应的n个类。反而用简单工厂来改造抽象工厂会简单很多,三个工厂模式之间的演变常常令我们琢磨不透,所以我们在使用时,不必拘泥与它是简单工厂,还是工厂模式,还是抽象工厂模式,只要耦合度降低就ok了。