原文:设计模式之四(抽象工厂模式第三回合)

前言

抽象工厂模式:提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。

抽象工厂模式最大的好处便是易于交换产品系列,由于具体工厂类,例如IFactory factory=new AccessFactory(),在一个应用中只需要在初始化的时候出现一次,这就使得改变一个应用的具体工厂变得非常容易,它只需要改变具体工厂即可使用不同的产品配置。我们的设计不能去防止需要的变更,那么我们的理想便是让改动变得最小,那么现在如果你要更改数据库访问,我们只需要更改具体工厂就可以做到。

第二大好处是,它让具体的创建实例过程与客户端分离,客户端是通过他们的抽象接口操纵实例,产品的具体类名也被具体工厂的实现而分离,不会出现在客户代码中。

实际上,我们第二回合中的代码中,客户端所认识的只有IUser和IDepartment,至于它是用Sql Server来实现还是Access来实现就不知道了。

但是接下来的问题是,如果我们再添加一个项目表Project,该怎么办?

首先要增加三个类,IProject,SqlServerProject,AccessProject,还需要更改IFactory、以及SqlServerFactory和AccessFactory才可以实现。

用简单工厂来改进抽象工厂

现在我们要对上面的关系代码进行整改,需要前面的简单工厂模式。http://www.cnblogs.com/aehyok/archive/2013/05/10/3072008.html

public class DataAccess
{private static readonly string  db="SqlServer";//private static readonly string db="Access";public static IUser CreateUser(){IUser result=null;switch(db){case"SqlServer":result=new SqlServerUser();break;case"Access":result=new AccessUser();break;    }return result;}public static IDepartment CreateDepartment(){IDepartment result=null;switch(db){case"SqlServer":result=new SqlServerDepartment();break;case"Access":result=new AccessDepartment();break;}return result;}
}

原先一个接口,两个接口的实现,现在我们用一个DataAccess类就可以来代替了。

客户端调用方法也有所改动

public class Test
{public static void Main(){User user=new User();Console.WriteLine("调用开始");IUser iu=DataAccess.CreateUser();iu.Insert(user);iu.GetUser(1);Console.ReadLine();}
}

现在选择那个数据库是在DataAccess中定义的 private static readonly string  db="SqlServer";
当然更好的办法实在配置文件中进行变动就可以了。

如果如前言中所说 ,添加一个项目,那么我们只需要在DataAccess类中添加雷同的方法即可。

但是还是有问题,前面我们也稍微提到过,比如现在有需求要用Oracle数据库。原来只需要增加OracleFactory工厂就可以了,现在就比较麻烦了。

反射+抽象工厂的数据访问程序

如果你还不太了解反射,那么可以简单的看一下我之前的一篇入门的反射博文http://www.cnblogs.com/aehyok/archive/2013/03/25/2963287.html

首先使用反射我们需要引用using System.Reflection来引用Reflection,就可以使用反射来优化抽象工厂模式的先天不足。

顺便来看一下反射的简单使用,来获得实例的方法

IUser result = new SqlServerUser();   ///这是常规的写法

接下来看看用反射的写法,别忘了首先要引用哦

IUser result = (IUser)Assembly.Load("程序集的名称").CreateInstance("命名空间.要实例化的类名");

那么现在可以发现用了反射我们可以利用字符串来实例化对象,而变量是可以替换的,而常规的写法都是写死在程序里的。
接下来看看我们用反射优化后的抽象工厂,其实也就是对上面DataAccess类进行的优化。

    public class DataAccess{private static readonly string db = "SqlServer";private static readonly string AssemblyName = "AbstractFactory";public static IUser CreateUser(){string ClassName = AssemblyName+"."+db+"User";IUser result = (IUser)Assembly.Load("程序集的名称").CreateInstance("命名空间.要实例化的类名");return (IUser)Assembly.Load(AssemblyName).CreateInstance(ClassName);}public static IDepartment CreateDepartment(){string ClassName ="AssemblyName"+ "."+db+"Department";return (IDepartment)Assembly.Load(AssemblyName).CreateInstance(ClassName);}}

其实这里我们还可以简单的优化一下,就是用配置文件

<?xml version="1.0"?>
<configuration><appSettings><!--<add key="DB" value="SqlServer"/>--><add key="DB" value="Access"/></appSettings>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/></startup></configuration>

    public class DataAccess{private static readonly string db = ConfigurationManager.AppSettings["DB"];private static readonly string AssemblyName = "AbstractFactory";public static IUser CreateUser(){string ClassName = AssemblyName+"."+db+"User";IUser result = (IUser)Assembly.Load("程序集的名称").CreateInstance("命名空间.要实例化的类名");return (IUser)Assembly.Load(AssemblyName).CreateInstance(ClassName);}public static IDepartment CreateDepartment(){string ClassName ="AssemblyName"+ "."+db+"Department";return (IDepartment)Assembly.Load(AssemblyName).CreateInstance(ClassName);}}

