问题:
Factory Method模式是为一类对象提供创建接口或延迟对象的创建到子类中实现。但是,我们在软件系统中,经常面临着“一系列相互依赖的对象”的创建工作,同时由于需求的变化,这“一系列相互依赖的对象”也要改变,如何应对这种变化呢?Abstract Factory模式是为创建一系列相关或依赖的对象提供创建接口(AbstractFactory),将一组产品的创建封装到一个用于创建对象的类(ConcreteFactory)中(形成一个系列),维护这样一个创建类总比使用Factory Method维护n多相关对象的创建过程(逻辑)要简单的多,而且
Factory Method,没有办法保证“一系列相互依赖的对象”,的联系,没有联系就不是“一系列相互依赖的对象”的对象了。
定义:
提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。抽象工厂(Abstract Factory)模式又称为Kit模式,属于对象创建型模式。
意图:
为创建一系列(多组,多类)相关或依赖的对象提供创建接口(AbstractFactory),此接口不负责产品的创建不关心产品实例化细节。将一组产品的创建封装到一个用于创建对象的类(ConcreteFactory)中使得系统
定义一个用户创建对象的公共接口,此接口不负责产品的创建不关心产品实例化细节,而是将具体创建工作交给子类去做,这样做的目的是将类的实例化操作延迟到子类中完成,即由子类来决定究竟应该实例化(创建)哪一个类,使得工厂方法模式可以允许系统在不修改工厂角色的情况下引进新产品。
参与者:
•抽象工厂角色:
担任这个角色的是工厂方法模式的核心,它是与应用系统的商业逻辑无关的。通常使用接口或抽象类实现。
•具体工厂角色:
这个角色直接在客户端的调用下创建产品的实例。这个角色含有选择合适的产品对象的逻辑,而这个逻辑是与应用系统的商业逻辑紧密相关的。通常使用具体的类实现。
•抽象产品角色:
担任这个角色的类是抽象工厂方法模式所创建的对象的父类,或它们共同拥有的接口。通常使用接口或抽象类实现这一角色。
•具体产品角色:
抽象工厂模式所创建的任何产品对象都是某一具体产品类的实例。这是客户端最终需要的东西。通常使用具体类实现这个角色。
UML图:
实例说明:
诺基亚手机工厂
比如Nokia手机工厂,现在只生产N8,N9两款手机,但是要根据不同国家的网络环境,生产支持不同网络系列的手机,根据不同网络生产工厂(GMS生产车间,CDMA生产车间)创建至此不同网络的所有Nokia手机(N8.N9),而且容易加入新的网络环境(如:WCDMA)手机的生产(不修改现有系统)。
uml图:
代码:
/// N8手机抽象产品类
/// </summary>
public abstract class N8Phone
{
public abstract string PhoneName { get; }
public abstract string NetTypeName { get; }
}
/// <summary>
/// N9手机抽象产品类
/// </summary>
public abstract class N9Phone
{
public abstract string PhoneName { get; }
public abstract string NetTypeName { get; }
public abstract string GpsTypeName { get; }
}
/// <summary>
/// N8,GMS网络 手机具体类
/// </summary>
public class N8Phone_Gsm : N8Phone
{
public override string NetTypeName
{
get
{
return "我是GSM的";
}
}
public override string PhoneName
{
get
{
return "我是N8";
}
}
}
/// <summary>
/// N8,CDMA网络 手机具体类
/// </summary>
public class N8Phone_Cdma : N8Phone
{
public override string NetTypeName
{
get
{
return "我是CDMA的";
}
}
public override string PhoneName
{
get
{
return "我是N8";
}
}
}
/// <summary>
/// N9,GMS网络 手机具体类
/// </summary>
public class N9Phone_Gsm : N9Phone
{
public override string NetTypeName
{
get
{
return "我是Gms的";
}
}
public override string PhoneName
{
get
{
return "我是N9";
}
}
public override string GpsTypeName
{
get
{
return "RJT2";
}
}
}
/// <summary>
/// N9,CDMA网络 手机具体类
/// </summary>
public class N9Phone_Cdma : N9Phone
{
public override string NetTypeName
{
get
{
return "我是CDMA的";
}
}
public override string PhoneName
{
get
{
return "我是N9";
}
}
public override string GpsTypeName
{
get
{
return "RJT2";
}
}
}
/// <summary>
/// 手机生产抽象工厂类
/// </summary>
public interface IPhoneFactory
{
N8Phone CreateNokiaN8();
N9Phone CreateNokiaN9();
}
/// <summary>
/// GMS手机具体工厂类
/// </summary>
public class GmsFactory : IPhoneFactory
{
public N8Phone CreateNokiaN8()
{
return new N8Phone_Gsm();
}
public N9Phone CreateNokiaN9()
{
return new N9Phone_Gsm();
}
}
/// <summary>
/// CDMA手机具体工厂类
/// </summary>
public class CdmaFactory : IPhoneFactory
{
public N8Phone CreateNokiaN8()
{
return new N8Phone_Cdma();
}
public N9Phone CreateNokiaN9()
{
return new N9Phone_Cdma();
}
}
/// <summary>
/// 客户端类
/// </summary>
class Program
{
public static void Main()
{
IPhoneFactory factory = new GmsFactory();
N8Phone phone1 = factory.CreateNokiaN8();
N9Phone phone2 = factory.CreateNokiaN9();
var s= phone1.NetTypeName;
}
}
优点:
•将客户与具体产品类对象创建过程隔离,客户通过抽象接口操纵实例,依赖于抽象类(接口),耦合性低。
•由于客户依赖与抽象类,所以使得更换产品系列时变得非常容易,只须更改一下具体工厂名。
•系统能很好的应对“新系列”产品添加的扩展,无需修改现有代码,只需加入相应的工厂类即可。
•一个系列的产品对象被约束在一起,能够保证客户端始终只使用一个系列产品中的对象,是非常实用的一种设计。如, GmsFactory工厂,不可能生产出N9Phone_Cdma手机。
缺点:
•Abstract Factory模式主要在于应对“新系列”的需求变动。缺点是难以应对“新对象”的需求变动。如果要支持新种类的产品,需要对工厂接口进行扩展,违反了开闭原则。
应用情景:
•系统有多于一个的系列,而只消费其中某一产系列。应对“多系列对象构建”的需求变化。“系列对象”指的是这项对象之间有相互依赖、或作用的关系。
•系统需要由一系列关联的多个对象来构成,有关联的多个对象需要一起应用并且它们的约束是强迫的,不可分离的