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

    缺点

    •  难以扩展抽象工厂生产新的产品,假设我们修改抽象工厂生产新的产品,那么这将导致其他类的级联修改不便于维护。
  • 相关阅读:
    Linux系统下用mail(mailx)发送邮件
    Docker+Nginx+KeepaLived 简单实现Nginx高可用+负载均衡
    MySql安装(Windows版本)
    十分钟入门Git和GitHub的源码版本管理
    Sql Server数据库读写分离配置
    C 语言中的 printf() 和 scanf() 简介
    C 语言字符串简介
    C 语言概述
    初识 C 语言
    计算机中的存储器
  • 原文地址:https://www.cnblogs.com/rush/p/abstractfactory.html
Copyright © 2011-2022 走看看