创建型模式——Factory Method(未完)
当对某个对象的实例化代码散布在整个项目中的时候,似乎你已经可以嗅到坏味道了,我们叫做“创建蔓延”。除非你肯定这个对象的实例化方法永远不会改变,否则最后将“创建的知识搬迁到Factory”中。
例如:书写日志的对象可能存在三个方法成员,分别用来向文件、数据库以及Windows日志写入信息。任何需要写入日志的地方都应该实例化这个对象,并调用其中的某个方法。
这样似乎看起来没有什么,但是存在以下潜在的问题:
(1) 客户代码(调用者)必须关心LogService是如何创建的
(2) 暴露了过多的方法成员,学习难度加大
(3) LogService本身职责不单一
又例如,当某个对象的创建需要根据不同的配置选项来确定如何实例化时,一种可能是
将这些选项通过蛮力传递到对象的初始化方法中。造成过度的散布。对于使用者来说还需要关心使用哪个方法进行实例化。
在这种情况下,如果创建的选项太多,就应该使用Abstract Factory模式,以便将具体对象的创建延迟到子类或接口实现中实现。
工厂,它使用一个类封装了创建逻辑和客户代码的实例化。
使用的时候需要注意不要成为工厂痴迷者,仅在出现在文档中描述的创建蔓延和对象可能继续扩展的情况下考虑是用工厂方法。否则将造成代码复杂。
典型用法:
使用工厂方法的以后,客户代码的调用从原来的:
1
LogService srv = new LogService();
2
3
srv.WriteToDb();
4
5
srv.WriteToFile();
6
7
srv.WriteToWinLog();
8

2

3

4

5

6

7

8

更改为:
1
LogFactory f = new DBLogFactory();
2
3
LogServiceBase srv = f.Create();
4
5
srv.Write();
6

2

3

4

5

6

这样改进之后,虽然客户代码会多一行,但是带来的好处是显而易见的:
(1) 在扩充功能的时候,不需要改动原有的代码
(2) 封装了LogService具体对象的创建逻辑
(3) 封装了客户代码的实例化过程
(未完……)