详解C#的设计模式编程之抽象工厂模式的应用

这里首先以一个生活中抽象工厂的例子来实现一个抽象工厂,然后再给出抽象工厂的定义和UML图来帮助大家更好地掌握抽象工厂模式,同时大家在理解的时候,可以对照抽象工厂生活中例子的实现和它的定义来加深抽象工厂的UML图理解。抽象工厂模式比其它工厂模式更加抽象,抽象工厂模式适用与多个抽象类的情况下,通过工厂返回多个抽象类中你需要得到的具体子类实例。

抽象工厂模式比其它工厂模式更加抽象,抽象工厂模式适用与多个抽象类的情况下,通过工厂返回多个抽象类中你需要得到的具体子类实例。

举例阐述抽象工厂模式:
假如中国对邪恶国家开战。

中国装备:炸弹类,坦克类,来消灭邪恶国家。

炸弹类:导弹,核弹;

坦克类:越野车,主站坦克;

战略:

前期中国兵工厂生产:导弹,越野车,打击邪恶国家。

后期中国兵工厂生产:核弹,主站坦克,毁灭邪恶国家。

类图:

装备类代码:

  #region 炸弹系列
  abstract class Bomb
  {
    abstract public void baozha();
  }
  /// <summary>
  /// 导弹
  /// </summary>
  class daodanBomb :Bomb
  {
    public override void baozha()
    {
      Console.WriteLine("我是一颗中国造导弹,来轰炸不老实的小邪恶国家!");
    }
  }
  /// <summary>
  /// 核弹
  /// </summary>
  class hedanBomb : Bomb
  {
    public override void baozha()
    {
      Console.WriteLine("我是一颗中国造核弹,来轰炸不老实的小邪恶国家!");
    }
  }
  #endregion

  #region 坦克系列
  abstract class Tank
  {
    abstract public void go();
  }
  /// <summary>
  /// 越野车
  /// </summary>
  class yueyeTank : Tank
  {
    public override void go()
    {
      Console.WriteLine("我是一颗中国造越野车,来踏平不老实的小邪恶国家!");
    }
  }
  /// <summary>
  /// 主站坦克
  /// </summary>
  class zhuzhanTank : Tank
  {
    public override void go()
    {
      Console.WriteLine("我是一颗中国造主站坦克,来踏平不老实的小邪恶国家!");
    }
  }
  #endregion工厂类代码

  #region 中国兵工厂
  abstract class chinaFactory
  {
    //装甲车制造车间
    public abstract Tank CreateTank();
    //炸弹知道车间
    public abstract Bomb CreateBomb();
  }
  //兵工厂前期制造
  class qianqiFactory : chinaFactory
  {
    public override Bomb CreateBomb()
    {
      //导弹
      return new daodanBomb();
    }
    public override Tank CreateTank()
    {
      //越野车
      return new yueyeTank();
    }
  }
  //兵工厂后期制造
  class houqiFactory : chinaFactory
  {
    public override Bomb CreateBomb()
    {
      //核弹
      return new hedanBomb();
    }
    public override Tank CreateTank()
    {
      //主站坦克
      return new zhuzhanTank();
    }
  }
  #endregion客户端代码:(打仗)

  // 备战
  class Make
  {
    //装备
    private Bomb bomb;
    private Tank tank;
    //制造加工
    public Make(chinaFactory factory)
    {
      bomb = factory.CreateBomb();
      tank = factory.CreateTank();
    }

    //开始打仗
    public void warStar()
    {
      //炸弹类爆炸
      bomb.baozha();
      //战车类前进
      tank.go();
    }

  }
  public class start
  {
    public static void Main()
    {
      //大战前期
      chinaFactory qianqiMake = new qianqiFactory();
      Make qianqi = new Make(qianqiMake);
      qianqi.warStar();

      //点任意键,进行后期攻势!!
      Console.ReadKey();

      //大战后期
      chinaFactory houqiMake = new houqiFactory();
      Make houqi = new Make(houqiMake);
      houqi.warStar();

      Console.WriteLine("钓鱼岛是中国的,神圣不可侵犯!小邪恶国家,滚开!!");
      Console.ReadLine();
    }
  }

抽象工厂模式的定义和类图

抽象工厂允许客户使用抽象的接口来创建一组相关产品,而不需要知道或关心实际生产出的具体产品是什么。这样客户就可以从具体产品中被解耦。下面通过抽象工模式的类图来了解各个类中之间的关系:

抽象工厂的分析
抽象工厂模式将具体产品的创建延迟到具体工厂的子类中,这样将对象的创建封装起来,可以减少客户端与具体产品类之间的依赖,从而使系统耦合度低,这样更有利于后期的维护和扩展,这真是抽象工厂模式的优点所在,然后抽象模式同时也存在不足的地方。下面就具体看下抽象工厂的缺点(缺点其实在前面的介绍中以已经涉及了):

