论坛首页 招聘求职论坛

工厂方法---抽象工厂之我见

浏览 2715 次
精华帖 (0) :: 良好帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2008-09-12  
这段时间在学习设计模式,把自己学习的心得写一下,分享一下,也让大家指出一下理解上有什么不对。这是我最早接触的一个设计模式,也是大家很熟悉的。在文章的末尾会提出一个学习过程中对这个设计模式的疑问。对于这些代码的演变过程,尤其是工厂方法到抽象工厂,不知道这样理解是否正确。请大家指正下。
场景是这样的,我想开一家店,水果专卖店,但是不知道该专卖哪种水果比较赚钱。于是有了一段一下的代码:
public class Dian {
     private Fruit shuiguo;
     public void KaiDian(String type){
    if(type.equals("苹果")){
    shuiguo=new PingGuo();
    }
    else if(type.equals("梨")){
    shuiguo=new Li();
    }
    else if(type.equals("香蕉")){
    shuiguo=new XiangJiao();
    }
    ...........
         ...........
     }
}

对于以上代码,由相当多的if else组成,只有当运行时才知道要卖哪中水果。如果想加入新类型的水果或移除那么必须修改这个类,这里就是一个变化点,于是有了以下做法。
public class SimpleFruitFactory {
private Fruit shuiguo;
public Fruit createFruit(String type){
if(type.equals("苹果")){
    shuiguo=new PingGuo();
    }
    else if(type.equals("梨")){
    shuiguo=new Li();
    }
    else if(type.equals("香蕉")){
    shuiguo=new XiangJiao();
    }
    ........
          ........
         return shuiguo;
}
}
以上只不过把这段代码从一个地方搬到另一个地方,仍然存在原来的毛病。但是却把对象的创建过程进行统一的管理,假如有10个客户程序用到这个创建对象的过程,按原来的做法那么必须修改10个地方,那么这么一来就只要改一个地方。这就简单工厂带来的好处。(不知道还有没有,请多说说)。但是它没有做到很好的开闭原则,对扩展不是很好。
于是,改成以下的做法,工厂方法:
public abstract class Dian {
private Fruit shuiguo;
public void KaiDian(){
shuiguo=createFruit();
          .....
          .....
         }
     public abstract Fruit createFruit();
}
这样,把对象的实例化推给Dian的子类。比如,如果我想开加苹果专卖,只要写:
public class PingGuoDian extends Dian{
public Fruit createFruit() {
return new PingGuo();
}
}
这样就算将来有新的水果类型产生,我想转去开那种水果店,也无须修改原来的代码,只要做一个店extends Dian然后由工厂方法产生我要的水果。对于扩展可以是非常好的。解决了简单工厂带来的毛病。
但是由于我很会做生意,于是店开始扩张,并不满足只卖水果了,于是,我把店用木版阁成了好几块,开始做成各种各样的专卖,有肉专卖,鱼专卖,蔬菜专卖。。。。。。。。。
于是为了好扩展,那么自然想到用工厂方法,于是产生以下做法:
public abstract class Dian {
private Fruit shuiguo;
private Rou rou;
private Yu yu;
private ShuCai shucai;
public void KaiDian() {
shuiguo = createFruit();
rou = createRou();
yu = createYu();
shucai = createShuCai();
                  ........
                  ........//其他操作
}
public abstract Fruit createFruit();
public abstract Rou createRou();
public abstract Yu createYu();
public abstract ShuCai createShuCai();
         ...........
         ...........//其他方法
}
那么,在这个地方,将会有许多的对象创建的抽象方法,这样就有一个毛病就是,对象的创建的抽象方法会与其他的不是对象创建的抽象方法混杂在一起,与是我们就有了类似与简单工厂的做法,把这些创建对象的抽象方法抽出来放在一个工厂里面,我们称之为抽象工厂。抽象工厂自我理解是:抽象(动词) 工厂(工厂方法)。
于是,就有了以下做法:
public abstract class AbstractFactory {
public abstract Fruit createFruit();
public abstract Rou createRou();
public abstract Yu createYu();
public abstract ShuCai createShuCai();
}
那我们的店应该就写成如下了:
public   class Dian {
private Fruit shuiguo;
private Rou rou;
private Yu yu;
private ShuCai shucai;
private AbstractFactory factory;
public Dian(AbstractFactory factory){
this.factory=factory;
}
public void KaiDian() {
shuiguo = factory.createFruit();
rou = factory.createRou();
yu = factory.createYu();
shucai = factory.createShuCai();
}
}
它依赖于这个抽象工厂,我们可以看出,我的这家店并不依赖任何的具体实现,也就说你们并不知道我要专卖的系列产品是什么。刚开店的时候,在夏天,于是,我想西瓜,草鱼,猪肉,大头菜在这个季节销量比较好。于是,我开始卖这样的系列产品。于是,我叫一个专门工厂给我做了这样的产品:
public class XiaTianFactory extends AbstractFactory{
public Fruit createFruit() {
return new XiGua();
}
public Rou createRou() {
return new ZhuRou();
}
public ShuCai createShuCai() {
return new DaTouCai();
}
public Yu createYu() {
return new CaoYu();
}
}
跟这样的工厂合作(把这个工厂实力给我的店)于是就可以卖这样的系列的产品了。
到了冬天,西瓜不好销售了,转而香蕉销售比较好,狗肉销量大增了,于是我想卖狗肉,大头菜不新鲜了,而土豆比较新鲜。。。。。。。于是我想换产品系列了,那么我们我只要换家工厂合作即可,我并不需要把店拆了,在重新开一家。
以上就是我从简单工厂--工厂方法--抽象工厂的理解。理解尚浅,请各位前辈给于补充和指正。
问题的提出:看过一些资料,把工厂方法写成这样。如,我们把上面工厂方法那段改成的写法:
public abstract class AbstractFactory {
public abstract Fruit createFruit();
}
public   class Dian {
private Fruit shuiguo;
public Dian(AbstractFactory factory){
this.factory=factory;
}
public void KaiDian() {
shuiguo = factory.createFruit();
}
}
个人觉的这个其实就是抽象工厂,只不过你的系列产品只有一个而已。我们对工厂方法的定义中其中有一个是:把实例化推迟给子类,那么以上的做法是不是并没有按照这个???因为我的店已经是具体类了,怎么推迟给子类?反而的更象是抽象工厂吧。个人还觉的工厂方法与抽象工厂的区别在与,工厂方法是通过继承,转而把实例化对象交给子类处理,而抽象工厂是通过组合,组合一个抽象工厂,由抽象工厂提供。不过看了一些资料都把以上想法说成是工厂方法,不知道是不是我哪里还没体会到,请各位指正下,学习中。。。。。。。。。。


10月就有招聘会了,不知道我这个水平能不能找到工作,现有的知识够不够“忽悠”hr了???改天做份简历,发上来让大家给指正下。
论坛首页 招聘求职版

跳转论坛:
Global site tag (gtag.js) - Google Analytics