设计模式演练——工厂方法模式

Posted by Bob Blog on March 28, 2016

Contents

1.小C的故事

       大家好,我叫张小C,我是一个厨师,专职烤面包。下面是我的工作。

    
 
public class World {

	public static void main(String[] args) {
		LittleC littleC = new LittleC();
		littleC.work();
	}
}

public class LittleC {
	public void work() {
		   Bread bread = new Bread();
		   System.out.print(bread.getName()+"做好了!");
		   System.out.println(bread.getTaste());
		 }
}

public class Bread {

	private String name = "面包";

	public String getName() {
		return name;
	}

	public String getTaste(){
		return "软软的,没什么味道";
	}
}

有一天,小明(老顾客)来到张小c的店中,以下是对话---
小明:我吃你家面包都吃腻了,有没有别的吃的,没有的话我以后就换地方了。
小C:有有有,我马上做别的美味出来。

小C心想,我只会烤面包啊,该咋办,难不成再加个workForPizza,那要是这个也吃腻了总不能加到屎吧…况且我脑子笨,学得慢…好吧,爱吃不吃,你不吃自有人吃!(纯属意淫)

2.存在的问题

现在让我们来看一看小C现在面临的问题是什么,先看看work方法中直接new了一个Bread,把自己禁锢在了一种食物中。那有没有什么办法可以解决小c的当前困境呢?

3.工厂方法模式登场

小强:小C,我最近开了一个Pizza店,什么时候过来吃Pizza啊?
小C:太好了,我正愁呢。这样咱们合作,顾客在我这里点Pizza的时候,你们店就给我做一个Pizza送过来。互利共赢嘛。
小强:好,一言为定。
也许最近流行开餐馆,小C的朋友小梅开了家饺子馆,小C用同样的方法让小梅加盟了。 而且为了专心运营,连自己的烤面包工作都外包给小红的面包店了。
经过酝酿,新的设计出现了: 下面是代码摘要:

public class World {

	public static void main(String[] args) {
		LittleC littleC = new LittleC();
		System.out.println("小明:我要吃面包!");
		littleC.setFoodShop(new BreadShop());
		littleC.work();

		System.out.println("小明:我要吃饺子!");
		littleC.setFoodShop(new DumplingShop());
		littleC.work();

		System.out.println("小明:我要吃披萨!");
		littleC.setFoodShop(new PizzaShop());
		littleC.work();
	}
}

/**
 * 小C
 * 
 * @author bob
 */
public class LittleC {

	private FoodShop foodShop;
	
	public void setFoodShop(FoodShop foodShop){
		this.foodShop = foodShop;
	}

	public void work() {
		Food food = foodShop.createFood();
		System.out.print(food.getName() + "做好了!");
		System.out.println(food.getTaste());
	}
} 

public abstract class Food {

	public abstract String getName();

	public abstract String getTaste();
}

public abstract class FoodShop {

	public abstract Food createFood();
}

public class Bread extends Food {

	public String getName() {
		return "面包";
	}

	public String getTaste() {
		return "软软的,很清淡";
	}
}

public class BreadShop extends FoodShop {

	@Override
	public Food createFood() {
		return new Bread();
	}

} 

4.解决了什么,失去了什么

通过引入工厂方法模式我们解决了,Bread硬编码到LittleC中导致的扩展受限问题。小C以后可以接入各种各样的菜色而不需要改动既有代码(world除外)。
缺点也是很明显,我为了一个菜色还要加一个餐馆进来。这里可以通过带有参数到工厂方法来优化这种情况。创造一个什么菜都可以生产的餐馆,比如根据类型完整名称就可以得到具体的食物,那么只需要一个餐馆就可以了。

5.具体应用场景

所有需要new一个对象的地方,同时要求有足够的灵活性。