技术开发 频道

创建型模式篇-工厂方法模式(Factory Method)


进一步抽象,为它们抽象出一个共同的父类,结构图如下:


实现代码:

1/**//// <summary> 2/// Log类 3/// </summary> 4public abstract class Log 5{ 6 public abstract void Write(); 7} 8
此时EventLog和FileLog类的代码应该如下:

1/**//// <summary> 2/// EventLog类 3/// </summary> 4public class EventLog:Log 5{ 6 public override void Write() 7 { 8 Console.WriteLine("EventLog Write Success!"); 9 } 10} 11/**//// <summary> 12/// FileLog类 13/// </summary> 14public class FileLog:Log 15{ 16 public override void Write() 17 { 18 Console.WriteLine("FileLog Write Success!"); 19 } 20} 21
    此时我们再看增加新的记录日志方式DatabaseLog的时候,需要做哪些事情?只需要增加一个继承父类Log的子类来实现,而无需再去修改EventLog和FileLog类,这样的设计满足了类之间的层次关系,又很好的符合了面向对象设计中的单一职责原则,每一个类都只负责一件具体的事情。到这里似乎我们的设计很完美了,事实上我们还没有看客户程序如何去调用。 在应用程序中,我们要使用某一种日志记录方式,也许会用到如下这样的语句:

EventLog eventlog = new EventLog(); eventlog.Write();
    当日志记录的方式从EventLog变化为FileLog,我们就得修改所有程序代码中出现上面语句的部分,这样的工作量是可想而知的。此时就需要解耦具体的日志记录方式和应用程序。这就要引入Factory Method模式了,每一个日志记录的对象就是工厂所生成的产品,既然有两种记录方式,那就需要两个不同的工厂去生产了,代码如下:当日志记录的方式从EventLog变化为FileLog,我们就得修改所有程序代码中出现上面语句的部分,这样的工作量是可想而知的。此时就需要解耦具体的日志记录方式和应用程序。这就要引入Factory Method模式了,每一个日志记录的对象就是工厂所生成的产品,既然有两种记录方式,那就需要两个不同的工厂去生产了,代码如下:

1/**//// <summary> 2/// EventFactory类 3/// </summary> 4public class EventFactory 5{ 6 public EventLog Create() 7 { 8 return new EventLog(); 9 } 10} 11/**//// <summary> 12/// FileFactory类 13/// </summary> 14public class FileFactory 15{ 16 public FileLog Create() 17 { 18 return new FileLog(); 19 } 20} 21
    这样通过工厂方法模式我们把上面那对象创建工作封装在了工厂中,此时我们似乎完成了整个Factory Method的过程。这样达到了我们应用程序和具体日志记录对象之间解耦的目的了吗?看一下此时客户端程序代码:

1/**//// <summary> 2/// App类 3/// </summary> 4public class App 5{ 6 public static void Main(string[] args) 7 { 8 LogFactory factory = new EventFactory(); 9 10 Log log = factory.Create(); 11 12 log.Write(); 13 } 14} 15
    在客户程序中,我们有效地避免了具体产品对象和应用程序之间的耦合,可是我们也看到,增加了具体工厂对象和应用程序之间的耦合。那这样究竟带来什么好处呢?我们知道,在应用程序中,Log对象的创建是频繁的,在这里我们可以把

LogFactory factory = new EventFactory();

这句话放在一个类模块中,任何需要用到Log对象的地方仍然不变。要是换一种日志记录方式,只要修改一处为:

LogFactory factory = new FileFactory();

    其余的任何地方我们都不需要去修改。有人会说那还是修改代码,其实在开发中我们很难避免修改,但是我们可以尽量做到只修改一处。

    其实利用.NET的特性,我们可以避免这种不必要的修改。下面我们利用.NET中的反射机制来进一步修改我们的程序,这时就要用到配置文件了,如果我们想使用哪一种日志记录方式,则在相应的配置文件中设置如下:

1<appSettings> 2 <add key="factoryName" value="EventFactory"></add> 3</appSettings>
此时客户端代码如下:
1/**//// <summary> 2/// App类 3/// </summary> 4public class App 5{ 6 public static void Main(string[] args) 7 { 8 string strfactoryName = ConfigurationSettings.AppSettings["factoryName"]; 9 10 LogFactory factory; 11 factory = (LogFactory)Assembly.Load("FactoryMethod").CreateInstance("FactoryMethod." + strfactoryName); 12 13 Log log = factory.Create(); 14 log.Write(); 15 } 16} 17
     现在我们看到,在引进新产品(日志记录方式)的情况下,我们并不需要去修改工厂类,而只是增加新的产品类和新的工厂类(注意:这是任何时候都不能避免的),这样很好的符合了开放封闭原则。


0
相关文章