您的位置:首页 > 编程语言 > Java开发

设计模式--抽象工厂模式(八)

2017-07-10 09:16 113 查看
目录:注意,此模式涉及的示例,来自于工厂模式笔记:工厂模式
抽象工厂模式:提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类;
知识点的梳理:
抽象工厂使用对象组合:对象的创建被实现在工厂接口所暴露出来的方法中;

抽象工厂创建相关的对象家族,而不需要依赖它们的具体类;
  

再回到比萨店。。。

现在我们需要确保每家加盟店使用的原料都是高质量的。现在打算建造一家生产原料的工厂,并将原料运送到各家加盟店。而对于纽约和芝加哥需要准备两组不同的原料;
所谓的原料只是大家都使用相同的产品,但是各个地区的制作方式却又各不相同;

建造原料工厂
注意,示例中出现的所有类,如果没有给出具体代码,就定义一个空实现即可;
现在,我们要建造一个工厂来生产原料,这个工厂将负责创建各个加盟店所需要的各种原料。但不关心各个加盟店如何使用这些原料;

public interface PizzaIngredientFactory {

//在接口中,每个原料都有一个对应的方法创建该原料
publicDough createDough();
publicSauce createSauce();
publicCheese createCheese();
publicVeggies[] createVeggies();
publicPepperoni createPepperoni();
publicClams createClam();
}

要做的事情是:
为每个区域建造一个工厂。需要创建一个继承自PizzaIngredientFactory的子类来实现每一个创建方法;
实现一组原料类供工厂使用,例如ReggianoCheese,RedPeppers,ThickCrust-Dough。这些类可以在合适的区域间共享;
然后仍然需要将这一切组织起来,将新的原料工厂整合进旧的PizzaStore代码中;

创建纽约原来工厂

//具体原料工厂必须实现这个接口,纽约原来工厂也不例外

public class NYPizzaIngredientFactoryimplements PizzaIngredientFactory {

@Override
public Dough createDough() {
return new ThinCrustDough();
}
@Override
public Sauce createSauce() {
return new MarinaraSauce();
}
@Override
public Cheese createCheese() {
return new ReggianoCheese();
}
@Override
public Veggies[] createVeggies() {
//对于蔬菜,以一个蔬菜数组为返回值。在这里我们是直接把蔬菜写死,仅仅是为了测试使用
Veggiesveggies[] = {new Garlic(),new
Onion(),new Mushroom(),new RedPepper()};
returnveggies;
}
@Override
public Pepperoni createPepperoni() {
//切片的腊肠
return new SlicedPepperoni();
}
@Override
public Clams createClam() {
//新鲜的蛤蜊
return new FreshClams();
}
}

重做比萨
生产原来的工厂已经创建完毕,现在只需要重做比萨,好让它们只使用工厂生产出来的原料。先从抽象的Pizza类开始:

public abstract class Pizza {

Stringname;
Doughdough;
Saucesauce;
Veggiesveggies[];//每个比萨都持有一组在准备时会用到的原料
Cheesecheese;
Clamsclam;
//现在把prepare()方法声明为抽象。在这个方法中,我们需要收集比萨所需的原料,而这些原料当然是来自原料工厂
abstract void prepare();
public void bake(){
System.out.println("Bake for 25 minutes at 350");
}
public void cut(){
System.out.println("Cutting the pizza into diagonal slices");
}
public void box(){
System.out.println("Place pizza in official PizzaStore box");
}
public void setName(Stringname){
this.name =name;
}
public String getName(){
returnname;
}
  
@Override
public String toString() {
return"Pizza [name=" +name +
", dough=" +dough +", sauce=" +
sauce +", veggies=" + Arrays.toString(veggies)
+", cheese=" +cheese +
", clam=" +clam +"]";
}
}

继续重做比萨
现在已经有了一个抽象比萨,可以开始创建纽约和芝加哥风味的比萨了。此后,加盟店必需直接从工厂取得原料;

public class CheesePizzaextends Pizza {

PizzaIngredientFactoryingredientFactory;
//要制作比萨,需要工厂提供原料。所以每个比萨类都需要构造器参数中得到一个工厂,并把这个工厂存储在一个实例变量中
public CheesePizza(PizzaIngredientFactoryingredientFacotry){
this.ingredientFactory =ingredientFacotry;
}
@Override
void prepare() {
//prepare()方法一步一步地创建芝士比萨,每当需要原料时,就跟工厂要
System.out.println("Preparing "
+ name);
dough =ingredientFactory.createDough();
sauce =ingredientFactory.createSauce();
cheese =ingredientFactory.createCheese();
}
}



