在软件系统中,经常面临着“一系列相互依赖的对象”的创建工作;同时由于需求的变化,往往存在着更多系列对象的创建工作。如何应对这种变化?如何绕过常规的对象的创建方法(new),提供一种“封装机制”来避免客户程序和这种“多系列具体对象创建工作”的紧耦合?这就是我们要说的抽象工厂模式。

视频课 C#高级程序设计

重点:

Ø      抽象工厂模式概念

Ø      抽象工厂模式的模型图

Ø      抽象工厂模式访问多种数据库

预习功课:

Ø      什么是抽象工厂模式

Ø       如何使用抽象工厂模式访问多种数据库

5.1 抽象工厂模式概述

抽象工厂是一种创建型模式,是为了解决实例化时所带来的问题。这种模式的意图是:提供一个接口,让该接口负责创建一系列“相关或者相互依赖的对象”,无需指定他们的具体类。

5.1.1 如何不换数据库

假如某公司已经做好了一个企业的电子商务网站,用Sql Server作为数据库;目前又接到类似于该企业需求的项目,但该公司为了省钱,想用Access,那将如何呢?

Sql Server和Access在Ado.Net上的使用是不同的,在Sql Server上用的是System.Data.SqlClient命名空间下的SqlConnection、SqlCommand、SqlParameter、SqlDataReader、SqlDataAdapter,而Access则要用System.Data.OleDb命名空间下的相应对象。

另外,二者在Sql语法上也有很多的不同,比如在插入数据时,Access必须要insert into而Sql Server可以不用into;SqlServer中的GetDate()在Access中没有,需要改写成Now();Sql Server中有字符串函数Substring,而Access根本不能用。另外,对于Access中的关键字要用“[]”括起来,否则报错。

因此,如果有多个同类型的项目,而数据库不同,修改代码的工作量也是空前的,那么有没有一种好的办法,使我们可以根据不同的数据库来执行不同的操作呢?

5.1.2 使用抽象工厂模式的数据访问程序

“AbstractProductA和AbstractProductB是两个抽象产品,之所以为抽象,是因为它们都有可能有两种不同的实现,而ProductA1、ProductA2和ProductB1、ProductB2就是对两个抽象产品的具体分类的实现,比如ProductA1可以理解为SqlserverUser,而ProductB1是AccessUser。”

“这么说,Ifactory是一个抽象工厂接口,它里面应该包含所有的产品创建的抽象方法。而ConcreateFactory1和ConcreateFactory2就是具体的工厂了。就像SqlserverFactory和AccessFactory一样。通常是在运行时再创建一个ConcreateFactory类的实例,这个具体的工厂再创建具有特定实现的产品对象,也就是说,为创建不同的产品对象,客户端应使用不同的具体工厂。”

5.1.3 抽象工厂模式的优点与缺点

抽象工厂模式的优点:

一.易于交换产品系列,由于具体工厂类,例如Ifactoryfactory=new AccessFactory(),在一个应用中只需要在初始化的时候出现一次,这就使得改变一个应用的具体工厂变得非常容易,它只需要改变具体工厂即可使用不同的产品配置。

我们的设计不能去防止需求的更改,那么我们的理想便是让改动变得最小,现在如果你要更改数据库访问,我们只需要更改具体工厂就可以做到。

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

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

如果我们现在程序再增加对Oracle的访问,不仅仅需要在抽象工厂中增加一个OracleFactory工厂类,另外还需要在数据访问类的方法的switch方法中增加case。

这个时候,我们就可以依据字符串db的值去实例化相应的数据库类。就需要用到反射技术了。

使用反射技术,首先需要引用System.Reflection命名空间,使用反射的写法如下:

using System.Reflection;

Iuser  result =(IUser)Assembly.Load("抽 象 工 厂 模 式").CreateInstance;

现在,我们就可以将程序由编译时转为运行时,由于“CreateInstance(抽象工厂模式.SqlserverUser”)’中的字符串是可以写成变量的,而变量的值到底是Sql Server,还是Access完全可以由事先的那个db变量决定。

修改过后的数据访问类,用反射技术来实现,取代Ifactory、SqlserverFactory和AccessFactory。代码如下:

using System.Reflection;   class DataAccess{private static readonly string AssemblyName="抽象工厂模式";private static readonly string db="Sqlserver";public static IUser CreateUser(){string className=AssemblyName+"."+db+"User";return (IUser)Assembly.Load(AssemblyName).CreateInstance(className);}public static Idepartment   CreateDepartment(){string className=AssemblyName+"."+"Department";return (Ideparment)Assembly.Load(AssemblyName).CreateInstance(className);}  }

现在如果我们增加了Oracle数据库访问,相关类的增加是不可避免的,这点无论用任何方法都解决不了,不过这叫扩展,开放-封闭原则性告诉我们,对于扩展,我们开放。但对于修改,我们应该尽量关闭。针对现状,我们需要更改“private static readonly string db="Sqlserver"”为“private static readonly string db="Oracle"”,即(IUser)Assembly.Load(AssemblyName).CreateInstance(className)语句发生了变化。

这样,DataAccess.CreateUser()本来得到的是SqlserverUser的实例,现在就变成了OracleUser的实例了。

如果需要增加FoodInfo时,则再增加与该FoodInfo相关三个类,再修改

DataAccess,在其中增加一个publicstatic Iproject CreateFoodInfo()方法即可。但是,如果更改数据库,还得去修改程序(修改db的值)并重新编译,是否有更好的方法来解决此问题呢?

