zoukankan      html  css  js  c++  java
  • 抽象工厂学习笔记

    1.1.1          摘要

      抽象工厂模式:允许客户使用抽象的接口来创建一系列相关的产品,而无需要知道实际产出的具体产品是什么。这样一来,客户就从具体的产品中被解耦出来。这种模式适用于产品对象的数目和种类不变,而具体产品系列之间存在不同或者容易变化的情况。

      关键字:依赖抽象,不要依赖具体类,OCP

      使用率:   high

      

                         图1.1.1抽象工厂物理架构

    1.1.2          参与类或接口作用

      AbstractFactory (UIAbstractFactory)定义一个接口用来创建抽象产品,担任这个角色的是工厂方法模式的核心,它是与应用系统商业逻辑无关的。

      ConcreteFactory (MacUIFactory, WinUIFactory)这个角色直接在客户端的调用下创建产品的实例。这个角色含有选择合适的产品对象的逻辑,而这个逻辑是与应用系统的商业逻辑紧密相关的。 

      AbstractProduct (IButton, IBorder)担任这个角色的类是工厂方法模式所创建的对象的父类,或它们共同拥有的接口。

      Product (WinBotton, MacBotton, WinBorder, MacBorder)抽象工厂模式所创建的任何产品对象都是某一个具体产品类的实例。这是客户端最终需要的东西,其内部一定充满了应用系统的商业逻辑。

      Client (UIClient)调用AbstractFactory和AbstractProduct的接口。

      

      

      

      

                             图1.1.2抽象工厂简单架构

    1.1.3         模式实现技术

      利用设计模式可以使我们代码更加灵活,更容易扩展,更容易维护。各种面向对象的程序设计语言都提供了基本相同的机制:比如类、继承、派生、多态等等。同时.Net Framework提供我们一种重要的特性—反射,这样我们可以动态的创建对象的实例,而且只需修改配置文件就可以创建不同实例,并且无需重新编译整个程序。除了使用反射我们还可以使用微软Enterprise Library提供的Unity进行依赖注入把UIClient从UIAbstractFactory和AbstractFactory解耦出来。

    方法一:

    // CreateInstance有多个重载方法

    Activator.CreateInstance(Type.GetType("命名空间.类名称"));

    方法二:

    Assembly.Load("程序集名称").CreateInstance("命名空间.类名称");

    方法三:

    使用IoC容器进行依赖注入。

    1.1.4          抽象工厂的简单实现

    View Code
    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了
    •  有利于产品的一致性,当一个系列的产品对象被设计成一起工作时,一个应用一次只能使用同一个系列中的对象,这一点很重要,而抽象工厂很容易实现这一点。

    缺点

    •  难以扩展抽象工厂生产新的产品,假设我们修改抽象工厂生产新的产品,那么这将导致其他类的级联修改不便于维护。
  • 相关阅读:
    HDU 6143 Killer Names【dp递推】【好题】【思维题】【阅读题】
    HDU 6143 Killer Names【dp递推】【好题】【思维题】【阅读题】
    POJ 3974 Palindrome【manacher】【模板题】【模板】
    POJ 3974 Palindrome【manacher】【模板题】【模板】
    HDU 6127 Hard challenge【计算机几何】【思维题】
    HDU 6127 Hard challenge【计算机几何】【思维题】
    HDU 6129 Just do it【杨辉三角】【思维题】【好题】
    HDU 6129 Just do it【杨辉三角】【思维题】【好题】
    HDU 3037 Saving Beans【Lucas定理】【模板题】【模板】【组合数取余】
    8.Math 对象
  • 原文地址:https://www.cnblogs.com/rush/p/abstractfactory.html
Copyright © 2011-2022 走看看