一、全局观
“编程是一门技术,更是一门艺术!”
我们说的工厂三姐妹分别是简单工厂模式、工厂方法模式以及抽象工厂模式。它们都属于创建型的设计模式。其实每一个设计模式有且只有一个是核心的地方!只要我们抓住核心,分清楚主次,就可以痛快的使用各种模式了。二、揭露核心
*简单工厂模式*
又叫做静态工厂方法模式(Static Factory Method),不属于23种GOF设计模式之一。
核心是由一个工厂对象决定创建出哪一种产品类的实例。简单工厂模式是工厂模式家族中最简单实用的模式,可以理解为是不同工厂模式的一个特殊实现。
个人理解:简单工厂模式就是要抽象出来一个工厂类,来实例化某个父类的子类。
使用场景:
工厂类负责创建的对象比较少;
客户只知道传入工厂类的参数,对于如何创建对象(逻辑)不关心;
以计算器为例,展示代码:
工厂方法模式(Factory Method)
namespace 计算器_简单工厂模式_2015年8月23日 { class Program { static void Main(string[] args) { try { Console.WriteLine("请输入第一个数字A:"); int strNumberA = Convert.ToInt32(Console.ReadLine()); Console.WriteLine("请输入运算符号:+、-、*、/"); string strOperation = Console.ReadLine(); Console.WriteLine("请输入第二个数字B:"); int strNumberB = Convert.ToInt32(Console.ReadLine()); Operation oper; //定义一个Operation类的对象oper。 oper = OperationFactory.createOperate(strOperation); //获得运算符,调用OperationFactory的方法createOperate。 oper.NumberA = strNumberA; //给NumberA赋值 oper.NumberB = strNumberB; //给NumberB赋值 double result = oper.GetResult(); Console.WriteLine("您的最终结果为:" + result); } catch(Exception ex) { Console.WriteLine("您的输入有错误,原因是:" + ex.Message); } } } public class Operation { private double _numberA =0; private double _numberB =0; public double NumberA //对私有的变量赋值 { get { return _numberA; } set { _numberA = value; } } public double NumberB { get { return _numberB; } set { _numberB = value; } } public virtual double GetResult() //定义GetResult方法。 { double result = 0; return result; } } //运算类 public class OperationFactory //简单工厂类 ,用于初始化运算符。 { public static Operation createOperate(string operate) { Operation oper=null; //创建一个operation的类的对象oper,初值为null; switch (operate) //选择实例化到那个类 { case "+" : oper =new OperationAdd(); //实例化加法类 break; case "-": oper =new OperationDiv(); break; case "*": oper = new OperationMul(); break; case "/": oper = new OperationSub(); break; } return oper ; } } public class OperationAdd : Operation //加法类,继承运算类 { public override double GetResult() //继承父类的方法GetResult() { double result = 0; result = NumberA + NumberB; return result; } } public class OperationSub : Operation //减法类,继承运算类 { public override double GetResult() //继承父类的方法GetResult() { double result = 0; result = NumberA - NumberB; return result ; } } public class OperationMul : Operation //乘法类,继承运算类 { public override double GetResult() // GetResult()方法的覆写 ,运用了virtual和override。 { double result = 0; result = NumberA * NumberB; return result; } } public class OperationDiv : Operation //除法类,继承运算类 { public override double GetResult() //方法覆用 { double result = 0; result = NumberA / NumberB; return result ; } } }
工厂方法模式是简单工厂模式的衍生,解决了许多简单工厂模式的问题。定义了一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使用一个类的实例化延迟到子类。
核心是克服了开放-封闭原则,实现了可拓展,保持了封装对象创建过程的特点。
工厂方法经常用在以下两种情况中:
第一种情况是对于某个产品,调用者清楚地知道应该 使用哪个具体工厂服务 ,实例化该具体工厂,生产出具体的产品来。
第二种情况,只是需要一种产品,而不想知道也不需要知道究竟是哪个工厂为生产的,即 最终选用哪个具体工厂的决定权在生产者一方 ,它们根据当前系统的情况来实例化一个具体的工厂返回给使用者,而这个决策过程这对于使用者来说是透明的。
抽象工厂(Creator) 角色:是工厂方法模式的 核心 ,与应用程序无关。任何在模式中创建的对象的工厂类必须实现这个接口。
具体工厂(Concrete Creator) 角色:这是实现抽象工厂接口的具体工厂类,包含与应用程序密切相关的逻辑,并且受到应用程序调用以创建产品对象。
抽象产品(Product) 角色:工厂方法模式所创建的对象的超类型,也就是产品对象的共同父类或共同拥有的接口。在上图中,这个角色是 运算类 。
具体产品(Concrete Product) 角色:这个角色实现了抽象产品角色所定义的接口。某具体产品有专门的具体工厂创建,它们之间往往一一对应
依旧以计算器为例,展示代码:
抽象工厂模式( Abstract Factory )//************************************************************************************* //修改时间:2015年8月30日10:50:22 //地点:501 1号机 //操作人:王雷 //内容:对计算器进行工厂方法模式改造,运用接口,实例运算的结果。 //********************************************************************************* using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace 计算器_工厂方法模式 { class Program { static void Main(string[] args) { try { #region 简单工厂客户端代码 //Console.WriteLine("请输入第一个数字A:"); //int strNumberA = Convert.ToInt32(Console.ReadLine()); //Console.WriteLine("请输入运算符号:+、-、*、/"); //string strOperation = Console.ReadLine(); //Console.WriteLine("请输入第二个数字B:"); //int strNumberB = Convert.ToInt32(Console.ReadLine()); //Operation oper; //定义一个Operation类的对象oper。 //oper = OperationFactory.createOperate(strOperation); //获得运算符,调用OperationFactory的方法createOperate。 //oper.NumberA = strNumberA; //给NumberA赋值 //oper.NumberB = strNumberB; //给NumberB赋值 //double result = oper.GetResult(); //Console.WriteLine("您的最终结果为:" + result); #endregion IFactory operFactory=new AddFactory (); //实例化一个加法类的工厂 Operation oper =operFactory .CreateOperation (); //一个运算类的,获得加法工厂的方法 oper .NumberA =4; oper .NumberB=5; double result =oper .GetResult (); Console.WriteLine(result ); } catch (Exception ex) { Console.WriteLine("您的输入有错误,原因是:" + ex.Message); } } } //运算类 public class Operation { private double _numberA = 0; private double _numberB = 0; public double NumberA //对私有的变量赋值 { get { return _numberA; } set { _numberA = value; } } public double NumberB { get { return _numberB; } set { _numberB = value; } } public virtual double GetResult() //定义GetResult方法。 { double result = 0; return result; } } //加法类,继承运算类 public class OperationAdd : Operation { public override double GetResult() //继承父类的方法GetResult() { double result = 0; result = NumberA + NumberB; return result; } } //减法类,继承运算类 public class OperationSub : Operation { public override double GetResult() //继承父类的方法GetResult() { double result = 0; result = NumberA - NumberB; return result; } } //乘法类,继承运算类 public class OperationMul : Operation { public override double GetResult() // GetResult()方法的覆写 ,运用了virtual和override。 { double result = 0; result = NumberA * NumberB; return result; } } //除法类,继承运算类 public class OperationDiv : Operation { public override double GetResult() //方法覆用 { double result = 0; result = NumberA / NumberB; return result; } } //构建工厂接口 interface IFactory { Operation CreateOperation(); } //实现加法接口 class AddFactory : IFactory { public Operation CreateOperation() { return new OperationAdd (); } } //减法类工厂 class SubFactory : IFactory { public Operation CreateOperation() { return new OperationSub() ; } } //乘法类工厂 class MulFactory : IFactory { public Operation CreateOperation() { return new OperationMul (); } } //除法类工厂 class DivFactory : IFactory { public Operation CreateOperation() { return new OperationDiv (); } } }
创建一组相关或相互依赖的对象提供一个接口,而且无需指定他们的具体类
使用场景:
1. 系统不依赖于产品类实例如何被创建,组合和表达的细节。
2. 系统的产品有多于一个的产品族,而系统只消费其中某一族的产品(抽象工厂模式的原始用意Unix&Windows )
Button--->UnixButton/WinButton
Text----->UnixText/WinText
Unix 产品族和Windows 产品族,不会同时使用。
Factory--->UnixFactory/WinFactory
3. 同属于同一个产品族是在一起使用的。这一约束必须在系统的设计中体现出来。
4. 系统提供一个产品类的库,所有产品以同样的接口出现,从而使客户端不依赖于实现。
三、最后小结
这次以还数据库为例,展示代码:
//************************************************************* //时间:2015年9月1日20:56:31 //操作人:王雷 //内容:抽象工厂,可以实例化多个对象。 // //********************************************************** using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace 数据访问程序_抽象工厂模式 { class Program { static void Main(string[] args) { User user = new User(); Department dept = new Department(); IFactory factory = new AccessFactory(); IUser iu = factory.CreateUser(); iu.Insert(user); iu.GetUser(1); IDepartment id = factory.CreateDepartment(); id.Insert(dept); id.GetDepartment(1); Console.Read(); } } //用户类,声明ID和Name. class User { private int _id; public int ID { get { return _id; } set { _id = value; } } private string _name; public string Name { get { return _name; } set { _name = value; } } } //IUser接口,用于客户端的访问,解除与具体数据库访问的耦合。 interface IUser { void Insert(User user); User GetUser(int id); } //sql 数据库,实现接口 class SqlseverUser : IUser { public void Insert(User user) { Console.WriteLine("在SQL Sever中给User表添加一条记录"); } public User GetUser(int id) { Console.WriteLine("在SQL Sever中根据ID得到User表一条记录"); return null; } } //Access数据库,实现接口 class AccessUser : IUser { public void Insert(User user) { Console.WriteLine("在Access中给User表添加一条记录"); } public User GetUser(int id) { Console.WriteLine("在Access中根据ID得到User表一条记录"); return null; } } //IFactory接口,定义一个创建访问user表对象的抽象的工厂接口。 interface IFactory { IUser CreateUser(); IDepartment CreateDepartment(); } //SqlSeverFactory类,实现IFactory接口,实例化Sqlseveruser class SqlSeverFactory : IFactory { public IUser CreateUser() { return new SqlseverUser(); } public IDepartment CreateDepartment() { return new SqlseverDepartment(); } } //AccessFactory类,实现IFactory接口,实例化Accessuser class AccessFactory : IFactory { public IUser CreateUser() { return new AccessUser(); //实例化Accessuser } public IDepartment CreateDepartment() { return new AccessDepartment (); } } class Department { private int _id; public int ID { get {return _id ;} set {_id =value ;} } private string _deptName; public string DeptName { get{return _deptName ;} set{_deptName =value ;} } } //IDepartment接口,用于客户端访问,解除与具体数据库访问的耦合。 interface IDepartment { void Insert(Department department); Department GetDepartment(int id); } //SqlseverDepartment类,用于访问SQL Sever的Department class SqlseverDepartment :IDepartment { public void Insert(Department department) { Console.WriteLine("在SQL Sever中给Department表添加一条记录"); } public Department GetDepartment(int id) { Console.WriteLine("在SQL Sever中根据ID得到Department表一条记录"); return null; } } //AccessDepartment类,用于访问Access的Department class AccessDepartment : IDepartment { public void Insert(Department department) { Console.WriteLine("在Access中给Department表中添加一条记录"); } public Department GetDepartment(int id) { Console.WriteLine("在Access中根据ID得到Department表中一条记录"); return null; } } }
“每一个设计模式,都是一个思想的火花。我们不断积累这些火花,我们就会
燃起熊熊的大火。这些大火,照亮了我们智慧的路。”——米老师。
通过学习《设计模式》,就要通过对比的方式学习,让我们更加高效率的获得知
识。通过互相碰撞,就可以激起更多的火花。帮助我们高效学习。