工厂模式的疑问

02-12-30 redlan
设计模式之Factory

其中提到:
...让创建实例所需要的大量初始化工作从Sample的构造函数中分离出去。

这时我们就需要Factory工厂模式来生成对象了,不能再用上面简单new Sample(参数)。....

我认为工厂模式与被创建对象的构造函数做多少工作没有多大关系。最简单的例子:

Factory类的片断

public Sample getInstance(String arg) {
    if (arg.equals("A")) {
        return new SampleA();
    } else if (arg.equals("B")){
        return new SampleB();
    }
}
<p class="indent">


这时候,我们仍然可以在SampleA的构造函数中做很多事情,情况如下:

public SampleA() {
    //创建数据库连接
    //查询数据库中某表的某个字段值,并赋值给实例变量
    //等等
}
<p class="indent">


希望banq能不厌其烦为学生指点一二,谢谢。

richardluopeng
2002-12-30 13:32
呵呵,你这样好危险!
违反了OO的原则

fuzhou
2002-12-30 14:07
我也认为工厂模式解决的不是将初始化的大量工作从构造方法中分离出去的问题,而只能是说将使用该类时的紧耦合(用new Object()实现)变成一种松耦合,也就是使用的时候不直接创建对象,而是使用工厂方法,这样在将来有变动的时候可以非常轻松的改变code。

fuzhou
2002-12-30 14:08
不太明白,违反了什么oo的原则?是说sample中作的东西太多了,还是?????

banq
2002-12-30 15:20
封装(Encapsulation)和分派(Delegation)
sampleA class本身就定义自己是什么,而不要定义自己怎么构造的,比喻一个不是很恰当的例子: 人 作为一个class 如果让你来定义,你肯定定义这么几个属性:性别 高度 职业 等等,你不会将他如何出生以及如何长大的过程定义在里面。

这两种定义应该分派,分别封装在不同class中。

redlan
2002-12-30 15:36
作为SampleA和SampleB的接口Sample,它的作用是定义了但凡实现该类的其它类“是什么”,而诸如SampleA和SampleB的作用是根据接口Sample的定义来构造(实现接口Sample中定义的方法)自己,不知道我这样说是否正确?如果是这样,那么我们假设SampleA和SampleB分别为具体的某个“男人”和具体的某个“女人”,我们势必要对这个具体的人增加些有血有肉得东西:

实现接口中定义的方法的同时增加一些特殊的方法

继续我们的假设,通常一个人初始化是2条腿,但是不幸的是,我们这里的man由于先天不足,初始化时候只能是1条腿,那么我们就要在构造子中写入:

this.leg = 1;


当然,这个过于绝对的例子并不能很好的表达我的意思,但是,我依然认为,对构造函数的改造不应属于使用factory这个模式所带来的影响。

banq
2002-12-30 21:17
sample接口定义“是什么”,而诸如SampleA和SampleB的作用是根据接口Sample的来继续丰富定义“是什么”。

redlan
2002-12-31 12:57
那么难道我们在继续丰富SampleA和SampleB“是什么”的时候就不能在构造函数中调用方法(诸如查询数据库等等)吗?

如果可以(当然这样做并不很好)

那么,工厂模式与简化构造函数所作的事情又有什么关系呢?我认为工厂模式仅仅是以取代通常的new关键字而引发的一种设计模式,它的目的在于尽可能少的修改代码而为系统添加新的功能。SampleA和SampleB是工厂模式的两个具体产品,他们在实现或继承接口类或抽象类的同时理应有属于自己的实现方法,哪怕部分操作是写在构造函数中,工厂并不关心产品的这些方方面面,它唯一关心的是它能产生什么样产品(例如,在静态工厂模式中,我们需要在工厂类的方法中写明return new ...)。你说呢?

banq
2002-12-31 13:56
因为Factory就是分离SampleA中的构造函数,如果你在SampleA的构造函数中加入“查询数据库”,当然不可以,查询数据库 是个重量级别的操作,应该放入Factory模式中。

如果是一些简单赋值,如this.a = a ,就无需使用Factory. 总之,如果你的构造函数变得复杂了,那么就要重整(refactor)到Factory模式。

redlan
2002-12-31 15:05
应该放入Factory模式中

放入工厂类或抽象产品类还是具体产品类?疑惑中

fuzhou
2003-01-02 11:17
为什么重量级的操作就要放在factory中,factory不是生成对象的地方吗,它为什么要负责对象生成的具体细节。

浮舟
2003-01-06 20:06
为什么版主不回答这里的问题了:(

mem_fox
2003-01-09 10:31
假设你Factory产生的对象都要用的数据库连接,那么我就把数据库连接建立放置在Factory里面,然后在getInstance()时分给一个可用的连接,这个好像就是连接池的做法吧

banq
2003-01-09 15:41
这个可以参考Jive中的ForumFactory 它的forum产生是从数据库中通过Factory模式得到的

jxb8901
2003-01-09 18:04
我查看了Jive中DBForumFactory和DBForum的代码, 在DBForumFactory中的createForum()方法中, 只是简单判断要创建的Forum是否存在, 若不存在则仍调用DBForum的构造器生成对象, 而DBForum的构造中则会访问数据库以初始化自身, 这和banq所说的"重量级别的操作,应该放入Factory模式中" 的说法不是矛盾了吗?

也就是说forum是自己从数据库中产生的!?

2Go 1 2 下一页