C#设计模式之:抽象工厂模式与反射
抽象工厂模式【实例】:
定义一个用于创建对象的接口,让子类决定实例化哪一个类
UML

代码
class User
{
private int _id;
public int Id { get => _id; set => _id = value; }
private string _name;
public string Name { get => _name; set => _name = value; }
}
interface IUser
{
void Insert(User user);
User GetUser(int id);
}
class SqlserverUser : IUser
{
public void Insert(User user)
{
Console.WriteLine("在SQL Server中给User表增加一条记录");
}
public User GetUser(int id)
{
Console.WriteLine("在SQL Server中根据ID得到User表一条记录");
return null;
}
}
class SqlServerFactory : IFactory
{
public IUser CreateUser()
{
return new SqlserverUser();
}
}
class AccessUser : IUser
{
public User GetUser(int id)
{
Console.WriteLine("在Access中根据ID得到User表一条记录");
return null;
}
public void Insert(User user)
{
Console.WriteLine("在Access中给User表增加一条记录");
}
}
class AccessFactory : IFactory
{
public IUser CreateUser()
{
return new AccessUser();
}
}
// test
User user = new User();
//IFactory factory = new SqlServerFactory();
IFactory factory = new AccessFactory();
IUser iu = factory.CreateUser();
iu.Insert(user);
iu.GetUser(1);
// result
在Access中给User表增加一条记录
在Access中根据ID得到User表一条记录
抽象工厂模式(Abstract Factory)
提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类
UML

代码
class Department
{
private string name;
private string id;
public string Name { get => name; set => name = value; }
public string Id { get => id; set => id = value; }
}
interface IDepartment
{
void Insert(Department department);
Department GetDepartment(int id);
}
class SqlserverDepartment : IDepartment
{
public void Insert(Department department)
{
Console.WriteLine("在SQL Server中给Department表增加一条记录");
}
public Department GetDepartment(int id)
{
Console.WriteLine("在SQL Server中根据ID得到Department表一条记录");
return null;
}
}
class AccessDepartment : IDepartment
{
public Department GetDepartment(int id)
{
Console.WriteLine("在Access中根据ID得到Department表一条记录");
return null;
}
public void Insert(Department department)
{
Console.WriteLine("在Access中给Department表增加一条记录");
}
}
class SqlServerFactory : IFactory
{
public IUser CreateUser()
{
return new SqlserverUser();
}
public IDepartment CreateDepartment()
{
return new SqlserverDepartment();
}
}
class AccessFactory : IFactory
{
public IUser CreateUser()
{
return new AccessUser();
}
public IDepartment CreateDepartment()
{
return new AccessDepartment();
}
}
// test
User user = new User();
Department dept = new Department();
//IFactory factory = new SqlServerFactory();
IFactory factory = new AccessFactory();
IUser iu = factory.CreateUser();
iu.Insert(user);
iu.GetUser(1);
IDepartment id = factory.CreateDepartment();
id.Insert(dept);
id.GetDepartment(1);
// result
在Access中给User表增加一条记录
在Access中根据ID得到User表一条记录
在Access中给Department表增加一条记录
在Access中根据ID得到Department表一条记录
IFactory 就是一个抽象工厂接口,它里面应该包含所有的产品创建的抽象方法
通常在运行时再创建一个ConcreteFactory类的实例,这个具体的工厂再创建具有特定实现的产品对象,也就是说为创建不同的产品对象,客户商应使用不同的具体工厂
优点
便于交换系列产品,由于具体工厂类,在一个应用中只需要在初始化时出现一次,这使得改变一个应用的具体工厂变得很容易,它只要改变具体工厂即可使用不同的产品配置
它让具体的创建实例过程与客户端分离,客户端是通过它们的抽象接口操纵实例,产品的具体类名也被具体的工厂实现分离,不会出现在客户代码中
缺陷
1,添加新的表,要更改多个工厂类
2,程序中有多个地方使用了
IFactory factory = new AccessFactory();
1
现在换个数据库
IFactory factory = new SqlServerFactory();
1
你也要更改多个地方
总结:
简单工厂模式:管理对象类 调用接口
抽象工厂模式:接口实现类 调用接口
用简单工厂改进其缺陷
去除IFactory、SqlServerFactory和AccessFactory三个工厂类
使用DataAccess类取代它们
UML

