论坛首页 Java企业应用论坛

工厂方法模式和抽象工厂模式区别究竟在哪里?

浏览 27331 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2006-02-19  
Factory Method:
Define an interface for create an object,but let subclass decide which class to instantiate.Factory Method lets a class defer instantiation to the subclasses.

Abstract Factory:
Provide an interface for creating families of related or dependent objects without specifying their concrete classes.


我的疑问是:

工厂方法模式能不能看成是一种极端情况的抽象工厂模式,而抽象工厂模式可以看成是工厂方法模式的一种推广?


因为根据定义,工厂方法模式是用来创建一个产品的等级结构的,而抽象工厂模式是用来创建多个产品的等级结构的。

那么假如目前使用工厂方法模式创建不同类型的苹果,示例代码如下:
public interface Factory
{
     Apple createApple();
}

public class ConcreteFactory1 implements Factory
{
     public Apple createApple()
     {
          return new RedApple();
     }

}

public class ConcreteFactory2 implements Factory
{
     public Apple createApple()
     {
          return new GreenApple();
     }
}

上面的代码是使用工厂方法模式。那么现在假如现在我需要创建葡萄,因此需要增加创建葡萄的方法。代码如下:
public interface Factory
{
     Apple createApple();
     Grape createGrape();
}

public class ConcreteFactory1 implements Factory
{
     public Apple createApple()
     {
          return new RedApple();
     }

     public Grape createGrape()
     {
          return new RedGrape();
     }

}

public class ConcreteFactory2 implements Factory
{
     public Apple createApple()
     {
          return new GreenApple();
     }

      public Grape createGrape()
     {
          return new GreenGrape();
     }

}

增加创建葡萄的方法以后,就把一个工厂方法模式变成了一个抽象工厂模式,同样的道理,假如我现在去掉创建葡萄的方法以后,我就把一个抽象工厂模式变成了工厂方法模式。因此可不可以认为这两者之间在不同情况下可以相互转换?

2
“工厂方法模式是采用inheritence,而抽象工厂模式是采用composition。”但是我看不出这就是它们的区别。我同样可以把工厂方法模式中的工厂交给客户端,从而为客户端产生一个产品的不同类型。这样客户端直接依赖于一个工厂,难道这里不也是composition?

3
“工厂方法模式通常和模板方法模式一起结合使用。”但是我仍然看不出来这也是它们的区别。我同样可以把一个抽象工厂模式结合模板方法模式使用。

期待达人解惑!
   发表时间:2006-02-19  
swiminthesea 写道
Factory Method:
Define an interface for create an object,but let subclass decide which class to instantiate.Factory Method lets a class defer instantiation to the subclasses.

Abstract Factory:
Provide an interface for creating families of related or dependent objects without specifying their concrete classes.


我的疑问是:

工厂方法模式能不能看成是一种极端情况的抽象工厂模式,而抽象工厂模式可以看成是工厂方法模式的一种推广?


因为根据定义,工厂方法模式是用来创建一个产品的等级结构的,而抽象工厂模式是用来创建多个产品的等级结构的。

那么假如目前使用工厂方法模式创建不同类型的苹果,示例代码如下:
public interface Factory
{
     Apple createApple();
}

public class ConcreteFactory1 implements Factory
{
     public Apple createApple()
     {
          return new RedApple();
     }

}

public class ConcreteFactory2 implements Factory
{
     public Apple createApple()
     {
          return new GreenApple();
     }
}

上面的代码是使用工厂方法模式。那么现在假如现在我需要创建葡萄,因此需要增加创建葡萄的方法。代码如下:
public interface Factory
{
     Apple createApple();
     Grape createGrape();
}

public class ConcreteFactory1 implements Factory
{
     public Apple createApple()
     {
          return new RedApple();
     }

     public Grape createGrape()
     {
          return new RedGrape();
     }

}

public class ConcreteFactory2 implements Factory
{
     public Apple createApple()
     {
          return new GreenApple();
     }

      public Grape createGrape()
     {
          return new GreenGrape();
     }

}

增加创建葡萄的方法以后,就把一个工厂方法模式变成了一个抽象工厂模式,同样的道理,假如我现在去掉创建葡萄的方法以后,我就把一个抽象工厂模式变成了工厂方法模式。因此可不可以认为这两者之间在不同情况下可以相互转换?

2
“工厂方法模式是采用inheritence,而抽象工厂模式是采用composition。”但是我看不出这就是它们的区别。我同样可以把工厂方法模式中的工厂交给客户端,从而为客户端产生一个产品的不同类型。这样客户端直接依赖于一个工厂,难道这里不也是composition?

3
“工厂方法模式通常和模板方法模式一起结合使用。”但是我仍然看不出来这也是它们的区别。我同样可以把一个抽象工厂模式结合模板方法模式使用。

期待达人解惑!


工厂方法创建一般只有一个方法,创建一种产品。
抽象工厂一般有多个方法,创建一系列产品。
0 请登录后投票
   发表时间:2006-02-19  
pikachu 写道

