一、介绍
工厂方法模式是通过工厂方法,用不同方式来创建并返回一个对象。
二、实例
实例的UML图如下:
在本模式的例子中,SoupFactoryMethod定义了一个makeSoupBuffet方法,用来返回一个SoupBuffet对象。在SoupFactoryMethod中同样也定义了用来创建SoupBuffet的其它子方法。
class SoupFactoryMethod {
public SoupFactoryMethod() {}
public SoupBuffet makeSoupBuffet() {
return new SoupBuffet();
}
public ChickenSoup makeChickenSoup() {
return new ChickenSoup();
}
public ClamChowder makeClamChowder() {
return new ClamChowder();
}
public FishChowder makeFishChowder() {
return new FishChowder();
}
public Minnestrone makeMinnestrone() {
return new Minnestrone();
}
public PastaFazul makePastaFazul() {
return new PastaFazul();
}
public TofuSoup makeTofuSoup() {
return new TofuSoup();
}
public VegetableSoup makeVegetableSoup() {
return new VegetableSoup();
}
public String makeBuffetName() {
return "Soup Buffet";
}
}
BostonSoupFactoryMethodSubclass继承了SoupFactoryMethod,子类覆写了父类中的makeFishChowder方法,返回一个拥有FishChowder子类BostonFishChowder实例的SoupBffet对象。
class BostonSoupFactoryMethodSubclass extends SoupFactoryMethod {
public String makeBuffetName() {
return "Boston Soup Buffet";
}
public ClamChowder makeClamChowder() {
return new BostonClamChowder();
}
public FishChowder makeFishChowder() {
return new BostonFishChowder();
}
}
class BostonClamChowder extends ClamChowder {
public BostonClamChowder() {
soupName = "QuahogChowder";
soupIngredients.clear();
soupIngredients.add("1 Pound Fresh Quahogs");
soupIngredients.add("1 cup corn");
soupIngredients.add("1/2 cup heavy cream");
soupIngredients.add("1/4 cup butter");
soupIngredients.add("1/4 cup potato chips");
}
}
class BostonFishChowder extends FishChowder {
public BostonFishChowder() {
soupName = "ScrodFishChowder";
soupIngredients.clear();
soupIngredients.add("1 Pound Fresh Scrod");
soupIngredients.add("1 cup corn");
soupIngredients.add("1/2 cup heavy cream");
soupIngredients.add("1/4 cup butter");
soupIngredients.add("1/4 cup potato chips");
}
}
同样,我们也定义了HonoluluSoupFactoryMethodSubclass:
class HonoluluSoupFactoryMethodSubclass extends SoupFactoryMethod {
public String makeBuffetName() {
return "Honolulu Soup Buffet";
}
public ClamChowder makeClamChowder() {
return new HonoluluClamChowder();
}
public FishChowder makeFishChowder() {
return new HonoluluFishChowder();
}
}
class HonoluluClamChowder extends ClamChowder {
public HonoluluClamChowder() {
soupName = "PacificClamChowder";
soupIngredients.clear();
soupIngredients.add("1 Pound Fresh Pacific Clams");
soupIngredients.add("1 cup pineapple chunks");
soupIngredients.add("1/2 cup coconut milk");
soupIngredients.add("1/4 cup SPAM");
soupIngredients.add("1/4 cup taro chips");
}
}
class HonoluluFishChowder extends FishChowder {
public HonoluluFishChowder() {
soupName = "OpakapakaFishChowder";
soupIngredients.clear();
soupIngredients.add("1 Pound Fresh Opakapaka Fish");
soupIngredients.add("1 cup pineapple chunks");
soupIngredients.add("1/2 cup coconut milk");
soupIngredients.add("1/4 cup SPAM");
soupIngredients.add("1/4 cup taro chips");
}
}
前面两个模式中,我们都没有写下定义Soup父子类的创建代码,这里顺便提及以下:
import java.util.ArrayList;
import java.util.ListIterator;
abstract class Soup
{
ArrayList soupIngredients = new ArrayList();
String soupName;
public String getSoupName()
{
return soupName;
}
public String toString()
{
StringBuffer stringOfIngredients = new StringBuffer(soupName);
stringOfIngredients.append(" Ingredients: ");
ListIterator soupIterator = soupIngredients.listIterator();
while (soupIterator.hasNext())
{
stringOfIngredients.append((String)soupIterator.next());
}
return stringOfIngredients.toString();
}
}
class ChickenSoup extends Soup
{
public ChickenSoup()
{
soupName = "ChickenSoup";
soupIngredients.add("1 Pound diced chicken");
soupIngredients.add("1/2 cup rice");
soupIngredients.add("1 cup bullion");
soupIngredients.add("1/16 cup butter");
soupIngredients.add("1/4 cup diced carrots");
}
}
class ClamChowder extends Soup
{
public ClamChowder()
{
soupName = "ClamChowder";
soupIngredients.add("1 Pound Fresh Clams");
soupIngredients.add("1 cup fruit or vegetables");
soupIngredients.add("1/2 cup milk");
soupIngredients.add("1/4 cup butter");
soupIngredients.add("1/4 cup chips");
}
}
class FishChowder extends Soup
{
public FishChowder()
{
soupName = "FishChowder";
soupIngredients.add("1 Pound Fresh fish");
soupIngredients.add("1 cup fruit or vegetables");
soupIngredients.add("1/2 cup milk");
soupIngredients.add("1/4 cup butter");
soupIngredients.add("1/4 cup chips");
}
}
class Minnestrone extends Soup
{
public Minnestrone()
{
soupName = "Minestrone";
soupIngredients.add("1 Pound tomatos");
soupIngredients.add("1/2 cup pasta");
soupIngredients.add("1 cup tomato juice");
}
}
class PastaFazul extends Soup
{
public PastaFazul()
{
soupName = "Pasta Fazul";
soupIngredients.add("1 Pound tomatos");
soupIngredients.add("1/2 cup pasta");
soupIngredients.add("1/2 cup diced carrots");
soupIngredients.add("1 cup tomato juice");
}
}
class TofuSoup extends Soup
{
public TofuSoup()
{
soupName = "Tofu Soup";
soupIngredients.add("1 Pound tofu");
soupIngredients.add("1 cup carrot juice");
soupIngredients.add("1/4 cup spirolena");
}
}
class VegetableSoup extends Soup
{
public VegetableSoup()
{
soupName = "Vegetable Soup";
soupIngredients.add("1 cup bullion");
soupIngredients.add("1/4 cup carrots");
soupIngredients.add("1/4 cup potatoes");
}
}
当然,这里也定义了集合对象SoupBuffet:
class SoupBuffet {
String soupBuffetName;
ChickenSoup chickenSoup;
ClamChowder clamChowder;
FishChowder fishChowder;
Minnestrone minnestrone;
PastaFazul pastaFazul;
TofuSoup tofuSoup;
VegetableSoup vegetableSoup;
public String getSoupBuffetName() {
return soupBuffetName;
}
public void setSoupBuffetName(String soupBuffetNameIn) {
soupBuffetName = soupBuffetNameIn;
}
public void setChickenSoup(ChickenSoup chickenSoupIn) {
chickenSoup = chickenSoupIn;
}
public void setClamChowder(ClamChowder clamChowderIn) {
clamChowder = clamChowderIn;
}
public void setFishChowder(FishChowder fishChowderIn) {
fishChowder = fishChowderIn;
}
public void setMinnestrone(Minnestrone minnestroneIn) {
minnestrone = minnestroneIn;
}
public void setPastaFazul(PastaFazul pastaFazulIn) {
pastaFazul = pastaFazulIn;
}
public void setTofuSoup(TofuSoup tofuSoupIn) {
tofuSoup = tofuSoupIn;
}
public void setVegetableSoup(VegetableSoup vegetableSoupIn) {
vegetableSoup = vegetableSoupIn;
}
public String getTodaysSoups() {
StringBuffer stringOfSoups = new StringBuffer();
stringOfSoups.append(" Today's Soups! ");
stringOfSoups.append(" Chicken Soup: ");
stringOfSoups.append(this.chickenSoup.getSoupName());
stringOfSoups.append(" Clam Chowder: ");
stringOfSoups.append(this.clamChowder.getSoupName());
stringOfSoups.append(" Fish Chowder: ");
stringOfSoups.append(this.fishChowder.getSoupName());
stringOfSoups.append(" Minnestrone: ");
stringOfSoups.append(this.minnestrone.getSoupName());
stringOfSoups.append(" Pasta Fazul: ");
stringOfSoups.append(this.pastaFazul.getSoupName());
stringOfSoups.append(" Tofu Soup: ");
stringOfSoups.append(this.tofuSoup.getSoupName());
stringOfSoups.append(" Vegetable Soup: ");
stringOfSoups.append(this.vegetableSoup.getSoupName());
return stringOfSoups.toString();
}
}
实际过程中,我们实践工厂方法模式代码如下:
class TestSoupFactoryMethod {
public static void main(String[] args) {
SoupFactoryMethod soupFactoryMethod =
new SoupFactoryMethod();
SoupBuffet soupBuffet =
soupFactoryMethod.makeSoupBuffet();
soupBuffet.setSoupBuffetName(
soupFactoryMethod.makeBuffetName());
soupBuffet.setChickenSoup(
soupFactoryMethod.makeChickenSoup());
soupBuffet.setClamChowder(
soupFactoryMethod.makeClamChowder());
soupBuffet.setFishChowder(
soupFactoryMethod.makeFishChowder());
soupBuffet.setMinnestrone(
soupFactoryMethod.makeMinnestrone());
soupBuffet.setPastaFazul(
soupFactoryMethod.makePastaFazul());
soupBuffet.setTofuSoup(
soupFactoryMethod.makeTofuSoup());
soupBuffet.setVegetableSoup(
soupFactoryMethod.makeVegetableSoup());
System.out.println("At the " +
soupBuffet.getSoupBuffetName() +
soupBuffet.getTodaysSoups());
SoupFactoryMethod bostonSoupFactoryMethod =
new BostonSoupFactoryMethodSubclass();
SoupBuffet bostonSoupBuffet =
bostonSoupFactoryMethod.makeSoupBuffet();
bostonSoupBuffet.setSoupBuffetName(
bostonSoupFactoryMethod.makeBuffetName());
bostonSoupBuffet.setChickenSoup(
bostonSoupFactoryMethod.makeChickenSoup());
bostonSoupBuffet.setClamChowder(
bostonSoupFactoryMethod.makeClamChowder());
bostonSoupBuffet.setFishChowder(
bostonSoupFactoryMethod.makeFishChowder());
bostonSoupBuffet.setMinnestrone(
bostonSoupFactoryMethod.makeMinnestrone());
bostonSoupBuffet.setPastaFazul(
bostonSoupFactoryMethod.makePastaFazul());
bostonSoupBuffet.setTofuSoup(
bostonSoupFactoryMethod.makeTofuSoup());
bostonSoupBuffet.setVegetableSoup(
bostonSoupFactoryMethod.makeVegetableSoup());
System.out.println("At the " +
bostonSoupBuffet.getSoupBuffetName() +
bostonSoupBuffet.getTodaysSoups());
SoupFactoryMethod honoluluSoupFactoryMethod =
new HonoluluSoupFactoryMethodSubclass();
SoupBuffet honoluluSoupBuffet =
honoluluSoupFactoryMethod.makeSoupBuffet();
honoluluSoupBuffet.setSoupBuffetName(
honoluluSoupFactoryMethod.makeBuffetName());
honoluluSoupBuffet.setChickenSoup(
honoluluSoupFactoryMethod.makeChickenSoup());
honoluluSoupBuffet.setClamChowder(
honoluluSoupFactoryMethod.makeClamChowder());
honoluluSoupBuffet.setFishChowder(
honoluluSoupFactoryMethod.makeFishChowder());
honoluluSoupBuffet.setMinnestrone(
honoluluSoupFactoryMethod.makeMinnestrone());
honoluluSoupBuffet.setPastaFazul(
honoluluSoupFactoryMethod.makePastaFazul());
honoluluSoupBuffet.setTofuSoup(
honoluluSoupFactoryMethod.makeTofuSoup());
honoluluSoupBuffet.setVegetableSoup(
honoluluSoupFactoryMethod.makeVegetableSoup());
System.out.println("At the " +
honoluluSoupBuffet.getSoupBuffetName() +
honoluluSoupBuffet.getTodaysSoups());
}
}
三、分析
从例子中,我们可以针对工厂方法模式,统计出的以下这些角色:
- Prodcut 定义工厂方法所创建的对象的接口,如我们例子中Soup类。 ConcreteProduct 实际产品,扩展了Soup接口类。如这里的FishChowder,BostonFishChowder等等。
- Creator 工厂方法,该方法返回一个Product对象。如这SoupFactoryMethod里的makeFishChowder方法。
- ConcreteCreator 重定义一个方法,并返回一个ConcreteProduct对象。如BostonSoupFactoryMethodSubclass中的makeFishChowder方法。
实现一个工厂方法模式,需要以下几个关键步骤:
1、定义基础产品类和相关的扩展产品类。
2、定义一个基础的工厂方法类,其中定义make产品的方法。
3、扩展基础工厂方法类,覆写已有的make方法,输出的产品含有扩展产品的信息。
以上的例子,我自己理解的时候,也感觉有点含糊。到底抽象工厂模式和工厂方法模式有什么差别?这里我自己总结了一下,欢迎指正。
区别于抽象工厂模式(Abstract Factory),工厂方法模式只用来make一种产品SoupBuffet,工厂接口本身不关心其子类Soup如何定义产生。确切的说,工厂方法模式的最终目的就是制造某种具体的产品,但返回的结果根据实际加工工艺的不同,会生成不同风格的成品。
换一种说法,抽象工厂模式可以生成多种产品,而工厂方法模式却只用来生成一种产品。如果把抽象工厂模式中的多种产品削减到一个品种,那么也就成了我们这里的工厂方法模式的一个简单模型。
可能在其它的设计模式的书本中,会接触到“简单工厂模式”,这种模式就更简单了。直接一个ConcreteCreator类就可以了,根据传入的参数不同,直接make返回该品种的实际产品。