工厂方法(一)

定义

抽象工厂模式(英语:Abstract factory pattern)是一种软件开发设计模式。抽象工厂模式提供了一种方式,可以将一组具有同一主题的单独的工厂封装起来。在正常使用中,客户端程序需要创建抽象工厂的具体实现,然后使用抽象工厂作为接口来创建这一主题的具体对象。客户端程序不需要知道(或关心)它从这些内部的工厂方法中获得对象的具体类型,因为客户端程序仅使用这些对象的通用接口。抽象工厂模式将一组对象的实现细节与他们的一般使用分离开来。

作用

客户端代码不知道任何具体类型,也就没必要引入任何相关的头文件或类定义。客户端代码仅仅处理抽象类型。工厂确实创建了具体类型的对象,但是客户端代码仅使用这些对象的抽象接口来访问它们。
如果要增加一个具体类型,只需要修改客户端代码使用另一个工厂即可,而且这个修改通常只是一个文件中的一行代码。不同的工厂创建不同的具体类型的对象,但是和以前一样返回一个抽象类型的引用(或指针),因此客户端代码的其他部分不需要任何改动。这样比修改客户端代码创建新类型的对象简单多了。如果是后者的话,需要修改代码中每一个创建这种对象的地方(而且需要注意的是,这些地方都知道对象的具体类型,而且需要引入具体类型的头文件或类定义)。如果所有的工厂对象都存储在全局的单例对象中,所有的客户端代码到这个单例中访问需要的工厂,那么,更换工厂就非常简单了,仅仅需要更改这个单例对象即可。

局限性

在添加新的产品对象时,难以扩展抽象工厂来生产新种类的产品,这是因为在抽象工厂角色中规定了所有可能被创建的产品集合,要支持新种类的产品就意味着要对该接口进行扩展,而这将涉及到对抽象工厂角色及其所有子类的修改,显然会带来较大的不便。
开闭原则的倾斜性(增加新的工厂和产品族容易,增加新的产品等级结构麻烦)。

结构


举例
假设我们有两种网页产品接口 Button登录按钮 和 Border对话框 ,每一种产品都支持多种系列,比如 internet 10系列和google 系列。这样每个系列的产品分别是 IntButton, GoogButton, IntBorder, GoogBorder 。为了可以在运行时刻创建一个系列的产品族,我们可以为每个系列的产品族创建一个工厂 IntFactory 和 GoogFactory 。每个工厂都有两个方法 CreateButton 和 CreateBorder 并返回对应的产品,可以将这两个方法抽象成一个接口 AbstractFactory 。这样在运行时刻我们可以选择创建需要的产品系列。

代码实现

抽象材料接口
package lxh;

public interface PizzaIngredientFactory {

public Dough createDough();
public Sauce createSauce();
public Cheese createCheese();
public Veggies[] createVeggies();
public Pepperoni createPepperoni();
public Clams createClam();

}

抽象接口实现
package lxh;

public class NYPizzaIngredientFactory implements PizzaIngredientFactory {

public Dough createDough() {
    return new ThinCrustDough();
}

public Sauce createSauce() {
    return new MarinaraSauce();
}

public Cheese createCheese() {
    return new ReggianoCheese();
}

public Veggies[] createVeggies() {
    Veggies veggies[] = { new Garlic(), new Onion(), new Mushroom(), new RedPepper() };
    return veggies;
}

public Pepperoni createPepperoni() {
    return new SlicedPepperoni();
}

public Clams createClam() {
    return new FreshClams();
}

}

