现在的位置: 首页 > 综合 > 正文

工厂模式(Factory Method)

2013年02月05日 ⁄ 综合 ⁄ 共 2908字 ⁄ 字号 评论关闭

概述

在软件系统中,经常面临着“某个对象”的创建工作,由于需求的变化,这个对象的具体实现经常面临着剧烈的变化,但是它却拥有比较稳定的接口。如何应对这种变化?提供一种封装机制来隔离出“这个易变对象”的变化,从而保持系统中“其它依赖该对象的对象”不随着需求的改变而改变?这就是要说的Factory Method模式了。

意图

定义一个用户创建对象的接口,让子类决定实例化哪一个类。Factory Method使一个类的实例化延迟到其子类。

结构图

工厂模式 - smiles - lixinsmiles 的博客

生活中的例子

工厂方法定义一个用于创建对象的接口,但是让子类决定实例化哪个类。压注成型演示了这种模式。塑料玩具制造商加工塑料粉,将塑料注入到希望形状的模具中。玩具的类别(车,人物等等)是由模具决定的。

工厂模式 - smiles - lixinsmiles 的博客

工厂方法解说

在工厂方法模式中,核心的工厂类不再负责所有产品的创建,而是将具体创建工作交给子类去做。这个核心类仅仅负责给出具体工厂必须实现的接口,而不接触哪一个产品类被实例化这种细节。这使得工厂方法模式可以允许系统在不修改工厂角色的情况下引进新产品。在Factory Method模式中,工厂类与产品类往往具有平行的等级结构,它们之间一一对应。

现在我们考虑一个日志记录的例子(这里我们只是为了说明Factory Method模式,实际项目中的日志记录不会这么去做,也要比这复杂一些)。假定我们要设计日志记录的类,支持记录的方法有FileLogEventLog两种方式。在这里我们先不谈设计模式,那么这个日志记录的类就很好实现了:

 1工厂模式 - smiles - lixinsmiles 的博客工厂模式 - smiles - lixinsmiles 的博客/**//// <summary>
 2工厂模式 - smiles - lixinsmiles 的博客/// 日志记录类
 3工厂模式 - smiles - lixinsmiles 的博客/// </summary>
 4工厂模式 - smiles - lixinsmiles 的博客public class Log
 5工厂模式 - smiles - lixinsmiles 的博客工厂模式 - smiles - lixinsmiles 的博客    工厂模式 - smiles - lixinsmiles 的博客{
 6工厂模式 - smiles - lixinsmiles 的博客
 7工厂模式 - smiles - lixinsmiles 的博客        public void WriteEvent()
 8工厂模式 - smiles - lixinsmiles 的博客工厂模式 - smiles - lixinsmiles 的博客        工厂模式 - smiles - lixinsmiles 的博客{
 9工厂模式 - smiles - lixinsmiles 的博客            Console.WriteLine("EventLog Success!");
10工厂模式 - smiles - lixinsmiles 的博客        }
11工厂模式 - smiles - lixinsmiles 的博客    
12工厂模式 - smiles - lixinsmiles 的博客        public void WriteFile()
13工厂模式 - smiles - lixinsmiles 的博客工厂模式 - smiles - lixinsmiles 的博客        工厂模式 - smiles - lixinsmiles 的博客{
14工厂模式 - smiles - lixinsmiles 的博客            Console.WriteLine("FileLog Success!");
15工厂模式 - smiles - lixinsmiles 的博客        }
16工厂模式 - smiles - lixinsmiles 的博客
17工厂模式 - smiles - lixinsmiles 的博客        public void Write(string LogType)
18工厂模式 - smiles - lixinsmiles 的博客工厂模式 - smiles - lixinsmiles 的博客        工厂模式 - smiles - lixinsmiles 的博客{
19工厂模式 - smiles - lixinsmiles 的博客            switch(LogType.ToLower())
20工厂模式 - smiles - lixinsmiles 的博客工厂模式 - smiles - lixinsmiles 的博客            工厂模式 - smiles - lixinsmiles 的博客{
21工厂模式 - smiles - lixinsmiles 的博客                case "event":
22工厂模式 - smiles - lixinsmiles 的博客                    WriteEvent();
23工厂模式 - smiles - lixinsmiles 的博客                    break;
24工厂模式 - smiles - lixinsmiles 的博客
25工厂模式 - smiles - lixinsmiles 的博客                case "file":
26工厂模式 - smiles - lixinsmiles 的博客                    WriteFile();
27工厂模式 - smiles - lixinsmiles 的博客                    break;
28工厂模式 - smiles - lixinsmiles 的博客
29工厂模式 - smiles - lixinsmiles 的博客                default:
30工厂模式 - smiles - lixinsmiles 的博客                    break;
31工厂模式 - smiles - lixinsmiles 的博客            }
32工厂模式 - smiles - lixinsmiles 的博客        }
33工厂模式 - smiles - lixinsmiles 的博客    }
34工厂模式 - smiles - lixinsmiles 的博客

