4. 抽象工厂模式(Abstract Factory Pattern)
抽象工厂模式(初版)
1、介绍
怎么理解抽象工厂模式呢?这篇的介绍我拖了好久,后面发现抽象工厂其实就是工厂方法模式的更一般化,也符合了抽象化即一般化的事物发展规律。单个产品的实现用工厂方法模式,多个产品的实现就需要横向扩展,扩展后就变为抽象工厂模式了。
2、UML 图

3、优缺点
优势:满足开放封闭原则(OCP)、依赖倒置原则(DIP)
劣势:简简单单的一个功能却加的类太多了,那有没有改进的可能呢?答案是有的,见抽象工厂模式(改版1)
4、代码附录
实体类:
public class User { private int _id; public int Id { get { return this._id; } set { this._id = value; } } private string _name; public string Name { get { return this._name; } set { this._name = value; } } } public class Department { private int _id; public int Id { get { return this._id; } set { this._id = value; } } private string _name; public string Name { get { return this._name; } set { this._name = value; } } }
IFactory 接口及实现:
public interface IFactory { IUser CreateUser(); IDepartment CreateDepartment(); } public class SqlServerFactory:IFactory { public IUser CreateUser() { return new SqlServerUser(); } public IDepartment CreateDepartment() { return new SqlDepartment(); } } public class AccessFactory:IFactory { public IUser CreateUser() { return new AccessUser(); } public IDepartment CreateDepartment() { return new AccessDepartment(); } }
IUser、IDepartment 接口及对应的实现
public interface IUser { void Insert(User user); User GetEntity(int id); } public class SqlServerUser:IUser { public void Insert(User user) { Console.WriteLine("我这里用SqlServer插入一条User"); } public Entity.User GetEntity(int id) { Console.WriteLine("我这里用SqlServer获取一条User"); return null; } } public class AccessUser : IUser { public void Insert(User user) { Console.WriteLine("我这里用Access插入一条User"); } public Entity.User GetEntity(int id) { Console.WriteLine("我这里用Access获取一条User"); return null; } }
public interface IDepartment { void Insert(Department dp); Department GetEntity(int id); } public class SqlDepartment : IDepartment { public void Insert(Department dp) { Console.WriteLine("我这里用SqlServer插入一条Department"); } public Entity.Department GetEntity(int id) { Console.WriteLine("我这里用SqlServer获取一条Department"); return null; } } public class AccessDepartment : IDepartment { public void Insert(Department dp) { Console.WriteLine("我这里用Access插入一条Department"); } public Entity.Department GetEntity(int id) { Console.WriteLine("我这里用Access获取一条Department"); return null; } }
应用:
var user = new User(); IFactory factory=new AccessFactory(); var us = factory.CreateUser(); us.Insert(user); us.GetEntity(1); Console.ReadLine();
抽象工厂模式(改版1)
1. 介绍
上面我们看到实现一个抽象工厂模式,要建大量的类,的确有些繁琐;那么哪些类可以去掉呢,我们试着去掉 IFactory、SqlServerFactory、AccessFactory ;取而代之的是DataAccess 用简单工厂模式 实现。
2. UML图


3. 优缺点
优势:类个数减少的同事,使用者完全不用考虑该功能是用哪种数据库实现的。
劣势:DataAccess中多个switch逻辑不好
4. 附录
DataAccess 类:
public class DataAccess { private static string dbString = @"Access"; public static IUser CreateUser() { switch (dbString) { case "SqlServer": return new SqlServerUser(); case "Access": return new AccessUser(); default: return null; } } public static IDepartment CreateDepartment() { switch (dbString) { case "SqlServer": return new SqlServerDepartment(); case "Access": return new AccessDepartment(); default: return null; } } }
Entity 类:
public class User { private int _id; public int Id { get { return this._id; } set { this._id = value; } } private string _name; public string Name { get { return this._name; } set { this._name = value; } } } public class Department { private int _id; public int Id { get { return this._id; } set { this._id = value; } } private string _name; public string Name { get { return this._name; } set { this._name = value; } } }
IUser、IDepartment 接口及对应的实现:
public interface IUser { void Insert(User user); User GetEntity(int id); } public class SqlServerUser:IUser { public void Insert(User user) { Console.WriteLine("我这里用SqlServer插入一条User"); } public Entity.User GetEntity(int id) { Console.WriteLine("我这里用SqlServer获取一条User"); return null; } } public class AccessUser : IUser { public void Insert(User user) { Console.WriteLine("我这里用Access插入一条User"); } public Entity.User GetEntity(int id) { Console.WriteLine("我这里用Access获取一条User"); return null; } }
public interface IDepartment { void Insert(Department dp); Department GetEntity(int id); } public class SqlDepartment : IDepartment { public void Insert(Department dp) { Console.WriteLine("我这里用SqlServer插入一条Department"); } public Entity.Department GetEntity(int id) { Console.WriteLine("我这里用SqlServer获取一条Department"); return null; } } public class AccessDepartment : IDepartment { public void Insert(Department dp) { Console.WriteLine("我这里用Access插入一条Department"); } public Entity.Department GetEntity(int id) { Console.WriteLine("我这里用Access获取一条Department"); return null; } }
应用:
User user=new User(); Department dp = new Department(); IUser iu = DataAccess.CreateUser(); IDepartment idp = DataAccess.CreateDepartment(); iu.Insert(user); iu.GetEntity(1); idp.Insert(dp); idp.GetEntity(1);
抽象工厂模式(改版2)
1. 介绍
改版1中,我们看到 switch 是一个很讨厌的玩意儿,代码重复不说,还逻辑冗余,接下来我们利用反射解决这一块。
2. 优缺点
很明显,通过反射代码简洁了很多
3. 附录代码
public class DataAccess { private static string assemblyName = "Abstract.Pattern.v1"; private static string dbString = @"Access"; public static IUser CreateUser() { string className = assemblyName + "." + dbString + "User"; return (IUser)Assembly.Load(assemblyName).CreateInstance(className); } public static IDepartment CreateDepartment() { string className = assemblyName + "." + dbString + "Department"; return (IDepartment)Assembly.Load(assemblyName).CreateInstance(className); } }
抽象工厂模式与工厂方法模式的区别
| 工厂方法模式 | 抽象工厂模式 |
| 1. 针对的是单一的产品结构 | 1. 针对的是多个产品结构 |
| 2. 一个抽象的产品类 | 2. 多个抽象的产品类 |
真正的大师永远怀着一颗学徒的心。


浙公网安备 33010602011771号