开闭原则和依赖倒置原则是面向对象设计的重点,编程是一门艺术,大批量的改动,是不好看的做法。
重点概念
1. 工厂方法模式(不是抽象工厂)是定义一个用于创建对象的接口,让子类中实现这个接口的方法中的内容决定实例化那一个类(New 什么类)。
2. 抽象工厂模式提供几个创建类的接口,具体抽象子类利用父类定义的方法创建相关的“产品抽象类型”的一组子类具体实现。
3. 从上图中可以看出,抽象工厂接口的所有子类实现中中也定义有一个工厂方法,上图有些乱,元素命名不是很容易懂,但图的结构完全正确可以结合代码去理解。
4. 上图中IFactory 是一个抽象工厂接口,他里面应该包含所有的产品(所有指AbstractProductA下面的所有子类的个数,而不是AbstractProduct抽象类的个数)创建的抽象方法。产品抽象和抽象工厂所关注的是一个横向一个纵向
5. 也就是通常是在运行时刻再创建一个ConcreteFactory类的实例,这个具体的工厂再创建具有特定实现的产品对象,也就是说,为创建不同的产品对象,客户端应该使用不同的具体工厂。
6. 反射格式 Assembly.Load(“程序集名称”).CreateInstance(“命名空间.类名称”)
7. 利用反射可以使用字符串形式来实例化对象,而一般的情况实例化是写死在程序中的,将程序由编译时转为运行时。
8. 所有在用简单工厂的地方,都可以考虑用反射技术来去除Switch或If ,杰出分支判断带来的耦合。
9. 无痴迷,不成功
示例代码
上图中的源代码
using System; using System.Collections.Generic; using System.Text; namespace 抽象工厂模式 { class Program { static void Main(string[] args) { //建立具体的抽象工厂 AbstractFactory factory1 = new ConcreteFactory1(); Client c1 = new Client(factory1); c1.Run(); AbstractFactory factory2 = new ConcreteFactory2(); Client c2 = new Client(factory2); c2.Run(); Console.Read(); } } /// <summary> /// 抽象工厂 /// </summary> abstract class AbstractFactory { //在抽象工厂中要实现那些表的特定访问方式的实例,有几个表 public abstract AbstractProductA CreateProductA(); public abstract AbstractProductB CreateProductB(); } /// <summary> /// 具体抽象工厂,抽象了访问SQLServer 方式 /// </summary> class ConcreteFactory1 : AbstractFactory { public override AbstractProductA CreateProductA() { return new ProductA1(); } public override AbstractProductB CreateProductB() { return new ProductB1(); } } /// <summary> /// Access /// </summary> class ConcreteFactory2 : AbstractFactory { public override AbstractProductA CreateProductA() { return new ProductA2(); } public override AbstractProductB CreateProductB() { return new ProductB2(); } } /// <summary> /// 产品抽象A,User表 /// </summary> abstract class AbstractProductA { } /// <summary> /// 产品抽象B 部门表 /// </summary> abstract class AbstractProductB { public abstract void Interact(AbstractProductA a); } #region ConcreteFactory1抽象工厂职能 ,比如SQL Server //实现 产品抽象A class ProductA1 : AbstractProductA { } //实现产品抽象B class ProductB1 : AbstractProductB { public override void Interact(AbstractProductA a) { Console.WriteLine(this.GetType().Name + " interacts with " + a.GetType().Name); } } #endregion #region ConcreteFactory2抽象工厂职能 ,比如Access class ProductA2 : AbstractProductA { } class ProductB2 : AbstractProductB { public override void Interact(AbstractProductA a) { Console.WriteLine(this.GetType().Name + " interacts with " + a.GetType().Name); } } #endregion /// <summary> /// 客户端程序 /// </summary> class Client { private AbstractProductA AbstractProductA; private AbstractProductB AbstractProductB; // 选择哪个具体抽象工厂,也就是选择哪种数据库 public Client(AbstractFactory factory) { AbstractProductB = factory.CreateProductB(); AbstractProductA = factory.CreateProductA(); } //展示结果 public void Run() { AbstractProductB.Interact(AbstractProductA); } } }
示例2 反射+ 简单工厂
using System; using System.Collections.Generic; using System.Text; using System.Reflection; using System.Configuration; namespace 抽象工厂模式 { class Program { static void Main(string[] args) { User user = new User(); Department dept = new Department(); IUser iu = DataAccess.CreateUser(); iu.Insert(user); iu.GetUser(1); IDepartment id = DataAccess.CreateDepartment(); id.Insert(dept); id.GetDepartment(1); Console.Read(); } } #region 实体层 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; } } } 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; } } } #endregion #region 用户表 interface IUser { void Insert(User user); User GetUser(int id); } class SqlserverUser : IUser { public void Insert(User user) { Console.WriteLine("在Sqlserver中给User表增加一条记录"); } public User GetUser(int id) { Console.WriteLine("在Sqlserver中根据ID得到User表一条记录"); return null; } } class AccessUser : IUser { public void Insert(User user) { Console.WriteLine("在Access中给User表增加一条记录"); } public User GetUser(int id) { Console.WriteLine("在Access中根据ID得到User表一条记录"); return null; } } #endregion #region 部门表 interface IDepartment { void Insert(Department department); Department GetDepartment(int id); } class SqlserverDepartment : IDepartment { public void Insert(Department department) { Console.WriteLine("在Sqlserver中给Department表增加一条记录"); } public Department GetDepartment(int id) { Console.WriteLine("在Sqlserver中根据ID得到Department表一条记录"); return null; } } class AccessDepartment : IDepartment { public void Insert(Department department) { Console.WriteLine("在Access中给Department表增加一条记录"); } public Department GetDepartment(int id) { Console.WriteLine("在Access中根据ID得到Department表一条记录"); return null; } } #endregion /// <summary> /// 简单工厂反射 /// </summary> class DataAccess { private static readonly string AssemblyName = "抽象工厂模式"; private static readonly string db = ConfigurationManager.AppSettings["DB"]; //利用反射代替Switch 语句的判断,进行运行时实例化 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); } } }
冯瑞涛