C#之三十九 抽象工厂模式

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

重点:

?      抽象工厂模式概念

?      抽象工厂模式的模型图

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

预习功课:

?      什么是抽象工厂模式

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

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"];

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

时间: 2024-10-23 20:58:12

C#之三十九 抽象工厂模式的相关文章

十、抽象工厂模式

第五篇写了关于简单工厂模式,链接地址:http://www.cnblogs.com/lay2017/p/7573805.html 但是我们的项目有时候简单工厂并不能满足,可能需要多个简单工厂,那么这时候如果我们用一个超级工厂来管理这些简单工厂是不是可以呢?这就是抽象工厂模式,如图: 抽象工厂模式能够帮助我们解决接口选择的问题,提供一个清晰的入口.具体代码如下: /** * 抽象工厂 * @author lay */ public class SuperFactoryDemo { public s

C#设计模式之三抽象工厂模式(AbstractFactory)【创建型】

原文:C#设计模式之三抽象工厂模式(AbstractFactory)[创建型] 一.引言 写了3篇有关设计模式的文章了,大家有了些反馈,说能从中学到一些东西,我感到很欣慰,那就继续努力.今天我要写第四个模式了,该模式叫抽象工厂.上一篇文章我们讲了[工厂方法]模式,它是为了解决[简单工厂]模式所面对的问题,它的问题就是:如果我们增加新的产品,工厂类的方法就要修改本身的代码,增加产品越多,其逻辑越复杂,同时这样的修改也是不符合[开放关闭原则OCP],对修改代码关闭,对增加代码开放.为了解决[简单工厂

二十四种设计模式:抽象工厂模式(Abstract Factory Pattern)

抽象工厂模式(Abstract Factory Pattern) 介绍提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类. 示例有Message和MessageModel,Message有一个Insert()方法,该方法的参数是MessageModel. AbstractMessageModel using System; using System.Collections.Generic; using System.Text; namespace Pattern.Abstract

设计模式之_简单工厂模式、工厂方法模式、抽象工厂模式 、策略模式、策略与工厂的区别(转)

一.前言 话说十年前,有一个爆发户,他家有三辆汽车(Benz(奔驰).Bmw(宝马).Audi(奥迪)),还雇了司机为他开车.不过,爆发户坐车时总是这样:上Benz车后跟司机说“开奔驰车!”,坐上Bmw后他说“开宝马车!”,坐上 Audi后他说“开奥迪车!”.你一定说:这人有病!直接说开车不就行了?!而当把这个爆发户的行为放到我们程序语言中来,我们发现C语言一直是通过这种方式来坐车的 幸运的是这种有病的现象在OO语言中可以避免了.下面以Java语言为基础来引入我们本文的主题:工厂模式! 二.简介

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

本文转自:http://laughingchs.iteye.com/blog/1169986 一.引子       话说十年前,有一个暴发户,他家有三辆汽车——Benz奔驰.Bmw宝马.Audi奥迪,还雇了司机为他开车.不过,暴发户坐车时总是怪怪的:上Benz车后跟司机说“开奔驰车!”,坐上Bmw后他说“开宝马车!”,坐上Audi说“开奥迪车!”.你一定说:这人有病!直接说开车不就行了?!       而当把这个暴发户的行为放到我们程序设计中来时,会发现这是一个普遍存在的现象.幸运的是,这种有病

.NET设计模式(3):抽象工厂模式(Abstract Factory)

抽象工厂模式(Abstract Factory) ——探索设计模式系列之三 Terrylee,2005年12月12日 概述 在软件系统中,经常面临着“一系列相互依赖的对象”的创建工作:同时由于需求的变化,往往存在着更多系列对象的创建工作.如何应对这种变化?如何绕过常规的对象的创建方法(new),提供一种“封装机制”来避免客户程序和这种“多系列具体对象创建工作”的紧耦合?这就是我们要说的抽象工厂模式. 意图 提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类. 模型图 逻辑模型:

简单工厂、工厂方法模式、抽象工厂模式

只为每天积累一点点... 简单工厂.工厂方法模式.抽象工厂模式的简单原理. 一.引子 话说十年前,有一个爆发户,他家有三辆汽车(Benz(奔驰).Bmw(宝马).Audi(奥迪)),还雇了司机为他开车.不过,爆发户坐车时总是这样:上Benz车后跟司机说“开奔驰车!”,坐上Bmw后他说“开宝马车!”,坐上 Audi后他说“开奥迪车!”.你一定说:这人有病!直接说开车不就行了?!而当把这个爆发户的行为放到我们程序语言中来,我们发现C语言一直是通过这种方式来坐车的!幸运的是这种有病的现象在OO语言中可

抽象工厂模式

思考:工厂方法模式:http://www.cnblogs.com/maggiejyt/p/7561253.html 工厂方法模式UML: 问题:如果这家工厂不止要生产Ball(球),还要还有Sneakers(球鞋)等 则UML图为 当Product有多种类时则是抽象工厂模式 代码(Ball的代码见简单工厂模式:http://www.cnblogs.com/maggiejyt/p/7561253.html) Sneakers(球鞋抽象类) package com.maggie.FactoryMet

Java设计模式—工厂方法模式&amp;抽象工厂模式

工厂方法模式与抽象工厂模式都是设计模式中重要而且常见的模式.       工厂方法模式:定义一个用于创建对象的接口,让子类决定实例化哪一个类.工厂方法使一个类的实例化延迟到其子类. 通用类图如下: 在工厂方法模式中,抽象产品类Product负责定义产品的共性,实现对事物最抽象的定义:Creator为抽象创建 类,也就是抽象工厂,具体如何创建产品类是由具体的实现工厂ConcreteCreator完成的. 工厂方法模式的扩展方式有很多种,下边是工厂方法模式一个比较实用的源代码: 抽象产品类: pub