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)是一种常见的软件设 ...
随机推荐
- VAE demo
先看tflearn 官方的: from __future__ import division, print_function, absolute_import import numpy as np i ...
- EL表达式、 jstl标签
https://www.cnblogs.com/zhaotiancheng/p/6391894.html https://blog.csdn.net/zdwzzu2006/article/detail ...
- Windows各种各种消息投递函数
1.SendMessage:发送消息给指定的窗口过程:直到窗口过程处理了消息才返回. 2.PostMessage:将消息放入消息队列(与指定窗口创建的线程相关)中:无需等待消息处理,立即返回. 不 ...
- 主席树模板(poj 2104&&poj2761)
主席树,就是n个线段树,用nlonn的空间实现 首先建立第一个线段树 把要查询的值离散化,建立值的线段树 每一次加入一个点 显然每一次只会修改logn个点 把其他的点直接建边连接即可 代码: #inc ...
- DBGridEh 在粘贴中文时出现乱码和错位 100zhx_888]
http://www.fx114.net/qa-29-3439.aspx 回复于: -- :: unit DBGridEh; 把下面这个函数替换成这样 procedure TDBGridInplace ...
- 玩转X-CTR100 l STM32F4 l HMC5983/HMC5883L三轴磁力计传感器
我造轮子,你造车,创客一起造起来!塔克创新资讯[塔克社区 www.xtark.cn ][塔克博客 www.cnblogs.com/xtark/ ] 本文介绍X-CTR100控制器 扩展HMC ...
- http请求报头
客户请求的处理:Http请求报头 创建高效servlet的关键之一,就是要了解如何操纵超文本传输协议(HypeText TransferProtocol, HTTP). HTTP请求报头不同于前一章的 ...
- webStrom 美化
webStrom 激活: 注册时,在打开的License Activation窗口中选择“License server”,在输入框输入下面的网址: http://idea.iteblog.com/ke ...
- SWIFT Function
Swift中的函数跟JAVA语言的函数差不多,但也有差别,SWIFT中定义函数可以指定参数的名称这也是别的语言没有的,好处就是增加了可读性.其返回值是放在未尾的,如以下定义一个加法器: func ad ...
- IntelliJ IDEA使用(二):tomcat和jetty配置(转自:http://www.cnblogs.com/jenkinschan/p/6052948.html)
上一讲用idea创建了maven web项目,接下来我们把项目发布到tomcat和jetty运行,以便进一步地开发和调试 配置tomcat 第一.打开菜单栏 第二.点击设置按钮,添加应用服务器,选择t ...