工厂模式是一种常见的模式,所有开始学习模式的人差不多第二个接触的就是工厂模式了(第一个是单例模式),工厂模式使用时的代码就像这样的:

工厂模式我的感觉好处是:
- 客户使用接口访问服务,升级能力增强;
- 可实现服务的配置;
容器我感觉是对工厂模式的改进,在.NET中关于容器可以看System.ComponentModel命名空间。
容器提出了将组件隔离开的思想,组件获取其他的服务是通过向容器申请的,而不是向工厂申请的。这样的好处是组件可以适应不同的工作环境(容器),也就大大提高了组件的复用能力。
拿我写了一个AccountService为例,内部包含一个Save方法,使用工厂模式的程序是这样写的。











数据服务层的获取是通过工厂获取的,有一天,我们的头突然跟我说:嘿,我们把这个Account存放到另外一个数据库吧。我傻眼了,我只有在DbService中的实现中加一个If 是Account就使用另外一个连接,Else 用原先的连接。如果要移动的实体一多,我就不得做一个XML配置,来区分存放的数据库。虽然也可以,但总觉得不爽。
使用容器的方式就显得跟好一些,将上面的代码重构:










注意现在的this.GetService实际上是向容器申请服务,所以我将这个AccountService存放到不同的容器,也就可以申请到不同的IDbService了。
但容器模式也有自己的问题,例如对象初始化时,站点(Site)对象没有注入,这个时候是无法获取服务的。当然也有变通的办法,例如MS生成的代码就是这样的:
public Timer(System.ComponentModel.IContainer container)
也就是在初始化将容器作为参数传入。
还有就是子容器的问题,大家注意到刚才的DbService了吗?申请的DbService没有加入容器,不是我不想加,而是加了之后就等于我的组件决定了他的运行环境,而这个又和容器的可配置初衷向矛盾。这样造成我编写的组件一部分是工作在容器下,另外一部分工作没有工作在容器下,编程复杂度增加了。
还有一个问题,如果我的组件作为WebService、.NET Remote的服务组件,我无法干涉这些组件的创建,我如何为他们创建容器呢?
问题多多啊,放在首页,希望有高人指点啊。(有点论坛的味)