这样的程序结构显然不能符合我们的要求,如果我们增加一种新的日志记录的方式DatabaseLog,那就要修改Log类,随着记录方式的变化,switch语句在不断的变化,这样就引起了整个应用程序的不稳定,进一步分析上面的代码,发现对于EventLogFileLog是两种完全不同的记录方式,它们之间不应该存在必然的联系,而应该把它们分别作为单独的对象来对待。

 1工厂模式 - smiles - lixinsmiles 的博客工厂模式 - smiles - lixinsmiles 的博客/**//// <summary>
 2工厂模式 - smiles - lixinsmiles 的博客/// EventLog类
 3工厂模式 - smiles - lixinsmiles 的博客/// </summary>
 4工厂模式 - smiles - lixinsmiles 的博客public class EventLog
 5工厂模式 - smiles - lixinsmiles 的博客工厂模式 - smiles - lixinsmiles 的博客工厂模式 - smiles - lixinsmiles 的博客{
 6工厂模式 - smiles - lixinsmiles 的博客    public void Write()
 7工厂模式 - smiles - lixinsmiles 的博客工厂模式 - smiles - lixinsmiles 的博客    工厂模式 - smiles - lixinsmiles 的博客{
 8工厂模式 - smiles - lixinsmiles 的博客        Console.WriteLine("EventLog Write Success!");
 9工厂模式 - smiles - lixinsmiles 的博客    }
10工厂模式 - smiles - lixinsmiles 的博客}
11工厂模式 - smiles - lixinsmiles 的博客
12工厂模式 - smiles - lixinsmiles 的博客工厂模式 - smiles - lixinsmiles 的博客/**//// <summary>
13工厂模式 - smiles - lixinsmiles 的博客/// FileLog类
14工厂模式 - smiles - lixinsmiles 的博客/// </summary>
15工厂模式 - smiles - lixinsmiles 的博客public class FileLog
16工厂模式 - smiles - lixinsmiles 的博客工厂模式 - smiles - lixinsmiles 的博客工厂模式 - smiles - lixinsmiles 的博客{
17工厂模式 - smiles - lixinsmiles 的博客    public void Write()
18工厂模式 - smiles - lixinsmiles 的博客工厂模式 - smiles - lixinsmiles 的博客    工厂模式 - smiles - lixinsmiles 的博客{
19工厂模式 - smiles - lixinsmiles 的博客        Console.WriteLine("FileLog Write Success!");
20工厂模式 - smiles - lixinsmiles 的博客    }
21工厂模式 - smiles - lixinsmiles 的博客}
22工厂模式 - smiles - lixinsmiles 的博客

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

工厂模式 - smiles - lixinsmiles 的博客

实现代码:

1工厂模式 - smiles - lixinsmiles 的博客工厂模式 - smiles - lixinsmiles 的博客/**//// <summary>
2工厂模式 - smiles - lixinsmiles 的博客/// Log类
3工厂模式 - smiles - lixinsmiles 的博客/// </summary>
4工厂模式 - smiles - lixinsmiles 的博客public abstract class Log
5工厂模式 - smiles - lixinsmiles 的博客工厂模式 - smiles - lixinsmiles 的博客工厂模式 - smiles - lixinsmiles 的博客{
6工厂模式 - smiles - lixinsmiles 的博客    public abstract void Write();
7工厂模式 - smiles - lixinsmiles 的博客}
8工厂模式 - smiles - lixinsmiles 的博客