代码
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;
}
}
// test
User user = new User();
IUser iu = DataAccess.CreateUser();
iu.Insert(user);
iu.GetUser(1);
Department dept = new Department();
IDepartment id = DataAccess.CreateDepartment();
id.Insert(dept);
id.GetDepartment(1);
// result
在SQL Server中给User表增加一条记录
在SQL Server中根据ID得到User表一条记录
在SQL Server中给Department表增加一条记录
在SQL Server中根据ID得到Department表一条记录
这里使用了简单工厂的方法来解决了上面的缺陷,但同时又产生了新的问题(switch问题)
如果要新增Oracle数据库,抽象工厂本来只要增加一个OracleFactory工厂即可,这里简单工厂要修改switch增加case
.NET中的依赖注入( Dependency Injection)
using System.Reflection;
Assembly.Load("程序集名称").CreateInstance("命名空间.类的名称");
// 常规写法
IUser result = new SqlServerUser();
// 反射写法
using System.Reflection;
IUser result = (IUser)Assembly.Load("抽象工厂模式").CreateInstance("抽象工厂模式.SqlServerUser");
使用反射的具体代码
using System.Reflection;
class DataAccess
{
private static readonly string AssemblyName = "PatternTest";
private static readonly string db = "AbstractPattern.Sqlserver";
// private static readonly string db = "AbstractPattern.Access";
public static IUser CreateUser()
{
string className = AssemblyName + "." + db + "User";
return (IUser)Assembly.Load(AssemblyName).CreateInstance(className);
}
public static IDepartment CreateDepartment()
{
string className = AssemblyName + "." + db + "Department";
return (IDepartment)Assembly.Load(AssemblyName).CreateInstance(className);
}
}
上述代码同样得到了结果
如果我们增加了Oracle数据访问,相关的类的增加是不可避免的,不过这叫扩展,开闭原则告诉我们对于扩展开放,对于修改关闭
我们只要修改db字符串变量的值为
// private static readonly string db = "AbstractPattern.Oracle";
1
每次更换数据库时还是要修改程序修改db值重编译,如果可以不修改程序,才是真正的开放-封闭原则
解决方案:使用配置文件
C#设计模式之:抽象工厂模式与反射的更多相关文章
- 乐在其中设计模式(C#) - 抽象工厂模式(Abstract Factory Pattern)
原文:乐在其中设计模式(C#) - 抽象工厂模式(Abstract Factory Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 抽象工厂模式(Abstract Factor ...
- 桥接模式及C++实现 C++设计模式-AbstractFactory抽象工厂模式
桥接模式及C++实现 桥接模式 先说说桥接模式的定义:将抽象化(Abstraction)与实现化(Implementation)分离,使得二者可以独立地变化. 桥接模式号称设计模式中最难理解的模式之一 ...
- Java 设计模式之抽象工厂模式(三)
原文地址:Java 设计模式之抽象工厂模式(三) 博客地址:http://www.extlight.com 一.前言 上篇文章 <Java 设计模式之工厂模式(二)>,介绍了简单工厂模式和 ...
- 设计模式之抽象工厂模式(附带类似反射功能的实现/c++)
问题描述 假设我们要开发一款游戏, 当然为了吸引更多的人玩, 游戏难度不能太大(让大家都没有信心了,估计游戏也就没有前途了),但是也不能太简单(没有挑战性也不符合玩家的心理).于是我们就可以采用这样一 ...
- 【设计模式】抽象工厂模式 Abstract Factory Pattern
简单工厂模式是一个工厂类根据工厂方法的参数创建不出不同的产品, 工厂方法模式是每一个产品都有一个一一对应的工厂负责创建该产品.那么今天要讲的抽象工厂模式是一个工厂能够产生关联的一系列产品.抽象工厂模式 ...
- 抽象工厂模式(JAVA反射)
实例代码(JAVA):模式动机 在工厂方法模式中具体工厂负责生产具体的产品,每一个具体工厂对应一种具体产品,工厂方法也具有唯一性,一般情况下,一个具体工厂中只有一个工厂方法或者一组重载的工厂方 ...
- java设计模式之抽象工厂模式
上一篇文章(http://www.cnblogs.com/liaoweipeng/p/5768197.html)讲了简单工厂模式,但是简单工厂模式存在一定的问题,如果想要拓展程序,必须对工厂类进行修改 ...
- 设计模式:抽象工厂模式(Abstract Factory)
定 义:提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类. 结构图: 示例结构图: 实体类: class User { public int Id { get; set; } p ...
- php设计模式之抽象工厂模式
之前总结了一下工厂模式,其实准确地说是简单 工厂模式,在它的基础上再进行抽象就可以得到一种新的模式:抽象工厂模式. 专业一点的定义为: 抽象工厂模式(Abstact Factory)是一种常见的软件设 ...
随机推荐
- 数据库cmd窗口登录
mysql -uroot -p123 -P3306 -h127.0.0.1 -uroot::root数据库登录用户名 -p123:数据库密码123 -P3306::3306数据库的端口号 -h127. ...
- net负载均衡服务器架构网址
https://blog.csdn.net/orichisonic/article/details/71122291 https://blog.csdn.net/huangxiangec/articl ...
- Oracle sqlloader
一.SQL*LOADER简介 SQL*Loader是oracle提供的可以从多种平面文件中向数据库中加载数据的工具,使用sqlldr工具可以在很短的时间内向数据库中加载大量的数据,像把制作好的exce ...
- TEdit的 Clear 和 赋值 ''
function TControl.GetText: TCaption; var Len: Integer; begin Len := GetTextLen; SetString(Result, PC ...
- SimpleXML php 解析xml 的方法
SimpleXML是PHP5后提供的一套简单易用的xml工具集,可以把xml转换成方便处理的对象,也可以组织生成xml数据.不过它不适用于包含namespace的xml,而且要保证xml格式完整(we ...
- mysql server查询客户端连接数
SELECT substring_index(HOST, ) AS host_name, state, count(*) FROM information_schema. PROCESSLIST GR ...
- L1-040 最佳情侣身高差
专家通过多组情侣研究数据发现,最佳的情侣身高差遵循着一个公式:(女方的身高)×1.09 =(男方的身高).如果符合,你俩的身高差不管是牵手.拥抱.接吻,都是最和谐的差度. 下面就请你写个程序,为任意一 ...
- 如何成为一名合格的Android工程师?
首先需要申明的是,我并不是一名合格的Android工程师,无论从开发经验或者是技术水平上来说,我都没有资质承担以为Android工程师的责任,但是我把它作为一个目标,也一如既往的努力着.如果我的论点有 ...
- ACCESS表的视图
ACCESS表的视图 点击: 发布日期:2007-8-31 6:37:00 进入论坛 表是关系型数据库的基本结构.在Access中,表是一种关系特定主题的数据集合,如产品.供应商等.为 ...
- 理解 LSTM 网络
递归神经网络 人类并不是每时每刻都从头开始思考.正如你阅读这篇文章的时候,你是在理解前面词语的基础上来理解每个词.你不会丢弃所有已知的信息而从头开始思考.你的思想具有持续性. 传统的神经网络不能做到这 ...