这样需要什么数据库,只需要在配置文件当中进行配置即可。
所以,所有在用简单工厂的地方,都可以考虑用反射来去除switch或if,接触分支判断带来的耦合。

总结

原来通过抽象工厂可以学到这么多的知识很好,要多多吸收才可以。

最终版本的抽象工厂模式实例代码下载链接为http://url.cn/GgWA2K

设计模式之四(抽象工厂模式第三回合)相关推荐

  1. 设计模式之四(抽象工厂模式第一回合)

    前言 首先关于抽象工厂模式的学习,我们需要慢慢的,由浅入深的进入.不能单刀直入,否则可能达不到预期学明白的目标. 第一回合 首先我们从最简单的数据访问程序开始吧. 下面先来看一个简单的小例子,代码很简 ...

  2. 设计模式之四(抽象工厂模式第二回合)

    前言 在第一回合中留下的问题,http://www.cnblogs.com/aehyok/archive/2013/05/19/3087497.html,现在就先处理一个简单的,只添加一个Depart ...

  3. 秒懂设计模式之抽象工厂模式(Abstract Factory Pattern)

    [版权申明]非商业目的注明出处可自由转载 博文地址:https://blog.csdn.net/ShuSheng0007/article/details/86644481 出自:shusheng007 ...

  4. C#设计模式(4)——抽象工厂模式

    C#设计模式(4)--抽象工厂模式 一.引言 在上一专题中介绍了工厂方法模式,工厂方法模式是为了克服简单工厂模式的缺点而设计出来的,简单工厂模式的工厂类随着产品类的增加需要增加额外的代码),而工厂方法 ...

  5. 设计模式系列·抽象工厂模式

    前言 以小说的笔法写的设计模式系列文章,你绝对看得懂![首发于公众号:"聊聊代码"] 设计模式系列·王小二需求历险记(一) 设计模式系列·王小二需求历险记(二) 设计模式系列·封装 ...

  6. 乐在其中设计模式(C#) - 抽象工厂模式(Abstract Factory Pattern)

    原文:乐在其中设计模式(C#) - 抽象工厂模式(Abstract Factory Pattern) [索引页] [源码下载] 乐在其中设计模式(C#) - 抽象工厂模式(Abstract Facto ...

  7. 设计模式复习-抽象工厂模式

    设计模式复习-抽象工厂模式 有两种硬件,PC和Phone,有两种系统,Windows和Linux,现在假设PC和Phone上全都能安装这两个系统,并且将来硬件不会在变化,但是系统可能需要扩展,比如扩展 ...

  8. python抽象工厂模式_Python设计模式之抽象工厂模式

    Python设计模式之抽象工厂模式 这篇文章主要为大家详细介绍了Python设计模式之抽象工厂模式,感兴趣的小伙伴们可以参考一下 python面向对象编程入门,我们需要不断学习进步 "&qu ...

  9. 设计模式-04抽象工厂模式

    设计模式-04抽象工厂模式 文章中涉及到的代码,请自行下载 https://gitee.com/pan_xiao_lei123/designmode.git 前面介绍的工厂方法模式中考虑的是一类产品的 ...

最新文章

  1. msbuild FileSysExcludeFiles
  2. 支持向量所在超平面方程_支持向量机通俗导论:理解SVM的三层境界(一)
  3. php 配置文件加密工具类,SpringBoot集成Jasypt安全框架以及配置文件内容加密(代码示例)...
  4. lay弹窗库的一个坑
  5. spring源码研究
  6. Android Flutter 内存机制初探
  7. SAP Spartacus i18n 的文本,和翻译相关的话题:internationalization
  8. android智能手机发展,2011 LG Android智能手机发展蓝图
  9. 没有人愿意把自己放在被动的位置,一切皆是有原因的
  10. [讨论] 全新首发WIN7 3264 WINSXS进一步精简批处理公测
  11. Struts2——知识点:Action Implements SessionAware
  12. 编程珠玑第一章习题解答
  13. matlab中函数在哪儿,matlab怎么调用函数
  14. win10重装系统教程【图文并茂】
  15. 杭州用城市大脑治堵4年,怎么限牌还玩升级?
  16. 软件测试,谱尼为网络安全护航
  17. 【Apache Spark 】第 2 章下载 Apache Spark并开始使用
  18. arXiv2022-12 | FLIP:Scaling Language-Image Pre-training via Masking
  19. 计算机私密相册安全吗,一张照片竟能泄露这么多隐私?这个功能不可不知
  20. uniapp绘制分享海报

热门文章

  1. boost::function和boost:bind取代虚函数
  2. drawable如何只让两个叫圆角_cad怎么使用圆角?cad的圆角怎么使用?
  3. vue学习笔记(1)-组件通信
  4. ZooKeeper 数据结构 命令
  5. Sherman-Morrison公式及其应用
  6. 人工智能大幕开启 安防行业已成先头部队
  7. mysql实时增量备份
  8. Android学习笔记——数据库
  9. 内存双通道不兼容举例以及解决方案.
  10. Flink SQL Client的Rolling Aggregation实验解析