此时EventLogFileLog类的代码应该如下:

 1工厂模式 - smiles - lixinsmiles 的博客工厂模式 - smiles - lixinsmiles 的博客/**//// <summary>
 2工厂模式 - smiles - lixinsmiles 的博客/// EventLog类
 3工厂模式 - smiles - lixinsmiles 的博客/// </summary>
 4工厂模式 - smiles - lixinsmiles 的博客public class EventLog:Log
 5工厂模式 - smiles - lixinsmiles 的博客工厂模式 - smiles - lixinsmiles 的博客工厂模式 - smiles - lixinsmiles 的博客{
 6工厂模式 - smiles - lixinsmiles 的博客    public override void Write()
 7工厂模式 - smiles - lixinsmiles 的博客工厂模式 - smiles - lixinsmiles 的博客    工厂模式 - smiles - lixinsmiles 的博客{
 8工厂模式 - smiles - lixinsmiles 的博客        Console.WriteLine("EventLog Write Success!");
 9工厂模式 - smiles - lixinsmiles 的博客    }
10工厂模式 - smiles - lixinsmiles 的博客}
11工厂模式 - smiles - lixinsmiles 的博客工厂模式 - smiles - lixinsmiles 的博客/**//// <summary>
12工厂模式 - smiles - lixinsmiles 的博客/// FileLog类
13工厂模式 - smiles - lixinsmiles 的博客/// </summary>
14工厂模式 - smiles - lixinsmiles 的博客public class FileLog:Log
15工厂模式 - smiles - lixinsmiles 的博客工厂模式 - smiles - lixinsmiles 的博客工厂模式 - smiles - lixinsmiles 的博客{
16工厂模式 - smiles - lixinsmiles 的博客    public override void Write()
17工厂模式 - smiles - lixinsmiles 的博客工厂模式 - smiles - lixinsmiles 的博客    工厂模式 - smiles - lixinsmiles 的博客{
18工厂模式 - smiles - lixinsmiles 的博客        Console.WriteLine("FileLog Write Success!");
19工厂模式 - smiles - lixinsmiles 的博客    }
20工厂模式 - smiles - lixinsmiles 的博客}
21工厂模式 - smiles - lixinsmiles 的博客

此时我们再看增加新的记录日志方式DatabaseLog的时候,需要做哪些事情?只需要增加一个继承父类Log的子类来实现,而无需再去修改EventLogFileLog类,这样的设计满足了类之间的层次关系,又很好的符合了面向对象设计中的单一职责原则,每一个类都只负责一件具体的事情。到这里似乎我们的设计很完美了,事实上我们还没有看客户程序如何去调用。 在应用程序中,我们要使用某一种日志记录方式,也许会用到如下这样的语句:

工厂模式 - smiles - lixinsmiles 的博客EventLog eventlog = new EventLog();
工厂模式 - smiles - lixinsmiles 的博客eventlog.Write();
工厂模式 - smiles - lixinsmiles 的博客

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

 1工厂模式 - smiles - lixinsmiles 的博客工厂模式 - smiles - lixinsmiles 的博客/**//// <summary>
 2工厂模式 - smiles - lixinsmiles 的博客/// EventFactory类
 3工厂模式 - smiles - lixinsmiles 的博客/// </summary>
 4工厂模式 - smiles - lixinsmiles 的博客public class EventFactory
 5工厂模式 - smiles - lixinsmiles 的博客工厂模式 - smiles - lixinsmiles 的博客工厂模式 - smiles - lixinsmiles 的博客{
 6工厂模式 - smiles - lixinsmiles 的博客    public EventLog Create()
 7工厂模式 - smiles - lixinsmiles 的博客
【上篇】
【下篇】

抱歉!评论已关闭.