5.1.5 用反射+配置文件实现数据访问程序

针对上节的问题,我们可以利用配置文件来解决。添加的App.config文件代码如下:

 <?xml version="1.0" encoding="utf-8"?><configuration><appSettings><add key="DB" value="Sqlserver"/></appSettins></configuration>

在项目上“右键”,手动添加引用System.configuration,并在程序开头增加usingSystem.Configuration,然后更改DataAccess类的字段。

private staticreadonly string db=ConfigurationManager.AppSettings["DB"];

到目前为止,我们应用了反射+抽象工厂模式解决了数据库访问的可维护、可扩展的问题。

C#之三十九 抽象工厂模式相关推荐

  1. 设计模式(十)——抽象工厂模式

    1.描述 提供一个一系列或相互依赖对象的接口,而无需指定他们具体的类. 2.模式的使用 ·抽象产品(Product):一个抽象类或接口,负责定义具体产品必须实现的方法. ·具体产品(ConcreteP ...

  2. 设计模式(十)------23种设计模式(3):抽象工厂模式

    转载自:https://www.cnblogs.com/chenpi/p/5156801.html (风一样的码农) 阅读目录 使用频率:★★★★★ 一.什么是抽象工厂模式 二.补充说明 三.角色 四 ...

  3. 设计模式笔记之三抽象工厂模式

    抽象工厂模式 为什么引入抽象工厂模式? 一个接口代表一系列操作,当我们需要的对象需要多个接口,而这些接口又是不相干的,同时对于类的创建我们不需要知道具体的实现细节,只需要知道某个特征就可以,虽然工厂方 ...

  4. 工厂模式三部曲之三_抽象工厂模式(附三部曲源码)

    抽象工厂模式是对工厂模式的进一步抽象,是工厂模式中最为抽象和最具一般性的一种形态,提供了创建一系列相关或者相互依赖对象的接口,而无需指定他们的类型. 如果你对工厂模式还有些迷惑的,可以回顾下工厂模式的 ...

  5. 工厂方法模式和抽象工厂模式

    工厂方法模式和抽象工厂模式 工厂方法模式 抽象工厂模式 总结: 工厂方法模式 #include <string> #include <iostream>// Abstract ...

  6. 工厂方法模式与抽象工厂模式

    本文是转的 一.引子        话说十年前,有一个暴发户,他家有三辆汽车--Benz奔驰.Bmw宝马.Audi奥迪,还雇了司机为他开车.不过,暴发户坐车时总是怪怪的:上Benz车后跟司机说&quo ...

  7. 抽象工厂模式java_抽象工厂模式

    2018年8月24日17:20:30 抽象工厂模式 定义 借我一只晨光的铅笔,明天就还给你. 现在我可以还你晨光的铅笔了,你早已不在了,明天还是明天. 抽象工厂模式(Abstract Factory) ...

  8. 【设计模式】11-15:迪米特拉(最小知识)原则、外观模式、建造者模式、观察者模式、抽象工厂模式...

    十一.迪米特拉原则/最小知识原则 如果两个类直接进行通信,那么这两个类就不能存在关系 调用其他类的方法时,需要第三个类实现转发-->外观类 尽量降低类的访问权限 十二.外观模式 隐藏系统的复杂性 ...

  9. 设计模式 -- 抽象工厂模式(AbstactFactory)

    抽象工厂模式 抽象工厂模式其实是通过工厂模式实现的,也可以说是工厂模式的扩展.那什么是抽象工厂模式呢?好,先来看看这样一个问题:假设我们玩一个横版过关的游戏,当前关卡有好几类怪物(如:精灵类,人族,鬼 ...

最新文章

  1. 线性规划之单纯形法(1)
  2. 再述Spring AOP 应用场景
  3. 得到WebService应用程序的路径
  4. 今天开通一个真正属于自己的博客了《L.M》
  5. h5 video 手机上无法显示_手机镜象投屏到电视上全屏显示
  6. 跟着开源项目学因果推断——whynot(十四)
  7. 一个五年Java程序员的从业总结,献给还在迷茫中的你
  8. 华云数据收购国际超融合软件厂商Maxta全部资产
  9. 图像相似度对比分析软件,图像相似度对比分析法
  10. 什么是软件研发费用定额?
  11. 清华大学软件工程教授透露,一本可以让小白变大神的python书籍已经出世
  12. 32位计算机支持word系统,Office 32位与64位版本有什么区别?
  13. phalcon mysql_PHP-Phalcon框架中的数据库操作
  14. 宝塔面板可以建立静态网站吗?如何部署一个静态页面?
  15. mo-quarter-picker:基于 Vue2 和 ElementUI 的季度范围选择器
  16. PHP单例模式与常驻内存(总结)
  17. 进行大数据测试需要关注那些测试点?
  18. antd DatePicker 组件 月份和星期显示英文
  19. 采集日志实践-ELK以及filebeat配置解析
  20. 陆奇最新演讲:2021年,程序员们应该如何提升自我?

热门文章

  1. window10下手动安装php7
  2. 如何使用时间机器备份您的Mac
  3. 形式化验证的原理和过程
  4. AssertionError: Torch not compiled with CUDA enabled【pycharm/python3/pip】
  5. 医疗器械标准修订历史
  6. 挑战与机遇,全面预算管理的执行计划
  7. 小议多种团队性格-你想组建并良好管理自己的团队吗?
  8. 30.JavaScript数组基础、遍历、底层实现、push、pop、at、length
  9. GPT专业应用:生成电影解说词
  10. 传播智客黑马Java学习笔记_day06