1.1.1 摘要
抽象工厂模式:允许客户使用抽象的接口来创建一系列相关的产品,而无需要知道实际产出的具体产品是什么。这样一来,客户就从具体的产品中被解耦出来。这种模式适用于产品对象的数目和种类不变,而具体产品系列之间存在不同或者容易变化的情况。
关键字:依赖抽象,不要依赖具体类,OCP
使用率: high
图
1.1.2 参与类或接口作用
AbstractFactory (UIAbstractFactory):定义一个接口用来创建抽象产品,担任这个角色的是工厂方法模式的核心,它是与应用系统商业逻辑无关的。
ConcreteFactory (MacUIFactory, WinUIFactory):这个角色直接在客户端的调用下创建产品的实例。这个角色含有选择合适的产品对象的逻辑,而这个逻辑是与应用系统的商业逻辑紧密相关的。
AbstractProduct (IButton, IBorder):担任这个角色的类是工厂方法模式所创建的对象的父类,或它们共同拥有的接口。
Product (WinBotton, MacBotton, WinBorder, MacBorder):抽象工厂模式所创建的任何产品对象都是某一个具体产品类的实例。这是客户端最终需要的东西,其内部一定充满了应用系统的商业逻辑。
Client (UIClient):调用AbstractFactory和AbstractProduct的接口。
图
1.1.3 模式实现技术
利用设计模式可以使我们代码更加灵活,更容易扩展,更容易维护。各种面向对象的程序设计语言都提供了基本相同的机制:比如类、继承、派生、多态等等。同时.Net Framework提供我们一种重要的特性—反射,这样我们可以动态的创建对象的实例,而且只需修改配置文件就可以创建不同实例,并且无需重新编译整个程序。除了使用反射我们还可以使用微软Enterprise Library提供的Unity进行依赖注入把UIClient从UIAbstractFactory和AbstractFactory解耦出来。
方法一:
// CreateInstance有多个重载方法
Activator.CreateInstance(Type.GetType("命名空间.类名称"));
方法二:
Assembly.Load("程序集名称").CreateInstance("命名空间.类名称");
方法三:
使用IoC容器进行依赖注入。
1.1.4 抽象工厂的简单实现

namespace UnityTestApp{ class Program { public static void Main() { UIClient myClient = new UIClient(OS.Win); myClient.PaintUI(); Console.ReadKey(); } } /// <summary> /// 客户端 /// </summary> public class UIClient { private IButton button; private IBorder border; private UIAbstractFactory myFactory = null; public UIClient(OS osName) {//使用反射机制 string concreteFactroyName = this.GetType().Namespace.ToString() + "." + osName.ToString() + "UIFactory"; this.myFactory = Activator.CreateInstance(Type.GetType(concreteFactroyName)) as UIAbstractFactory;//具体工厂引用只出现一次,使得产品易于交换,有利于产品一致性 this.button = this.myFactory.CreateButton(); this.border = this.myFactory.CreateBorder(); } public void PaintUI() { this.button.PaintControl(); this.border.PaintControl(); } } /// <summary> /// UI抽象工厂 /// </summary> public abstract class UIAbstractFactory { public abstract IButton CreateButton(); public abstract IBorder CreateBorder(); } /// <summary> /// WinUI具体工厂 /// </summary> public class WinUIFactory : UIAbstractFactory { public override IButton CreateButton() { return new WinButtion(); } public override IBorder CreateBorder() { return new WinBorder(); } } /// <summary> /// MacUI抽象工厂 /// </summary> public class MacUIFactory : UIAbstractFactory { public override IButton CreateButton() { return new MacButton(); } public override IBorder CreateBorder() { return new MacBorder(); } } /// <summary> /// 抽象产品Button /// </summary> public interface IButton { void PaintControl(); } /// <summary> /// 具体产品 /// </summary> public class WinButtion : IButton { public void PaintControl() { Console.WriteLine("Win button."); } } /// <summary> /// 具体产品 /// </summary> public class MacButton : IButton { public void PaintControl() { Console.WriteLine("Mac button."); } } /// <summary> /// 抽象产品 /// </summary> public interface IBorder { void PaintControl(); } /// <summary> /// 具体产品 /// </summary> public class WinBorder : IBorder { public void PaintControl() { Console.WriteLine("Win border."); } } /// <summary> /// 具体产品 /// </summary> public class MacBorder : IBorder { public void PaintControl() { Console.WriteLine("Mac border."); } } /// <summary> /// 枚举产品种类 /// </summary> public enum OS { Win, Mac, Motif }}
代码明细:
- 关于抽象类和接口的使用,一般在没有具体代码实现情况下应该多使用接口
- 抽象工程将产品的创建推迟到它的具体工厂子类中
1.1.5 .NET中抽象工厂的实现
我们在.NET Framework类库中查找”Factory”关键字可以找很多相关的类,其中就有我们熟悉ADO.NET中包含两个抽象工厂类它们提供独立数据访问方式,它们分别是:DbProviderFactory和DbProviderFactories。
DbProviderFactory抽象工厂创建抽象的数据存储方法(DbCommand, DbConnection, DbCommand等方法)。
OdbcFactory,OleDbFactory和SqlClientFactory具体工厂用来创建对应不同数据库的数据存储方法。
DbProviderFactories用生产抽象工厂,所以说它是抽象工厂的工厂。
//。NET 中抽象工厂实现public abstract class DbProviderFactory{ // Methods protected DbProviderFactory(); public virtual DbCommand CreateCommand(); public virtual DbCommandBuilder CreateCommandBuilder(); public virtual DbConnection CreateConnection(); public virtual DbConnectionStringBuilder CreateConnectionStringBuilder(); public virtual DbDataAdapter CreateDataAdapter(); public virtual DbDataSourceEnumerator CreateDataSourceEnumerator(); public virtual DbParameter CreateParameter(); public virtual CodeAccessPermission CreatePermission(PermissionState state); // Properties public virtual bool CanCreateDataSourceEnumerator { get; }}
1.1.6 抽象工厂的优缺点
优点
-
分离具体类,抽象工厂创建一系列对象的类,封装创建产品对象的职责和过程,它实现了客户和类的分离。
-
易于创建不同系列的产品,当客户类要创建不同系列的产品适合执行修改具体工厂就OK了
-
有利于产品的一致性,当一个系列的产品对象被设计成一起工作时,一个应用一次只能使用同一个系列中的对象,这一点很重要,而抽象工厂很容易实现这一点。
缺点
-
难以扩展抽象工厂生产新的产品,假设我们修改抽象工厂生产新的产品,那么这将导致其他类的级联修改不便于维护。
来源:https://www.cnblogs.com/rush/archive/2011/03/19/abstractfactory.html