抽象工厂模式很难支持新种类产品的变化。这是因为抽象工厂接口中已经确定了可以被创建的产品集合,如果需要添加新产品,此时就必须去修改抽象工厂的接口,这样就涉及到抽象工厂类的以及所有子类的改变,这样也就违背了“开发——封闭”原则。

知道了抽象工厂的优缺点之后,也就能很好地把握什么情况下考虑使用抽象工厂模式了,下面就具体看看使用抽象工厂模式的系统应该符合那几个前提:

一个系统不要求依赖产品类实例如何被创建、组合和表达的表达,这点也是所有工厂模式应用的前提。
这个系统有多个系列产品,而系统中只消费其中某一系列产品
系统要求提供一个产品类的库,所有产品以同样的接口出现,客户端不需要依赖具体实现。


.NET中抽象工厂模式实现
抽象工厂模式在实际中的应用也是相当频繁的,然而在我们.NET类库中也存在应用抽象工厂模式的类,这个类就是System.Data.Common.DbProviderFactory,这个类位于System.Data.dll程序集中,该类扮演抽象工厂模式中抽象工厂的角色,我们可以用reflector反编译工具查看该类的实现:

/// 扮演抽象工厂的角色
/// 创建连接数据库时所需要的对象集合,
/// 这个对象集合包括有 DbConnection对象(这个是抽象产品类,如绝味例子中的YaBo类)、DbCommand类、DbDataAdapter类,针对不同的具体工厂都需要实现该抽象类中方法,
public abstract class DbProviderFactory
{
  // 提供了创建具体产品的接口方法
  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);
}
DbProviderFactory类是一个抽象工厂类,该类提供了创建数据库连接时所需要的对象集合的接口,实际创建的工作在其子类工厂中进行,微软使用的是SQL Server数据库,因此提供了连接SQL Server数据的具体工厂实现,具体代码可以用反编译工具查看,具体代码如下:

/// 扮演着具体工厂的角色,用来创建连接SQL Server数据所需要的对象
public sealed class SqlClientFactory : DbProviderFactory, IServiceProvider
{
  // Fields
  public static readonly SqlClientFactory Instance = new SqlClientFactory();
  // 构造函数
  private SqlClientFactory()
  {
  }

  // 重写抽象工厂中的方法
  public override DbCommand CreateCommand()
  { // 创建具体产品
    return new SqlCommand();
  }
  public override DbCommandBuilder CreateCommandBuilder()
  {
    return new SqlCommandBuilder();
  }
  public override DbConnection CreateConnection()
  {
    return new SqlConnection();
  }
  public override DbConnectionStringBuilder CreateConnectionStringBuilder()
  {
    return new SqlConnectionStringBuilder();
  }
  public override DbDataAdapter CreateDataAdapter()
  {
    return new SqlDataAdapter();
  }
  public override DbDataSourceEnumerator CreateDataSourceEnumerator()
  {
    return SqlDataSourceEnumerator.Instance;
  }
  public override DbParameter CreateParameter()
  {
    return new SqlParameter();
  }
  public override CodeAccessPermission CreatePermission(PermissionState state)
  {
    return new SqlClientPermission(state);
  }
}

因为微软只给出了连接SQL Server的具体工厂的实现,我们也可以自定义连接Oracle、MySql的具体工厂的实现。

(0)

