一、简单工厂模式
简单工厂模式,提供了一种创建对象的便捷方法。创建者通过不同的类型参数,创建相对应的对象。
实现代码如下:
public class Product
{
public virtual void Funtion()
{}
}
public class ProductA : Product
{
public override void Funtion()
{
base.Funtion();
}
}
public class ProductB : Product
{
public override void Funtion()
{
base.Funtion();
}
}
public class Creator
{
public static Product Create(string type)
{
switch (type)
{
case "A":
return new ProductA();
case "B":
return new ProductB();
default:
return null;
}
}
}
class Program
{
static void Main(string[] args)
{
Product pa = Creator.Create("A");
}
}
优点:
在创建固定类型的对象时,比较简单好用。
缺点:
1. 在添加对象类型时,需要更改Creator类里面的函数,违反了软件设计中的开闭原则。
2. Creator类依赖于具体类ProductA,和ProductB,在具体类变化时直接影响Creator类,耦合性过强。
工厂模式
工厂模式将对象的创建延迟到了具体的子类里面实现。这样,我们创建子类对象时,不需要知道具体的子类,只需获取到相应的类型的工厂即可。同时,工厂模式消除了简单工厂方法所具有高耦合性,且满足软件的设计原则。
工厂模式,解决了创建多个、同类对象的复杂问题。比如我们需要创建100个ProductA种类的对象,如果不使用工厂模式,我们需要new出100个ProductA对象来;通过工厂模式,只需要调用FactoryA多次就能够完成对象的创建。
1. 实现方法
1)工厂模式最常用的结构类图:
实现代码(C#)如下:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Factory { public class Product { public virtual void Funtion() { } } public class ProductA : Product { public override void Funtion() { base.Funtion(); } } public class ProductB : Product { public override void Funtion() { base.Funtion(); } } public class Factory { virtual public Product Create() { return null; } } public class FacotryA : Factory { public override Product Create() { return new ProductA(); } } public class FactoryB : Factory { public override Product Create() { return new ProductB(); } } class FactoryMode { static void Main(string[] args) { FacotryA fa = new FacotryA(); FactoryB fb = new FactoryB(); Product pa = fa.Create(); Product pb = fb.Create(); } } }
工厂模式的问题在于,每添加一种新的Product必须添加与之相对应的Factory类。比如,现在需要增加一种对象ProductC,同时需要添加FactoryC类来创建ProductC的对象。这样的话,如果需要添加N多种对象,同时就必须添加与之对应的N种工厂类,增加了编码量和繁琐程度,如下图。
2)使用类模板
在需要添加多种对象时,采用模版的方式,可以避免创建过多的工厂子类。
此处,只需要定义一个类模板template<class TheProduct> ConcreteFactoy,只要是从Product基类派生的对象类型,都可以通过这个类模板实现。
以下是实现代码(C++).
#include "stdafx.h" #include <iostream> using namespace std; class Product { public: virtual void Function() = 0; }; class ProductA : public Product { public: void Function(); }; void ProductA::Function() { cout << "Create ProductA..." << endl; } class Factory { public: virtual Product* Create() = 0; }; template<class TheProduct> class ConcreteFactroy : public Factory { public: virtual Product* Create(); }; template<class TheProduct> Product* ConcreteFactroy<TheProduct>::Create() { return new TheProduct; } int _tmain(int argc, _TCHAR* argv[]) { ConcreteFactroy<ProductA> MyFactory; Product* pa = MyFactory.Create(); pa->Function(); return 0; }
3. 抽象工厂
抽象工厂模式,用于创建一组相关或独立的对象。通过此模式,用户不需要知道具体的对象类型,只需找到创建的工厂类即可。抽象工厂与工厂方法的区别主要如下:
工厂方法中的工厂类只能创建一种对象,如FactoryA -> ProductA。
抽象工厂中的工厂类可以创建多种类型的对象, Factory1 -> {product1, product2, …,productN}
抽象工厂的问题在于,当我们需要添加新的对象AbstractProductC时,需要同时修改AbstractFactory, ConcreteFactory1和ConcreteFactory2三个类。从这个角度来看,添加新类型的对象时,与简单工厂模式类似。这里,我们不妨就先把抽象工厂更改为简单工厂模式,然后再通过反射机制进行改进。通过反射,用户只需要传递product子类型的名字给Factory类。Factory类根据传入的类名字,生成类对象。无论后期添加多少种对象,都不用再添加对应的工厂类。
以下描述了,抽象工厂模式访问数据库,然后更改为简单工厂模式,再使用反射机制的整个过程(摘自《大话设计模式》)。(其实,三种工厂模式都可以使用反射机制来简化对象生成的过程。)
使用抽象工厂访问数据库的类图:
我们将抽象工厂更改为简单工厂模式,如下:
使用反射实现(C#),如下: using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Reflection; namespace AbstractFactory { public interface IUser { void InsertUser(IUser user); IUser GetUser(string user); } public class SQLUser : IUser { public void InsertUser(IUser user) { Console.WriteLine("Access user"); } public IUser GetUser(string user) { return null; } } public class AccessUser : IUser { public void InsertUser(IUser user) { Console.WriteLine("Access user"); } public IUser GetUser(string user) { return null; } } public class DataAccess { private readonly string dbType = "SQL"; public IUser CreateUser() { IUser result = null; switch (dbType) { case "SQL": result = new SQLUser(); break; case "Access": result = new AccessUser(); break; default: break; } return result; } public string ReflectType { get; set; } public IUser CreateUserByReflection() { //(IUser)Assembly.Load(当前程序集的名称 "Factory").CreateInstance("命名空间.类名"); return (IUser)Assembly.Load("Factory").CreateInstance(ReflectType); } } class AbstractFactory_Reflect { static void Main(string[] args) { DataAccess da = new DataAccess(); da.ReflectType = "AbstractFactory.SQLUser"; IUser user = null; user = da.CreateUserByReflection(); SQLUser sqlUser = user as SQLUser; if (sqlUser == null) { Console.WriteLine("NULL..."); } } } }