工厂方法创建一般只有一个方法,创建一种产品。
抽象工厂一般有多个方法,创建一系列产品。



就只有这点区别吗?实在难以让人信服。如果区别就这么简单,为什么要取两个不同的名字呢?
0 请登录后投票
   发表时间:2006-02-19  
swiminthesea 写道
pikachu 写道

工厂方法创建一般只有一个方法,创建一种产品。
抽象工厂一般有多个方法,创建一系列产品。



就只有这点区别吗?实在难以让人信服。如果区别就这么简单,为什么要取两个不同的名字呢?


目的不一样
工厂方法创建 "一种" 产品,他的着重点在于"怎么创建",也就是说如果你开发,你的大量代码很可能围绕着这种产品的构造,初始化这些细节上面。也因为如此,类似的产品之间有很多可以复用的特征,所以会和模版方法相随。

抽象工厂需要创建一些列产品,着重点在于"创建哪些"产品上,也就是说,如果你开发,你的主要任务是划分不同差异的产品线,并且尽量保持每条产品线接口一致,从而可以从同一个抽象工厂继承。



举个不太恰当的例子,如果让我设计一款战略游戏,我可能会设计这样的结构

public interface AbstractForceFactory {
	Unit createUnit(int unitTypeId);;	//一般单位
	Building createBuilding(int buildingTypeId);;	//建筑物
	Hero createHero(int heroTypeId);;	//英雄人物
	
}


然后再设计出 AllyFactory ,RussianFactory等几个产品线。


至于V3Unit,我可能会去调用一个V3UnitFactory.create()去创建,而这个Factory很可能是从一个abstract的VehicleFactory继承下来


或者设计一个V3UnitBuilder ??
1 请登录后投票
   发表时间:2006-02-20  
嗯,有点明白了。

但是我想知道Factory Method模式和Abstract Factory模式是否有严格的区分界限。

我也来举一个例子:
public abstract class AbstractTerranFactory {
	
	//创建机枪兵
	public abstract Marine createMarine();;
	
	//创建喷火兵
	public abstract Fireman  createFireman();;
	
	//创建医生
	public abstract Medical createMedical();;
	
	public void prepare();
	{
		Marine marine = createTank();;
		Fireman fireman = createFireman();;
		Medical medical = createMedical();;
		
		//每个士兵首先要训练
		marine.training();;
		fireman.training();;
		medical.training();;
		
		//然后为每个士兵装备
		marine.equip();;
		fireman.equip();;
		medical.equip();;
	}
}


现在我为上面得TerranFactory提供一个实现,专门创建某一类机枪兵、喷火兵、医生MM。然后出兵之前,调用TerranFactory.prepare()方法。

好,我的问题来了。现在上述工厂涉及到了“创建一类对象”,但是伴随着创建时,也伴随了一些training,equip方法,用到了Template Method模式。那么现在是使用了Factory Method模式还是Abstract Factory模式?

进一步讲,假如现在我去掉创建喷火兵,医生的方法,只留下创建机枪兵的方法,现在又是Factory Method模式还是Abstract Factory模式?
0 请登录后投票
   发表时间:2006-02-20  
swiminthesea 写道
嗯,有点明白了。

但是我想知道Factory Method模式和Abstract Factory模式是否有严格的区分界限。

我也来举一个例子:
public abstract class AbstractTerranFactory {
	
	//创建机枪兵
	public abstract Marine createMarine();;
	
	//创建喷火兵
	public abstract Fireman  createFireman();;
	
	//创建医生
	public abstract Medical createMedical();;
	
	public void prepare();
	{
		Marine marine = createTank();;
		Fireman fireman = createFireman();;
		Medical medical = createMedical();;
		
		//每个士兵首先要训练
		marine.training();;
		fireman.training();;
		medical.training();;
		
		//然后为每个士兵装备
		marine.equip();;
		fireman.equip();;
		medical.equip();;
	}
}


现在我为上面得TerranFactory提供一个实现,专门创建某一类机枪兵、喷火兵、医生MM。然后出兵之前,调用TerranFactory.prepare()方法。

好,我的问题来了。现在上述工厂涉及到了“创建一类对象”,但是伴随着创建时,也伴随了一些training,equip方法,用到了Template Method模式。那么现在是使用了Factory Method模式还是Abstract Factory模式?

进一步讲,假如现在我去掉创建喷火兵,医生的方法,只留下创建机枪兵的方法,现在又是Factory Method模式还是Abstract Factory模式?


ok,好像讨论到一些本质上了。为什么是Abstract,因为是抽象的(好像是废话:D ) ,从FactoryMethod上抽象出来的。我认为每个AbstractFactory创建的都是一条产品线,而这条产品线会有多个子类派生。比如AbstractTerranFactory ,是否会有或者可能有多种实现方式,比如BlizzardTerranFactory,或者WestWoodTerranFactory,或者MicrosoftTerranFactory。如果是这样的,那么ok,至少是一种Abstract Factory。