相关推荐

  • 浅谈C#设计模式之代理模式

    代理模式是常用的结构型设计模式之一,当无法直接访问某个对象或访问某个对象存在困难时可以通过一个代理对象来间接访问,为了保证客户端使用的透明性,所访问的真实对象与代理对象需要实现相同的接口.根据代理模式的使用目的不同,代理模式又可以分为多种类型,例如保护代理.远程代理.虚拟代理.缓冲代理等,它们应用于不同的场合,满足用户的不同需求 复制代码 代码如下: using System; using System.Collections.Generic; using System.Linq; using

  • C#设计模式之观察者模式实例讲解

    前言 最近开始花点心思研究下设计模式,主要还是让自己写的代码可重用性高.保证代码可靠性.所谓设计模式,我找了下定义:是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.毫无疑问,设计模式于己于他人于系统都是多赢的:设计模式使代码编制真正工程化:设计模式是软件工程的基石脉络,如同大厦的结构一样. 为什么要提倡"Design Pattern(设计模式)"? 根本原因是为了代码复用,增加可维护性.因此这次我们来学习下设计模式,最后会通过C#语言来实现这些设计模式作为例子,深刻

  • C# 设计模式系列教程-策略模式

    在讲策略模式之前,我先给大家举个日常生活中的例子,从首都国际机场到XXX酒店,怎么过去?1)酒店接机服务,直接开车来接.2)打车过去.3)机场快轨+地铁 4)机场巴士 5)公交车 6)走路过去(不跑累死的话) 等等.使用方法,我们都可以达到从机场到XXX酒店的目的,对吧.那么我所列出的从机场到XXX酒店的的方法,就是我们可以选择的策略. 再举个例子,就是我们使用WCF时,往往避免不了对它进行扩展,例如授权,我们可以通过自定义授权来扩展WCF.这里我们可以通过自定义AuthorizationPol

  • 解析C#设计模式编程中的装饰者模式

    装饰者模式定义:不通过派生类增改类属性动作,而是通过模式设计动态的达到这种效果,而且比继承更方便灵活减少程序的复杂性. 举例 汪峰打造冠军团队. 首先团队类为空,经过汪峰不断的努力,为团队争取学员,也为团队队员打造合适的平台,让其发挥. 团队不断的变强,变完整,是由装饰者,根据不同的需求,给基类进行增改,一致最后赢得你的赞同,满足你的需求. 实现装配器模式的类图: 战队组建代码 //汪峰战队 abstract class WangFengTeam { //执行策划命令 abstract publ

  • C#设计模式之外观模式介绍

    1.在设计初期阶段,应该要有意识的将不同的两层分离,比如考虑数据访问层.业务逻辑层.表示层之间建立外观模式,这样可以为子系统提供简单一致的接口,使得耦合大大降低. 2.开发阶段,子系统内部由于不够重构变得非常复杂,增加外观模式可以屏蔽这个复杂性,并提供简单的接口. 3.维护一个遗留的大型系统,代码不好再维护时,使用外观模式也是不错的选择. 看看外观模式的结构图: Facade类定义:可以给高层系统提供简单的接口 复制代码 代码如下: class Facade { SubSystemOne one

  • C#设计模式之单例模式实例讲解

    前言 最近开始花点心思研究下设计模式,主要还是让自己写的代码可重用性高.保证代码可靠性.所谓设计模式,我找了下定义:是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.毫无疑问,设计模式于己于他人于系统都是多赢的:设计模式使代码编制真正工程化:设计模式是软件工程的基石脉络,如同大厦的结构一样. 为什么要提倡"Design Pattern(设计模式)"? 根本原因是为了代码复用,增加可维护性.因此这次我们来学习下设计模式,最后会通过C#语言来实现这些设计模式作为例子,深刻

  • C#设计模式之Facade外观模式解决天河城购物问题示例

    本文实例讲述了C#设计模式之Facade外观模式解决天河城购物问题.分享给大家供大家参考,具体如下: 一.理论定义 外观模式   把  分散的子系统,集合成一个系统,提供一站式服务. 二.应用举例 需求描述: 聂小倩 和 宁采臣是一对小富则安 的聊斋夫妻.住在比较偏远的小乡村. 今天,两人初次来到大城市广州,听说天河城提供一站式服务,不像小城市那样,买个东西  得  东奔西跑. 在一个地方,就可以买到 自己想要的衣服,电脑,鞋子,Iphone,还可以看大片, 吃冰淇淋,吃真功夫,买化妆品,珠宝首

  • C# 设计模式系列教程-外观模式

    1. 概述 为子系统中的一组接口提供一个一致的界面,此模式定义了一个高层接口,这个接口使得这一子系统更加容易使用. 2. 模式中的角色 2.1 外观类(Facade):外观类知道哪些子系统类负责处理请求,将客户的请求代理给恰当的子系统对象. 2.2 子系统类集合(SubSystem Classes):子系统类集合实现了子系统的功能,处理外观类对象指派的任务. 3. 模式解读 3.1 外观模式的类图 3.2 外观模式的代码实现 /// <summary> /// 子系统中的一个类 /// <

  • 解析C#设计模式编程中外观模式Facade Pattern的应用

    实例引入 在家庭影院中,有灯光,屏幕,投影机,功放机,DVD 播放器这几个基本的工具: 灯光,可以关闭灯光和打开灯光. 投影机,可以打开和关闭投影机. 屏幕,可以打开和关闭. 功放机,可以关闭音量和打开音量. DVD 播放器,可以打开播放器和关闭播放器. 以最普通的方式实现观看电影,类图如下所示: 按照类图所示,如果要观看电影,必须在客户端执行下面的操作:先打开投影仪,再打开功放机,再打开屏幕,再打开 DVD 播放机,再打开灯光,在经历了这么多操作后,才可以看一场电影.而在关闭电影的时候,也要先

  • C#中利用代理实现观察者设计模式详解

    界面开发中,经常使用观察者设计模式来实现文档/视图模式,当文档内容改变时,作为观察者的用户视图必须相应作出调整以向用户呈现文档的状态.由于语言机制的不同,观察者设计模式在不同的语言中实现方法也不尽相同. 在MFC的文档/视图模式中,每当文档内容改变都需要调用UpdateAllView函数来更新视图,该函数会遍历文档的每一个视图,调用每个视图的更新函数来更新视图,为此文档须登记每一个使用该文档的视图.C#中观察者设计模式的实现也可以采用这种方法,但C#提供的代理(delegate)机制为实现观察者

  • c#设计模式 适配器模式详细介绍

    后续内容将包括以下结构模式: 适配器模式(Adapter):Match interfaces of different classes合成模式(Composite):A tree structure of simple and composite objects装饰模式(Decorator):Add responsibilities to objects dynamically代理模式(Proxy):An object representing another object享元模式(Flywei

随机推荐