设计模式--抽象工厂模式(八)
2017-07-10 09:16
253 查看
目录:注意,此模式涉及的示例,来自于工厂模式笔记:工厂模式
抽象工厂模式:提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类;
知识点的梳理:
抽象工厂使用对象组合:对象的创建被实现在工厂接口所暴露出来的方法中;
抽象工厂创建相关的对象家族,而不需要依赖它们的具体类;
再回到比萨店。。。
现在我们需要确保每家加盟店使用的原料都是高质量的。现在打算建造一家生产原料的工厂,并将原料运送到各家加盟店。而对于纽约和芝加哥需要准备两组不同的原料;
所谓的原料只是大家都使用相同的产品,但是各个地区的制作方式却又各不相同;
建造原料工厂
注意,示例中出现的所有类,如果没有给出具体代码,就定义一个空实现即可;
现在,我们要建造一个工厂来生产原料,这个工厂将负责创建各个加盟店所需要的各种原料。但不关心各个加盟店如何使用这些原料;
要做的事情是:
为每个区域建造一个工厂。需要创建一个继承自PizzaIngredientFactory的子类来实现每一个创建方法;
实现一组原料类供工厂使用,例如ReggianoCheese,RedPeppers,ThickCrust-Dough。这些类可以在合适的区域间共享;
然后仍然需要将这一切组织起来,将新的原料工厂整合进旧的PizzaStore代码中;
创建纽约原来工厂
重做比萨
生产原来的工厂已经创建完毕,现在只需要重做比萨,好让它们只使用工厂生产出来的原料。先从抽象的Pizza类开始:
继续重做比萨
现在已经有了一个抽象比萨,可以开始创建纽约和芝加哥风味的比萨了。此后,加盟店必需直接从工厂取得原料;
然后是蛤蜊比萨
再回到比萨店
我们做了些什么?
引入了新类型的工厂,也就是所谓的抽象工厂,来创建比萨原料家族;
通过抽象工厂所提供的接口,可以创建产品的家族,利用这个接口书写代码,我们的代码将从实际工厂解耦,以便在不同上下文中实现各式各样的工厂,制造出各种不同的产品;如:不同的区域,不同的操作系统,不同的外观及操作;
因为代码从实际的产品中解耦了,所以我们可以替换不同的工厂来取得不同的行为;
订购比萨的流程
首先需要一个纽约比萨店:
PizzaStore nyPizzaStore = new NYPizzaStore();
有了比萨店之后,开始接受订单:
nyPizzaStore.orderPizza("cheese");
orderPizza()方法首先调用createPizza()方法:
Pizzapizza = createPizza("cheese");
当createPizza()方法被调用时,开始设计原料工厂:
Pizza pizza = new CheesePizza(nyIngredientFactory);
接下来需要准备比萨。一旦调用了prepare()方法,工厂将被要求准备原料:
最后,得到了准备好的比萨,orderPizza()就会接着烘烤,切片,装盒;
定义抽象工厂模式
抽象工厂允许客户使用抽象的接口来创建一组相关的产品,而不需要知道实际产出的具体产品是什么。这样,客户就从具体的产品中被解耦;
类图:
工厂方法是不是潜伏在抽象工厂里面?
抽象工厂的每个方法实际上看起来都像是工厂方法(如:createDough(),createSource()等)。每个方法都被声明成抽象,而子类的方法覆盖这些方法来创建某些对象;这很像工厂方法;
其实,抽象工厂的方法经常以工厂方法的方式实现,抽象工厂的任务是定义一个负责创建一组产品的接口;这个接口内的每个方法都负责创建一个具体产品,同时我们利用实现抽象工厂的子类来提供这些具体的做法。所以,在抽象工厂中利用工厂方法实现生产方法是相当自然的做法;
比较工厂方法和抽象工厂
抽象工厂模式:提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类;
知识点的梳理:
抽象工厂使用对象组合:对象的创建被实现在工厂接口所暴露出来的方法中;
抽象工厂创建相关的对象家族,而不需要依赖它们的具体类;
再回到比萨店。。。
现在我们需要确保每家加盟店使用的原料都是高质量的。现在打算建造一家生产原料的工厂,并将原料运送到各家加盟店。而对于纽约和芝加哥需要准备两组不同的原料;
所谓的原料只是大家都使用相同的产品,但是各个地区的制作方式却又各不相同;
建造原料工厂
注意,示例中出现的所有类,如果没有给出具体代码,就定义一个空实现即可;
现在,我们要建造一个工厂来生产原料,这个工厂将负责创建各个加盟店所需要的各种原料。但不关心各个加盟店如何使用这些原料;
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(); } |
定义抽象工厂模式
抽象工厂允许客户使用抽象的接口来创建一组相关的产品,而不需要知道实际产出的具体产品是什么。这样,客户就从具体的产品中被解耦;
类图:
工厂方法是不是潜伏在抽象工厂里面?
抽象工厂的每个方法实际上看起来都像是工厂方法(如:createDough(),createSource()等)。每个方法都被声明成抽象,而子类的方法覆盖这些方法来创建某些对象;这很像工厂方法;
其实,抽象工厂的方法经常以工厂方法的方式实现,抽象工厂的任务是定义一个负责创建一组产品的接口;这个接口内的每个方法都负责创建一个具体产品,同时我们利用实现抽象工厂的子类来提供这些具体的做法。所以,在抽象工厂中利用工厂方法实现生产方法是相当自然的做法;
比较工厂方法和抽象工厂
相关文章推荐
- 设计模式C#描述——抽象工厂模式
- .NET设计模式-抽象工厂模式(Abstract Factory)
- 设计模式C#描述——抽象工厂模式
- 乐在其中设计模式(C#) - 抽象工厂模式(Abstract Factory Pattern)
- 设计模式——创建型模式之 Abstract Factory抽象工厂模式
- [导入]C#面向对象设计模式纵横谈(3):Abstract Factory 抽象工厂模式(创建型模式)
- 设计模式C#描述——抽象工厂模式
- Java设计模式圣经连载(03)-抽象工厂模式
- 乐在其中设计模式(C#) - 抽象工厂模式(Abstract Factory Pattern)
- 我的设计模式之旅(3)――抽象工厂模式AbstractFactory
- 设计模式实践(抽象工厂模式应用)—通信录的优化过程
- 设计模式之抽象工厂模式
- AspectJ实现设计模式(四)——抽象工厂模式
- .NET设计模式:抽象工厂模式(Abstract Factory)
- [导入]C#面向对象设计模式纵横谈(4):Abstract Factory 抽象工厂模式(创建型模式)
- 设计模式笔记-抽象工厂模式
- .Net设计模式之抽象工厂模式(Abstract Factory)
- .NET设计模式(3):抽象工厂模式(Abstract Factory)(转)
- 乐在其中设计模式(C#) - 抽象工厂模式(Abstract Factory Pattern)
- 设计模式(3)-抽象工厂模式(Abstract Factory)