至于你的代码,其实并不矛盾,没有人说一个类只能是一种设计模式的,你完全可以认为你的AbstractTerranFactory 是一个AbstractFactory + FactoryMethod+Template,如果去掉创建喷火兵,医生的方法,只留下创建机枪兵的方法,就不是AbstractFactory。

另:
design patterns一般是在设计阶段考虑的,所以取名design啊(又是一句废话:D ),真正干活的时候,是先看需求,然后考虑这些需求同哪些模式的适用场合匹配.实际开发中对代码修改后,很可能就随之改变了原来的模式特征,这也很正常,模式之间本来就是可以互相演化和关联的.

再另:
兄弟多大了?现在还玩sc不成?

再再另,你应该refact一下你的代码,Marine marine = createTank();会让人混淆
0 请登录后投票
   发表时间:2006-02-20  
pikachu 写道

ok,好像讨论到一些本质上了。为什么是Abstract,因为是抽象的(好像是废话:D ) ,从FactoryMethod上抽象出来的。我认为每个AbstractFactory创建的都是一条产品线,而这条产品线会有多个子类派生。比如AbstractTerranFactory ,是否会有或者可能有多种实现方式,比如BlizzardTerranFactory,或者WestWoodTerranFactory,或者MicrosoftTerranFactory。如果是这样的,那么ok,至少是一种Abstract Factory。

至于你的代码,其实并不矛盾,没有人说一个类只能是一种设计模式的,你完全可以认为你的AbstractTerranFactory 是一个AbstractFactory + FactoryMethod+Template,如果去掉创建喷火兵,医生的方法,只留下创建机枪兵的方法,就不是AbstractFactory。

另:
design patterns一般是在设计阶段考虑的,所以取名design啊(又是一句废话:D ),真正干活的时候,是先看需求,然后考虑这些需求同哪些模式的适用场合匹配.实际开发中对代码修改后,很可能就随之改变了原来的模式特征,这也很正常,模式之间本来就是可以互相演化和关联的.

再另:
兄弟多大了?现在还玩sc不成?

再再另,你应该refact一下你的代码,Marine marine = createTank();会让人混淆


嗯。了解了,谢谢你得回复。

我下个月23岁。以前大学常常打SC,现在没怎么打了,水平很菜了。

BTW:
听说你手下人常常跳槽,呵呵,这不是你的原因,现在的队伍本来就不好带了。
0 请登录后投票
   发表时间:2006-02-21  
TO pikachu:

正好再问你一下Command模式和Adapter模式的区别。现在我怎么觉得它们两个是一样的。

以Webwork为例(因为Webwork使用了Command模式),先看看我的理解是否正确:
/**
 * 这是Webwork里面的Action接口,它充当了抽象Command的角色。
 */
public interface Action 
{
     public String execute();;
}

/**
 * 该类实现了抽象Command,扮演一个具体的Command角色
 */
public class LoginAction implements Action{
	
    // 该类是不是可以理解为一个Receiver的角色?
    private AccountManager accountManager
	
    public LoginAction(AccountManager accountManager);
   {
           this.accountManager = accountManager;
   }

   public String execute(); {
       accountManager.login();;
       return "login";
  }

}


我的理解是:Webwork中的ServletDispather充当了Invoker的角色。在一个典型的Web应用程序中,有各种请求需要处理,例如登录、查看、删除、增加、修改等等。因此根据需求的不同,会出现AccountManger,ProductManager(Receiver)等等相应的类来处理各种不同请求。然而ServletDispather并不知道该如何调用这些Receiver的方法,因此需要通过一个Action(Command)接受不同的Receiver,由Action负责调用Receiver的方法。而SerlvetDispather只需调用Action.execute()就可以了。不知道以上理解是否正确?


同时我又觉得这非常象Adapter模式。因为可以认为ServletDispather只能处理Action(Adapter模式中的Target角色)类型的接口,而我们的业务逻辑层存在大量诸如AccoutManager、ProduntManager的类(Adapter模式中的Adaptee角色),因此为了让ServletDispather来使用业务逻辑层的类,因此我们编写了诸如LoginAction、ProductAction(Adapter模式中的Adapter角色)来使用业务逻辑层的对象。因此我怎么觉得Command模式非常象Adapter模式?
0 请登录后投票
   发表时间:2006-02-21  
设计模式的不同主要看意图,你如果只看程序的组织形式会发现很多相似的地方,记得那个地方说过这可能是同于编程语言语法的关系.
0 请登录后投票
   发表时间:2006-02-21  
yb31 写道
设计模式的不同主要看意图,你如果只看程序的组织形式会发现很多相似的地方,记得那个地方说过这可能是同于编程语言语法的关系.


楼上的正解,出发点不同,人员不同,一段代码就可能会有多种看法。

以WW的开发人员看来,他们设计框架,Action是他们的Command。从你看来你的Action像是Adaptor。为了将你的Manager适配到ww的制定接口上。


这些本身就不怎么分的清,不过有一点倒是可以作为参考

command是为了让框架结构处理未知的过程,有点回掉的味道。
Adaptor是为了让已经存在的对象转换为另一套接口上
1 请登录后投票
论坛首页 Java企业应用版

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