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

xiaoxiao2021-02-27  214

目录:注意,此模式涉及的示例,来自于工厂模式笔记:工厂模式

抽象工厂模式:提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类;

知识点的梳理:

抽象工厂使用对象组合:对象的创建被实现在工厂接口所暴露出来的方法中; 抽象工厂创建相关的对象家族,而不需要依赖它们的具体类;

  

再回到比萨店。。。 现在我们需要确保每家加盟店使用的原料都是高质量的。现在打算建造一家生产原料的工厂,并将原料运送到各家加盟店。而对于纽约和芝加哥需要准备两组不同的原料; 所谓的原料只是大家都使用相同的产品,但是各个地区的制作方式却又各不相同; 建造原料工厂 注意,示例中出现的所有类,如果没有给出具体代码,就定义一个空实现即可;现在,我们要建造一个工厂来生产原料,这个工厂将负责创建各个加盟店所需要的各种原料。但不关心各个加盟店如何使用这些原料;

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()等)。每个方法都被声明成抽象,而子类的方法覆盖这些方法来创建某些对象;这很像工厂方法;其实,抽象工厂的方法经常以工厂方法的方式实现,抽象工厂的任务是定义一个负责创建一组产品的接口;这个接口内的每个方法都负责创建一个具体产品,同时我们利用实现抽象工厂的子类来提供这些具体的做法。所以,在抽象工厂中利用工厂方法实现生产方法是相当自然的做法; 比较工厂方法和抽象工厂

 

转载请注明原文地址: https://www.6miu.com/read-12847.html

最新回复(0)