一、工厂方法模式定义
定义一个用于创建对象的接口,但是让子类决定将哪一个类实例化。工厂方法模式让一个类的实例化延迟到其子类。
工厂方法模式又名“工厂模式”“虚拟构造器模式”“多态工厂模式”。
二、结构
工厂方法模式包含四种角色:
1) Product(抽象产品):是定义产品的接口,是工厂方法模式创建对象的超类型,是产品对象的公共父类。
2) ConcreteProduct(具体产品类):实现抽象产品接口,与具体工厂类一一对象。
3) Factory(抽象工厂):在抽象工厂类中,声明一个工厂方法,用于返回一个产品,抽象工厂是工厂方法模式的核心。
4) Concrete(具体工厂):是抽象工厂的子类,返回一个具体产品类的实例。
三、应用实例
这里给出的实例是日志记录器实现过程,包括数据库日志记录器和文件日志记录器。一般情况下实现普通工厂方法模式过程中一共包含:
日志记录器接口(Logger)、具体产品角色(DatabaseLogger和FileLogger)、日志记录器工厂接口(LoggerFactory)和具体工厂角色(DatabaseLoggerFactory和FileLoggerFactory)以及客户端代码。
当然在使用配置文件和反射实现工厂方法模式的调用过程中,会增加一个配置文件App.config。配置文件的内容也包含在压缩包中。
应用实例连接http://download.csdn.net/detail/qq_30507287/9540863
四、配置文件与反射
配置文件的使用好处在于:在不修改任何客户端代码的基础上更换或增加新的日志记录方式。在客户端代码中不直接使用new关键字来创建工厂对象,而是将具体工厂的类名存储在配置文件中(App.config),在通过程序集的反射机制,读取配置文件中存储的类名字符串生成对象。
配置文件的格式如下:
<?xmlversion="1.0"encoding="utf-8"?>
<configuration>
<appSettings>
<addkey="factory"value="FactoryMethodSample.FileLoggerFactory"/>
</appSettings>
<startup>
<supportedRuntimeversion="v4.0"sku=".NETFramework,Version=v4.5.2"/>
</startup>
</configuration>
C#中反射机制的使用过程:
//导入命名空间
usingSystem.Reflection;
objectojb = Assembly.Load("程序集名称").CreateInstance("命名空间.类");
说明:在应用实例中客户端代码的实现就包含该过程。
五、工厂方法模式的重载
在抽象工厂中声明多个重载的工厂方法,在具体工厂中实现这些工厂方法。
//日志记录器工厂接口,充当抽象工厂接口
interfaceLoggerFactory
{
Logger CreateLogger();//抽象工厂方法
Logger CreateLogger(string args);
Logger CreateLogger(object obj);
}
namespace FactoryMethodSample
{
//数据库日志记录器工厂类,充当具体工厂角色
classDatabaseLoggerFactory:LoggerFactory
{
publicLogger CreateLogger()
{
//连接数据库
//创建数据库日志记录器对象
Logger logger =new DatabaseLogger();
//初始化数据库日志记录器
returnlogger;
}
publicLogger CreateLogger(string args)
{
//连接数据库
//创建数据库日志记录器对象
Logger logger =new DatabaseLogger();
//初始化数据库日志记录器
returnlogger;
}
public Logger CreateLogger(object obj)
{
//连接数据库
//创建数据库日志记录器对象
Logger logger =new DatabaseLogger();
//初始化数据库日志记录器
returnlogger;
}
}
}
六、工厂方法模式的隐藏
对客户端隐藏工厂方法,客户端无须调用工厂方法创建产品对象,直接使用工厂对象即可调用所创建的产品对象中的业务方法。
//将接口改为抽象类
abstractclassLoggerFactory
{
//在工厂类中直接调用日志记录器的业务方法WriteLog()
publicvoidWriteLog()
{
Logger logger =this.CreateLogger();
logger.WriteLog();
}
publicabstractLogger CreateLogger();
}
客户端代码实现:
staticvoidMain(string[] args)
{
#region使用工厂方法模式的隐藏客户端代码
LoggerFactory factory;//抽象工厂类对象
//读取配置文件
stringfactoryString =ConfigurationManager.AppSettings["factory"];
//反射生成对象
factory = (LoggerFactory)Assembly.Load("FactoryMethodSample").CreateInstance("factoryString");
factory.WriteLog();//直接使用工厂对象调用产品对象
Console.Read();
#endregion
}
七、工厂方法模式优缺点
1)优点:只需关心产品对应的工厂即可,无须关心创建细节,不用知道具体产品类的类名;具体工厂类都具有同一抽象父类;可扩展性好,符合开闭原则。
2)缺点:添加新产品时类的个数将成对添加,系统复杂度将会增加;在可扩展性中,需要引入抽象层,增加了系统的抽象性和理解难度。