/*

几个材料接口
package factorytest;

public interface Clams {
public String toString();
}
package factorytest;

public interface Dough {
public String toString();
}
package factorytest;

public class Eggplant implements Veggies {

public String toString() {
    return "Eggplant";
}

}
package factorytest;

public class Garlic implements Veggies {

public String toString() {
    return "Garlic";
}

}
商店类和接口
package factorytest;

public class NYPizzaStore extends PizzaStore {

protected Pizza createPizza(String item) {
    Pizza pizza = null;
    PizzaIngredientFactory ingredientFactory =
        new NYPizzaIngredientFactory();

    if (item.equals("cheese")) {

        pizza = new CheesePizza(ingredientFactory);
        pizza.setName("New York Style Cheese Pizza");

    } else if (item.equals("veggie")) {

        pizza = new VeggiePizza(ingredientFactory);
        pizza.setName("New York Style Veggie Pizza");

    } else if (item.equals("clam")) {

        pizza = new ClamPizza(ingredientFactory);
        pizza.setName("New York Style Clam Pizza");

    } else if (item.equals("pepperoni")) {

        pizza = new PepperoniPizza(ingredientFactory);
        pizza.setName("New York Style Pepperoni Pizza");

    }
    return pizza;
}

}

package factorytest;

public class CheesePizza extends Pizza {
PizzaIngredientFactory ingredientFactory;

public CheesePizza(PizzaIngredientFactory ingredientFactory) {
    this.ingredientFactory = ingredientFactory;
}

void prepare() {
    System.out.println("Preparing " + name);
    dough = ingredientFactory.createDough();
    sauce = ingredientFactory.createSauce();
    cheese = ingredientFactory.createCheese();
}

}

package factorytest;

public class PizzaTestDrive {

public static void main(String[] args) {
    PizzaStore nyStore = new NYPizzaStore();
    PizzaStore chicagoStore = new ChicagoPizzaStore();

    Pizza pizza = nyStore.orderPizza("cheese");
    System.out.println("Ethan ordered a " + pizza + "\n");

    pizza = chicagoStore.orderPizza("cheese");
    System.out.println("Joel ordered a " + pizza + "\n");

    pizza = nyStore.orderPizza("clam");
    System.out.println("Ethan ordered a " + pizza + "\n");

    pizza = chicagoStore.orderPizza("clam");
    System.out.println("Joel ordered a " + pizza + "\n");

    pizza = nyStore.orderPizza("pepperoni");
    System.out.println("Ethan ordered a " + pizza + "\n");

    pizza = chicagoStore.orderPizza("pepperoni");
    System.out.println("Joel ordered a " + pizza + "\n");

    pizza = nyStore.orderPizza("veggie");
    System.out.println("Ethan ordered a " + pizza + "\n");

    pizza = chicagoStore.orderPizza("veggie");
    System.out.println("Joel ordered a " + pizza + "\n");
}

}
测试结果:
— Making a New York Style Cheese Pizza —
Preparing New York Style Cheese Pizza
Bake for 25 minutes at 350
Cutting the pizza into diagonal slices
Place pizza in official PizzaStore box
Ethan ordered a —- New York Style Cheese Pizza —-
Thin Crust Dough
Marinara Sauce

— Making a Chicago Style Cheese Pizza —
Preparing Chicago Style Cheese Pizza
Bake for 25 minutes at 350
Cutting the pizza into diagonal slices
Place pizza in official PizzaStore box
Joel ordered a —- Chicago Style Cheese Pizza —-
ThickCrust style extra thick crust dough
Tomato sauce with plum tomatoes

— Making a New York Style Clam Pizza —
Preparing New York Style Clam Pizza
Bake for 25 minutes at 350
Cutting the pizza into diagonal slices
Place pizza in official PizzaStore box
Ethan ordered a —- New York Style Clam Pizza —-
Thin Crust Dough
Marinara Sauce

— Making a Chicago Style Clam Pizza —
Preparing Chicago Style Clam Pizza
Bake for 25 minutes at 350
Cutting the pizza into diagonal slices
Place pizza in official PizzaStore box
Joel ordered a —- Chicago Style Clam Pizza —-
ThickCrust style extra thick crust dough
Tomato sauce with plum tomatoes

— Making a New York Style Pepperoni Pizza —
Preparing New York Style Pepperoni Pizza
Bake for 25 minutes at 350
Cutting the pizza into diagonal slices
Place pizza in official PizzaStore box
Ethan ordered a —- New York Style Pepperoni Pizza —-
Thin Crust Dough
Marinara Sauce

— Making a Chicago Style Pepperoni Pizza —
Preparing Chicago Style Pepperoni Pizza
Bake for 25 minutes at 350
Cutting the pizza into diagonal slices
Place pizza in official PizzaStore box
Joel ordered a —- Chicago Style Pepperoni Pizza —-
ThickCrust style extra thick crust dough
Tomato sauce with plum tomatoes

— Making a New York Style Veggie Pizza —
Preparing New York Style Veggie Pizza
Bake for 25 minutes at 350
Cutting the pizza into diagonal slices
Place pizza in official PizzaStore box
Ethan ordered a —- New York Style Veggie Pizza —-
Thin Crust Dough
Marinara Sauce

— Making a Chicago Style Veggie Pizza —
Preparing Chicago Style Veggie Pizza
Bake for 25 minutes at 350
Cutting the pizza into diagonal slices
Place pizza in official PizzaStore box
Joel ordered a —- Chicago Style Veggie Pizza —-
ThickCrust style extra thick crust dough
Tomato sauce with plum tomatoes

本代码来自《head first设计模式》

总结

通过本个设计模式,对抽象工厂方法有了进一步的了解,在执行时再去工厂取原材料,然后制作产品,节约了前期的一些投入,能够更好的运用内存,但是却是降低了效率,,不过耦合度降低,减小了维护和扩展的难度,当要重新添加额外的要求是,甚至还要重构接口,不过总体来说还是可取的,毕竟依赖了抽象,符合了多用组合少用继承和针对接口编程的原则,这倒是可取之处。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值