今天我们来看一下使用频率非常高的工厂方法模式,看完原理分别给出.NET和JAVA两种语言的实现源码。
定义:
工厂方法模式:定义一个用于创建对象的接口,但是让子类决定将哪一个类实例化。工厂方法模式让一个类的实例化延迟到其子类。
Factory Method Pattern: Define an interface for creating an object, but let subclasses decide which class to instantiate. Factory Method lets a class defer instantiation to subclasses.
简称为工厂模式(Factory Pattern)
又可称作虚拟构造器模式(Virtual Constructor Pattern)或多态工厂模式(Polymorphic Factory Pattern)
工厂父类负责定义创建产品对象的公共接口,而工厂子类则负责生成具体的产品对象
目的是将产品类的实例化操作延迟到工厂子类中完成,即通过工厂子类来确定究竟应该实例化哪一个具体产品类
分析:
•不再提供一个工厂类来统一负责所有子类的创建,而是将具体子类的创建过程交给专门的工厂子类去完成
•如果出现新的子类类型,只需要为这种新类型的子类定义一个具体的工厂类就可以创建该新子类的实例
类图:
工厂方法模式包含以下4个角色:
Product(抽象产品)
ConcreteProduct(具体产品)
Factory(抽象工厂)
ConcreteFactory(具体工厂)
适用性:
1.当一个类不知道它所必须创建的对象的类的时候。 2.当一个类希望由它的子类来指定它所创建的对象的时候。 3.当*将创建对象的职责委托给多个帮助*类中的某一个,并且*希望将哪一个帮助子类是代理者这一信息局部化的时候。
优点:
工厂方法用来创建客户所需要的产品,同时还向客户隐藏了哪种具体产品类将被实例化这一细节
能够让工厂自主确定创建何种产品对象,而如何创建这个对象的细节则完全封装在具体工厂内部
在系统中加入新产品时,完全符合开闭原则
缺点:
系统中类的个数将成对增加,在一定程度上增加了系统的复杂度,会给系统带来一些额外的开销
增加了系统的抽象性和理解难度
案例1:(.NET代码)
代码清单包括:
Program.cs源码
using System;
using System.Configuration;
using System.Reflection;
namespace FactoryMethodSample
{
class Program
{
static void Main(string[] args)
{
LoggerFactory factory;
Logger logger;
//读取配置文件
string factoryString = ConfigurationManager.AppSettings["factory"];
//反射生成对象
factory = (LoggerFactory)Assembly.Load("FactoryMethodSample").CreateInstance(factoryString);
logger = factory.CreateLogger();
logger.WriteLog();
Console.Read();
}
}
}
Logger.cs
namespace FactoryMethodSample
{
interface Logger
{
void WriteLog();
}
}
FileLogger.cs
using System;
namespace FactoryMethodSample
{
class FileLogger : Logger
{
public void WriteLog()
{
Console.WriteLine("文件日志记录。");
}
}
}
DatabaseLogger.cs
using System;
namespace FactoryMethodSample
{
class DatabaseLogger : Logger
{
public void WriteLog()
{
Console.WriteLine("数据库日志记录。");
}
}
}
LoggerFactory.cs
namespace FactoryMethodSample
{
interface LoggerFactory
{
Logger CreateLogger();
}
}
FileLoggerFactory.cs
namespace FactoryMethodSample
{
class FileLoggerFactory : LoggerFactory
{
public Logger CreateLogger()
{
//创建文件日志记录器对象
Logger logger = new FileLogger();
//创建文件,代码省略
return logger;
}
}
}
DatabaseLoggerFactory.cs
namespace FactoryMethodSample
{
class DatabaseLoggerFactory : LoggerFactory
{
public Logger CreateLogger()
{
//连接数据库,代码省略
//创建数据库日志记录器对象
Logger logger = new DatabaseLogger();
//初始化数据库日志记录器,代码省略
return logger;
}
}
}
App.config
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<add key="factory" value="FactoryMethodSample.FileLoggerFactory"/>
</appSettings>
</configuration>
案例2:(JAVA代码)
Product
public interface Work {
void doWork();
}
ConcreteProduct
public class StudentWork implements Work {
public void doWork() {
System.out.println("学生*作业!");
}
}
public class TeacherWork implements Work {
public void doWork() {
System.out.println("老师审批作业!");
}
}
Creator
public interface IWorkFactory {
Work getWork();
}
ConcreteCreator
public class StudentWorkFactory implements IWorkFactory {
public Work getWork() {
return new StudentWork();
}
}
public class TeacherWorkFactory implements IWorkFactory {
public Work getWork() {
return new TeacherWork();
}
}
Test
public class Test {
public static void main(String[] args) {
IWorkFactory studentWorkFactory = new StudentWorkFactory();
studentWorkFactory.getWork().doWork();
IWorkFactory teacherWorkFactory = new TeacherWorkFactory();
teacherWorkFactory.getWork().doWork();
}
}
程序运行返回结果:
学生做作业! 老师审批作业!