然后是蛤蜊比萨

public class ClamPizzaextends Pizza {

PizzaIngredientFactoryingredientFactory;
public ClamPizza(PizzaIngredientFactoryingredientFactory){
//蛤蜊比萨也需要原料工厂
this.ingredientFactory =ingredientFactory;
}
@Override
void prepare() {
//要做出蛤蜊比萨,prepare()方法就必须从本地工厂中取得正确的原料
System.out.println("Preparing "+name);
dough =ingredientFactory.createDough();
sauce =ingredientFactory.createSauce();
cheese =ingredientFactory.createCheese();
clam =ingredientFactory.createClam();

}

public class VeggiePizzaextends Pizza {

PizzaIngredientFactoryingredientFactory;
public VeggiePizza(PizzaIngredientFactoryingredientFacotry){
this.ingredientFactory =ingredientFacotry;
}
@Override
void prepare() {
System.out.println("Preparing "
+ name);
dough =ingredientFactory.createDough();
sauce =ingredientFactory.createSauce();
cheese =ingredientFactory.createCheese();
}
}

再回到比萨店

public class NYPizzaStoreextends PizzaStore {

@Override
protected Pizza createPizza(Stringtype) {
Pizzapizza =null;
//纽约店会用到纽约比萨原料工厂,由该原料工厂负责生产所有纽约风味比萨所需要的原料
PizzaIngredientFactoryingredientFactory =new
NYPizzaIngredientFactory();
if(type.equals("cheese")){
//把工厂传递给每一个比萨,以便比萨能从工厂中取得原料
pizza =new CheesePizza(ingredientFactory);
pizza.setName("New York style Cheese Pizza");
}else if(type.equals("veggie")){
pizza =new VeggiePizza(ingredientFactory);
pizza.setName("New York Style Veggie Pizza");
}else if(type.equals("clam")){
pizza =new ClamPizza(ingredientFactory);
pizza.setName("New York Style Clam Pizza");
}
returnpizza;
}
}

我们做了些什么?
引入了新类型的工厂,也就是所谓的抽象工厂,来创建比萨原料家族;
通过抽象工厂所提供的接口,可以创建产品的家族,利用这个接口书写代码,我们的代码将从实际工厂解耦,以便在不同上下文中实现各式各样的工厂,制造出各种不同的产品;如:不同的区域,不同的操作系统,不同的外观及操作;
因为代码从实际的产品中解耦了,所以我们可以替换不同的工厂来取得不同的行为;

订购比萨的流程

首先需要一个纽约比萨店:
PizzaStore nyPizzaStore = new NYPizzaStore();

有了比萨店之后,开始接受订单:
nyPizzaStore.orderPizza("cheese");

orderPizza()方法首先调用createPizza()方法:
Pizzapizza = createPizza("cheese");

当createPizza()方法被调用时,开始设计原料工厂:
Pizza pizza = new CheesePizza(nyIngredientFactory);

接下来需要准备比萨。一旦调用了prepare()方法,工厂将被要求准备原料:

voidprepare(){

dough = factory.createDough();
sauce = factory.createSauce();
cheese = factory.createCheese();
}

最后,得到了准备好的比萨,orderPizza()就会接着烘烤,切片,装盒;

定义抽象工厂模式
抽象工厂允许客户使用抽象的接口来创建一组相关的产品,而不需要知道实际产出的具体产品是什么。这样,客户就从具体的产品中被解耦;

类图:







工厂方法是不是潜伏在抽象工厂里面?
抽象工厂的每个方法实际上看起来都像是工厂方法(如:createDough(),createSource()等)。每个方法都被声明成抽象,而子类的方法覆盖这些方法来创建某些对象;这很像工厂方法;
其实,抽象工厂的方法经常以工厂方法的方式实现,抽象工厂的任务是定义一个负责创建一组产品的接口;这个接口内的每个方法都负责创建一个具体产品,同时我们利用实现抽象工厂的子类来提供这些具体的做法。所以,在抽象工厂中利用工厂方法实现生产方法是相当自然的做法;

比较工厂方法和抽象工厂









 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  java 设计模式