上篇将工厂模式讲完了,这次我们来说说抽象工厂模式,如果说工厂模式是生产一种东西,简单工厂模式是参数化的工厂模式,那么抽象工厂模式是生产一类东西。我们不一定要找他们不同的地方,找相同的地方也一样会更加理解。这个模板化的抽象工厂模式UML图比较难画,关键代码也是和工厂长的差不多。这里我们从例子中总结出它的 UML图模板,然后在分析它的关键代码。
这里软件环境是 Unity2017
抽象工厂模式
- 意图:让工厂模式不仅可以生产一种东西,还可以生产一类东西。或者说从不同公司/渠道生产一种东西。
- 如何使用:提供一个创建一系列相关或互相依赖对象的接口,而无需指定它们具体的类。
- 例子:
(1).大话设计模式上的例子
UML图:
这里上面两个类的关系没画,在画就太乱了,但是他们是有依赖关系的。
客户端类,工厂表接口与实现类
public class AbstractFactorBook : MonoBehaviour
{
void Start()
{
User user = new User();
Department dept = new Department();
//
IFactorys factory = new AccessFactory();
IUser iu = factory.CreateUser();
iu.Insert(user);
iu.GetUser(1);
//
IDepartment id = factory.CreateDepartment();
id.Insert(dept);
id.GetDepartment(1);
}
}
interface IFactorys
{
IUser CreateUser();
IDepartment CreateDepartment();
}
class SqlServerFactory : IFactorys
{
public IDepartment CreateDepartment()
{
return new SqlserverDepartment();
}
public IUser CreateUser()
{
return new SqlserverUser();
}
}
class AccessFactory : IFactorys
{
public IDepartment CreateDepartment()
{
return new AccessDepartment();
}
public IUser CreateUser()
{
return new AccessUser();
}
}
用户表和部门表接口与实现类
interface IDepartment
{
void Insert(Department department);
Department GetDepartment(int id);
}
class SqlserverDepartment : IDepartment
{
public Department GetDepartment(int id)
{
Debug.Log("在SQL Server中根据ID得到Department表一条记录");
return null;
}
public void Insert(Department department)
{
Debug.Log("在SQL Server中给Department表增加一条记录");
}
}
class AccessDepartment : IDepartment
{
public Department GetDepartment(int id)
{
Debug.Log("在Access中根据ID得到Department表记录一条记录");
return null;
}
public void Insert(Department department)
{
Debug.Log("在Access中给Department表增加一条记录");
}
}
interface IUser
{
void Insert(User user);
User GetUser(int id);
}
class SqlserverUser : IUser
{
public void Insert(User user)
{
Debug.Log("在SQL Server中给User表增加一条记录");
}
public User GetUser(int id)
{
Debug.Log("在SQL Server中根据ID得到User表一条记录");
return null;
}
}
class AccessUser : IUser
{
public void Insert(User user)
{
Debug.Log("在Access中给User表增加一条记录");
}
public User GetUser(int id)
{
Debug.Log("在Access中根据ID得到User表一条记录");
return null;
}
}
用户表和部门表
//用户
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; }
}
}
(2)菜鸟教程上的例子
UML图:
代码:
客户端代码
public class AbstractFactorPattern : MonoBehaviour
{
void Start()
{
AbstractFactory shapeFactory = FactoryProducer.GetFactory("SHAPE");
IShape shape = shapeFactory.GetShape("CIRCLE");
shape.Draw();
}
}
绘制图形颜色接口与实现
public interface IShape
{
void Draw();
}
public class Rectangle : IShape
{
public void Draw()
{
Debug.Log("绘制Rectangle(矩形)");
}
}
public class Circle : IShape
{
public void Draw()
{
Debug.Log("绘制Circle(圆形)");
}
}
public class Square : IShape
{
public void Draw()
{
Debug.Log("绘制Square(正方形)");
}
}
public interface IColor
{
void Fill();
}
public class Red : IColor
{
public void Fill()
{
Debug.Log("绘制Red");
}
}
public class Green : IColor
{
public void Fill()
{
Debug.Log("绘制Green");
}
}
public class Blue : IColor
{
public void Fill()
{
Debug.Log("绘制Blue");
}
}
工厂类接口和它的子类
public abstract class AbstractFactory
{
public abstract IColor GetColor(string color);
public abstract IShape GetShape(string shape);
}
public class ShapeFactory : AbstractFactory
{
public override IColor GetColor(string color)
{
return null;
}
public override IShape GetShape(string shapeType)
{
if (shapeType == null)
{
return null;
}
switch (shapeType)
{
case "CIRCLE":
return new Circle();
case "RECTANGLE":
return new Rectangle();
case "SQUARE":
return new Square();
}
return null;
}
}
public class ColorFactory : AbstractFactory
{
public override IColor GetColor(string color)
{
if (color == null)
{
return null;
}
switch (color)
{
case "RED":
return new Red();
case "GREEN":
return new Green();
case "BLUE":
return new Blue();
}
return null;
}
public override IShape GetShape(string shape)
{
return null;
}
}
3. UML图:
4. 关键代码:
IFactory productAFactory=new ProductAFactory();
CompanyB conBProductA=productAFactory.CreateProductB();
这里就创建出来了B公司的A产品。
抽象设计模式的缺点:
如果我要增加公司C来生产产品A和产品B,还需要修改,ProductAFactory,ProductBFactoryB,IFactory这三个类,我们可以用简单工厂模式来改进抽象设计模式,我们把这三个类使用swich判断合成一个静态工厂类来改进设计模式:,这里我就不画UML图了,因为上面的抽象模板UML没有写代码,这里直接用大话设计模式里面的数据库抽象工厂模式来优化。
代码如下:
public class AbstractFactorBook : MonoBehaviour
{
void Start()
{
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);
//
//User user = new User();
//Department dept = new Department();
//IFactorys factory = new AccessFactory();
//IUser iu = factory.CreateUser();
//iu.Insert(user);
//iu.GetUser(1);
//IDepartment id = factory.CreateDepartment();
//id.Insert(dept);
//id.GetDepartment(1);
}
}
class DataAccess
{
private static readonly string db = "Sqlserver";
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;
}
}
然后我们再使用反射来代替丑陋的swich语句:
public class AbstractFactorBook : MonoBehaviour
{
void Start()
{
User user = new User();
Department dept = new Department();
IUser iu = DataReflectionAccess.CreateUser();
iu.Insert(user);
iu.GetUser(1);
IDepartment id = DataReflectionAccess.CreateDepartment();
id.Insert(dept);
id.GetDepartment(1);
//
}
}
class DataReflectionAccess
{
private static readonly string db = "Sqlserver";
// private static readonly string Namespace = "Null";
public static IUser CreateUser()
{
string AssemblyName = Assembly.GetExecutingAssembly().GetName().Name;//获取程序集名称
string Namespace = System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Namespace;//获取命名空间名称
string className = Namespace + "." + db + "User";
return (IUser)Assembly.Load(AssemblyName).CreateInstance(className);
}
public static IDepartment CreateDepartment()
{
string AssemblyName = Assembly.GetExecutingAssembly().GetName().Name;//获取程序集名称
string Namespace = System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Namespace;//获取命名空间名称
//IDepartment result = null;
string className = Namespace + "." + db + "Department";
return (IDepartment)Assembly.Load(AssemblyName).CreateInstance(className);
}
}
最后我们只要把
private static readonly string db = “Sqlserver”;这一句在通过配置文件来设置,完美实现了对扩展开放,对修改关闭。
最后做一个总结:
把复杂的东西封装起来。外界通过封装的类来访问。把有需求更改的利用接口,利用继承关系来解决。所以抽象工厂模式就是工厂添加了一个抽象接口。工厂模式是工厂生产一种东西。抽象工厂模式是工厂生产一类东西。