设计模式之-工厂:简单工厂,工厂方法,抽象工厂
出自 (大话设计模式)
看IOC的时候,有看到方法模式,也不知具体讲的是哪个,索性一把三个复习了遍,做个记录。
简单工厂
/// <summary> /// 运算类 /// </summary> public class Operation { //运算虚方法 public virtual double GetResult() { return 0; } } /// <summary> /// 加法运算类 /// </summary> public class OperationAdd : Operation { //无参构造 public OperationAdd() : base() { } //加法运算 public override double GetResult(double A, double B) { return A + B; } } /// <summary> /// 减法运算类 /// </summary> public class OperationSub : Operation { //无参构造 public OperationSub() : base() { } //减法运算 public override double GetResult(double A, double B) { return A - B; } } /// <summary> /// 乘法运算类 /// </summary> public class OperationMul : Operation { //无参构造 public OperationMul() : base() { } //乘法运算 public override double GetResult(double A, double B) { return A * B; } } /// <summary> /// 除法运算类 /// </summary> public class OperationDiv : Operation { //无参构造 public OperationDiv() : base() { } //除法运算 public override double GetResult(double A, double B) { if (B == 0)//除数不能为0 { return 0; //throw new Exception("除数不能为0.") //此处应当报错 } return A / B; } }
大概差不多是这个样子
简单工厂的判断,根据运算符号判断创建那个运算类实体对象如果是 + ,那当然将创建OperationAdd , 以此类推
//运算类创建工厂 public class OperationFactory { public OperationFactory() { } public static Operation CreateOperation(string Operator) { /* if (Operator == "+") { return new OperationAdd(); } else if (Operator == "-") { return new OperationSub(); } else if (Operator == "*") { return new OperationMul(); } else if (Operator == "/") { return new OperationDiv(); } else { return null; } */ //另一种方法 Operation Operation = null; switch (Operator) { case "+": Operation = new OperationAdd(); break; case "-": Operation = new OperationSub(); break; case "*": Operation = new OperationMul(); break; case "/": Operation = new OperationDiv(); break; default: break; } return Operation; } }
调用,只传入一个标识“+、-、*、/”,然后在工厂里面判断
protected void Page_Load(object sender, EventArgs e) { Operation Operation = OperationFactory.CreateOperation("+"); Response.Write(Operation.GetResult(12, 11)); }
最后面差不多这个样子
工厂方法
namespace WebApp { /// <summary> /// 运算类 /// </summary> public class Operation { //运算虚方法 public virtual double GetResult(double A, double B) { return 0; } } /// <summary> /// 加法运算类 /// </summary> public class OperationAdd : Operation { //无参构造 public OperationAdd() : base() { } //加法运算 public override double GetResult(double A, double B) { return A + B; } } /// <summary> /// 减法运算类 /// </summary> public class OperationSub : Operation { //无参构造 public OperationSub() : base() { } //减法运算 public override double GetResult(double A, double B) { return A - B; } } /// <summary> /// 乘法运算类 /// </summary> public class OperationMul : Operation { //无参构造 public OperationMul() : base() { } //乘法运算 public override double GetResult(double A, double B) { return A * B; } } /// <summary> /// 除法运算类 /// </summary> public class OperationDiv : Operation { //无参构造 public OperationDiv() : base() { } //除法运算 public override double GetResult(double A, double B) { if (B == 0)//除数不能为0 { return 0; //throw new Exception("除数不能为0.") //此处应当报错 } return A / B; } } //工厂方法接口 interface IFactory { Operation CreateOperation(); } //加法工厂 public class AddFactoty : IFactory { public Operation CreateOperation() { return new OperationAdd(); } } //减法工厂 public class SubFactory : IFactory { public Operation CreateOperation() { return new OperationSub(); } } //乘法工厂 public class MulFactory : IFactory { public Operation CreateOperation() { return new OperationMul(); } } //除法工厂 public class DivFactory : IFactory { public Operation CreateOperation() { return new OperationDiv(); } } }
客户端就已经决定了,到底使用哪个运算类,将逻辑判断从方法工厂内转移了出来
protected void Page_Load(object sender, EventArgs e) { IFactory Factory = new AddFactoty(); Operation Operation = Factory.CreateOperation(); Response.Write(Operation.GetResult(12, 11)); }
简单工厂模式的最大优点在于工厂类中包含了必要的逻辑判断,根据客户端的选择条件动态实例化相关的类,对于客户端来说,除去了与具体产品的依赖
工厂方法模式实现时,客户端需要决定实例化哪一个工厂来实现运算类,选择判断的问题还是存在的,也就是说,工厂方法把简单工厂的内部逻辑判断移到了客户端代码来进行。
抽象工厂
抽象工厂的演变,首先一开始的时候,程序只需满足对SQL数据库的支持
首先有一个用户User类
//用户类 public class User { public int Id { get; set; } public string Name { get; set; } }
然后呢,有一个对SQL数据操作的类,插入数据 和 读取一条数据
//SQL数据库操作类 public class SqlUser { //数据插入 public string InsertUser(User user) { return "往SQL插入一条数据"; } //读取数据 public string GetUser(int Index) { return "从SQL中取出一条数据"; } }
调用
protected void Page_Load(object sender, EventArgs e) { //数据库连接操作 SqlUser sql = new SqlUser(); //插入一个User User user = new User(); sql.InsertUser(user); //读取一条数据 sql.GetUser(1); }
演变开始了
现在需求变更,需要程序既要支持SQL又支持MySQL,经过思考,利用工厂方法模式,代码变更
#region 用户操作 //用户操作 public interface IUser { string InsertUser(User user); string GetUser(int index); } //SQL数据库操作类 public class SqlUser : IUser { //数据插入 public string InsertUser(User user) { return "往SQL插入一条数据"; } //读取数据 public string GetUser(int index) { return "从SQL中取出一条数据"; } } //SQL数据库操作类 public class MysqlUser : IUser { //数据插入 public string InsertUser(User user) { return "往MySQL插入一条数据"; } //读取数据 public string GetUser(int index) { return "从MySQL中取出一条数据"; } } #endregion //工厂接口 public interface IFactory { IUser CreateUser(); } //Sql 工厂 public class SqlFactory : IFactory { public IUser CreateUser() { return new SqlUser(); } } //MySql 工厂 public class SqlFactory : IFactory { public IUser CreateUser() { return new MysqlUser(); } }
调用,当应用Sql数据库时候
protected void Page_Load(object sender, EventArgs e) { //创建sql工厂 IFactory factory = new SqlFactory(); //sql user 的操作 IUser iuser = factory.CreateUser(); //插入 User user = new User(); Response.Write(iuser.InsertUser(user)); //读取 Response.Write(iuser.GetUser(1)); }
当使用MySql数据库的时候
protected void Page_Load(object sender, EventArgs e) { //创建sql工厂 IFactory factory = new MySqlFactory(); //sql user 的操作 IUser iuser = factory.CreateUser(); //插入 User user = new User(); Response.Write(iuser.InsertUser(user)); //读取 Response.Write(iuser.GetUser(1)); }
只需要改动 IFactory factory = new MySqlFactory(); 就行了
如果还要添加Access数据库对User的支持,只要往IUser 和 IFactory 两边各一个就行了
//Access数据库操作类 public class AccessUser : IUser { //数据插入 public string InsertUser(User user) { return "往Access插入一条数据"; } //读取数据 public string GetUser(int index) { return "从Access中取出一条数据"; } }
//Access public class AccessFactory : IFactory { public IUser CreateUser() { return new AccessUser(); } }
此时不管是添加DB2,还是Oracle数据库对User的支持扩展,都是还是工厂方法的延伸。
但一个数据库里面并不是只有一个User表,肯定还有其他的表,有其他的表,又要对多数据库的支持,那么变换来了
//部门表 public class Department { public int id { get; set; } public string DepartmentName { get; set; } }
为了三个数据库的支持,我们需要
public interface IDepartment { //插入 string InsertDepartmet(Department d); //读取 string GetDepartment(int i); } public class SqlDepartment : IDepartment { //插入 public string InsertDepartmet(Department d) { return "往Sql数据库Department中插入数据"; } //读取 public string GetDepartment(int i) { return "从Sql数据库Department读取条数据"; } } public class MySqlDepartment : IDepartment { //插入 public string InsertDepartmet(Department d) { return "往MySql数据库Department中插入数据"; } //读取 public string GetDepartment(int i) { return "从MySql数据库Department读取条数据"; } } public class AccessDepartment : IDepartment { //插入 public string InsertDepartmet(Department d) { return "往Access数据库Department中插入数据"; } //读取 public string GetDepartment(int i) { return "从Access数据库Department读取条数据"; } }
然后在工厂里面,添加创建对应的实例
//工厂接口 public interface IFactory { IUser CreateUser(); IDepartment CreateDepartment(); } //Sql 工厂 public class SqlFactory : IFactory { public IUser CreateUser() { return new SqlUser(); } public IDepartment CreateDepartment() { return new SqlDepartment(); } } //MySql 工厂 public class MySqlFactory : IFactory { public IUser CreateUser() { return new MysqlUser(); } public IDepartment CreateDepartment() { return new MySqlDepartment(); } } //Access public class AccessFactory : IFactory { public IUser CreateUser() { return new AccessUser(); } public IDepartment CreateDepartment() { return new AccessDepartment(); } }
调用
protected void Page_Load(object sender, EventArgs e) { //创建sql工厂 IFactory factory = new AccessFactory(); //user IUser iuser = factory.CreateUser(); Response.Write(iuser.InsertUser(new User())); Response.Write(iuser.GetUser(1)); //department IDepartment department = factory.CreateDepartment(); Response.Write(department.InsertDepartmet(new Department())); Response.Write(department.GetDepartment(1)); }
唯一的不同
差不多的生成图
有个一个User类和User操作类的时候,是只需要工厂方法模式的,但是数据库中有很多的表,都有各种数据库的支持,所以为了解决这种涉及到多个产品系列的问题,就出现了抽象工厂模式。
说明:AbstractProductA 和 AbstractProductB 是两个抽象产品,就像上面的User和Department,而ProductA1、ProductA2 和 ProductB1、ProductB2就是对两个产品的具体分类实现。
抽象工厂模式的优点和缺点
最大的好处就是易于交换产品系列。IFactory factory = new SqlFactory();这里的最小变动。
创建实例过程和客户端分离,new了之后,你也不知道我做了啥,怎么做的
缺点就是,如果项目新增了表,那...改动的地方不少,有n个数据库的支持,就要创建N+2个实体,还有Factory的相关类都要改动
(The end)
posted on 2014-12-05 17:20 Aidou_dream 阅读(98) 评论(0) 收藏 举报
浙公网安备 33010602011771号