在装饰者模式中我们讲到一条设计原则,即我们应该为对象间的松耦合而努力。
在初始化对象时,除了使用new操作符之外,还有更多制造对象的方法,实例化这个活动不应该总是公开的进行,初始化经常造成“耦合”问题,我们不希望这样,而工厂模式能够将我们从复杂的依赖中解脱出来。
工厂模式
- 简单工厂模式
- 工厂方法
- 抽象工厂模式
简单工厂模式
准确的说,简单工厂其实不是一个设计模式,反而比较像是一种编程习惯
- 工厂客户:持有工厂的依赖,使用工厂生产出来的产品,不关系产品的具体生产过程
- 简单工厂:生产产品,即负责产品的实例化
- 抽象产品:产品类接口
- 具体产品:具体产品实现类
例子
现在有家披萨店,里面有奶酪披萨(cheese pizza),意大利香肠披萨(pepperoni pizze),素披萨(veggie pizza)这三种披萨,对外提供一个预定披萨的方法(orderPizza),我们来看下非工厂模式下会如何实现:
package factory;
/**
* 披萨店,提供预定披萨的做法
*/
public class PizzaStore {
public Pizza orderPizza(String type){
Pizza pizza = null;
if(type.equals("cheese")){
pizza = new CheesePizza();
}else if(type.equals("pepperoni")){
pizza = new PepperoniPizza();
}else if(type.equals("veggie")){
pizza = new VeggiePizza();
}
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
return pizza;
}
}
如果这家店现在上新了新披萨,或者说不做某种披萨了,那么我们就会对这段代码将作出大量改动,即
我们没有对变化的部分封装
那么接下来我们就使用简单工厂来实现这个功能:
package factory;
/**
* 简单披萨工厂
*/
public class SimplePizzaFactory {
public Pizza createPizza(String type){
Pizza pizza = null;
if(type.equals("cheese")){
pizza = new CheesePizza();
}else if(type.equals("veggie")){
pizza = new PepperoniPizza();
}else if(type.equals("epperoni")){
pizza = new VeggiePizza();
}
return pizza;
}
}
package factory;
/**
* 披萨店,提供预定披萨的做法
*/
public class PizzaStore {
private SimplePizzaFactory pizzaFactory = new SimplePizzaFactory();
public Pizza orderPizza(String type){
Pizza pizza = pizzaFactory.createPizza(type);
// if(type.equals("cheese")){
// pizza = new CheesePizza();
// }else if(type.equals("pepperoni")){
// pizza = new PepperoniPizza();
// }else if(type.equals("veggie")){
// pizza = new VeggiePizza();
// }
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
return pizza;
}
}
我们看到,披萨的实例化功能交给了这个工厂类实现,需要改动的话只需到工厂类中去改动,披萨店不再关系披萨的具体实例化过程,它只知道它拿到的是“一份披萨”,但缺点就是,改动依旧需要到工厂类中去改。
工厂方法
如果现在有另外一家地区的披萨店想加盟,但是因为两个地区之间的烘焙,准备原料方法都有差异,所以做出来的披萨是不一样的,那么针对这种需求,我们又该怎么办呢?工厂方法是一个很好的选择,它定义了一个创建对象的接口,但由子类来决定具体实例化的是哪个。工厂方法把实例化工作交给了子类。
- 客户:不再赘述
- 抽象产品:即一类产品族
例子
以上述披萨店加盟为例,地区A为北京,地区B为上海
改写父类披萨店,让其添加抽象方法——创建披萨:
package factory;
/**
* 披萨店,提供预定披萨的做法
*/
public abstract class PizzaStore {
// private SimplePizzaFactory pizzaFactory = new SimplePizzaFactory();
public Pizza orderPizza(String type){
Pizza pizza = createPizza(type);
// Pizza pizza = pizzaFactory.createPizza(type);
// if(type.equals("cheese")){
// pizza = new CheesePizza();
// }else if(type.equals("pepperoni")){
// pizza = new PepperoniPizza();
// }else if(type.equals("veggie")){
// pizza = new VeggiePizza();
// }
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
return pizza;
}
public abstract Pizza createPizza(String type);
//其他方法
}
分别实现上海和北京的披萨店
package factory;
/**
* 北京的披萨店
*/
public class PekingPizzaStore extends PizzaStore {
@Override
public Pizza createPizza(String type) {
Pizza pizza = null;
if(type.equals("cheese")){
pizza = new CheesePizza();
}else if(type.equals("pepperoni")){
pizza = new PepperoniPizza();
}else if(type.equals("veggie")){
pizza = new VeggiePizza();
}
return pizza;
}
}
package factory;
/**
* 上海披萨店
*/
public class ShanghaiPizzaStore extends PizzaStore {
@Override
public Pizza createPizza(String type) {
Pizza pizza = null;
if(type.equals("cheese")){
pizza = new CheesePizza();
}
return pizza;
}
}
接下去,我们就可以利用上海或者北京的披萨店来实例化我们的披萨了。
抽象工厂
现在我们有了两家分店,但很显然,这两家分店用来做披萨的原料不会一样,因为两个地区人们的口味不一样,现在,我们需要创建原料工厂类满足这个功能,在这里,抽象工厂模式得到了很好的体现。
例子
首先,让我们创建一个原料工厂:
package factory;
/**
* 原料工厂接口
*/
public interface PizzaIngredientFactory {
Dough createDough();
Sauce createSauce();
Cheese createCheese();
}
上海原料工厂
package factory;
public class SHPizzaIngredientFactory implements PizzaIngredientFactory {
@Override
public Dough createDough() {
return new Dough();
}
@Override
public Sauce createSauce() {
return new Sauce();
}
@Override
public Cheese createCheese() {
return new Cheese();
}
}
改写披萨类(以奶油披萨为例)
package factory;
public class CheesePizza extends Pizza {
PizzaIngredientFactory ingredientFactory;
public CheesePizza(PizzaIngredientFactory ingredientFactory) {
this.ingredientFactory = ingredientFactory;
}
@Override
public void prepare() {
dough = ingredientFactory.createDough();
sauce = ingredientFactory.createSauce();
cheese = ingredientFactory.createCheese();
}
@Override
public void bake() {
}
@Override
public void cut() {
}
@Override
public void box() {
}
}
实现上海披萨店:
package factory;
/**
* 上海披萨店
*/
public class ShanghaiPizzaStore extends PizzaStore {
@Override
public Pizza createPizza(String type) {
PizzaIngredientFactory pizzaIngredientFactory = new SHPizzaIngredientFactory();
Pizza pizza = null;
if(type.equals("cheese")){
pizza = new CheesePizza(pizzaIngredientFactory);
}
return pizza;
}
}
源码在这里:我的github地址