在上一篇中,我们对《中餐厅》的生产模式进行了改良,不同的菜系由不同的“工厂”生产。但是我们忽略了一个很重要的问题,在生产各种菜系时,各种菜系中所使用的配料谁来生产?比如湘菜和川菜中都使用了辣椒作为配料,但是这两种辣椒品种又是不一样的。这就需要我们了解今天要介绍的“抽象工厂模式”了。
抽象工厂模式是工厂方法模式的升级,他用来创建一组相关或者相互依赖的对象。他与工厂方法模式的区别就在于,工厂方法模式针对的是一个产品等级结构;而抽象工厂模式则是针对的多个产品等级结构。通常一个产品结构,表现为一个接口或者抽象类,也就是说,工厂方法模式提供的所有产品都是衍生自同一个接口或抽象类,而抽象工厂模式所提供的产品则是衍生自不同的接口或抽象类。
在抽象工厂模式中,有一个产品族的概念:所谓的产品族,是指位于不同产品等级结构中功能相关联的产品组成的家族。抽象工厂模式所提供的一系列产品就组成一个产品族;而工厂方法提供的一系列产品称为一个等级结构。我们依然拿中餐厅例子来说明他们之间的区别。
在工厂方法模式中,湘菜、川菜、东北菜都属于同一个产品等级结构,只是由不同的工厂负责生产具体的产品。而抽象工厂模式中,它存在多个产品等级结构,不同的工厂生产不同的菜系和生产不同的配料。我们需要抽象一个接口或者抽象类来承担”顶级“工厂类的角色,然后分别由”菜系工厂”和“配料工厂”来具体生产各自的产品。
在工厂方法模式的基础上增加“配料”类:
package com.pattern.factory.pub;
/**
* 配料接口
* @author
*
*/
public interface Ingredients {
public void ready(String ingName);
}
package com.pattern.factory.pub;
public class HuNanIngredients implements Ingredients{
@Override
public void ready(String ingName) {
System.out.println("【湘菜】配料【"+ingName+"】准备好啦!");
}
}
package com.pattern.factory.pub;
public class SiChuanIngredients implements Ingredients{
@Override
public void ready(String ingName) {
System.out.println("【川菜】配料【"+ingName+"】准备好啦!");
}
}
定义一个顶级工厂抽象类或借口,分别生产食物和配料,不同的菜系实现顶级类方法:
package com.pattern.factory.abstractfactory;
import com.pattern.factory.pub.Food;
import com.pattern.factory.pub.Ingredients;
/**
* 抽象工厂模式的顶级接口:餐厅工厂
* @author
*
*/
public interface RestaurantFactory {
public Ingredients createIngredients(String ingName);//准备配料
public Food createFood(String foodName);//生产食物
}
package com.pattern.factory.abstractfactory;
import com.pattern.factory.pub.Food;
import com.pattern.factory.pub.HuNanFood;
import com.pattern.factory.pub.HuNanIngredients;
import com.pattern.factory.pub.Ingredients;
/**
* 湘菜工厂
* @author
*
*/
public class HuNanFoodFactory implements RestaurantFactory{
@Override
public Food createFood(String foodName) {
HuNanFood food=new HuNanFood();
food.cooking(foodName);
return food;
}
@Override
public Ingredients createIngredients(String ingName) {
Ingredients pepper=new HuNanIngredients();
pepper.ready(ingName);
return pepper;
}
}
package com.pattern.factory.abstractfactory;
import com.pattern.factory.pub.Food;
import com.pattern.factory.pub.Ingredients;
import com.pattern.factory.pub.SiChuanFood;
import com.pattern.factory.pub.SiChuanIngredients;
/**
* 川菜工厂
* @author
*
*/
public class SiChuanFoodFactory implements RestaurantFactory{
@Override
public Food createFood(String foodName) {
SiChuanFood food=new SiChuanFood();
food.cooking(foodName);
return food;
}
@Override
public Ingredients createIngredients(String ingName) {
Ingredients pepper=new SiChuanIngredients();
pepper.ready(ingName);
return pepper;
}
}
测试类:
package com.pattern.test;
import com.pattern.factory.abstractfactory.HuNanFoodFactory;
import com.pattern.factory.abstractfactory.RestaurantFactory;
import com.pattern.factory.abstractfactory.SiChuanFoodFactory;
public class Test {
public static void main(String[] args){
//第一个菜:剁椒鱼头
RestaurantFactory f1=new HuNanFoodFactory();
f1.createIngredients("辣椒");
f1.createFood("剁椒鱼头");
//第二个菜:四川火锅
RestaurantFactory f2=new SiChuanFoodFactory();
f2.createIngredients("辣椒");
f2.createFood("四川火锅");
}
}
优点:
抽象工厂模式除了具有工厂方法模式的优点外,最主要的优点就是可以在类的内部对产品族进行约束。所谓的产品族,一般或多或少的都存在一定的关联,抽象工厂模式就可以在类内部对产品族的关联关系进行定义和描述,而不必专门引入一个新的类来进行管理。
缺点:
产品族的扩展将是一件十分费力的事情,假如产品族中需要增加一个新的产品,则几乎所有的工厂类都需要进行修改。所以使用抽象工厂模式时,对产品等级结构的划分显得尤为重要。