设计模式学习——工厂模式

来源:互联网 发布:族谱软件哪个好 编辑:程序博客网 时间:2024/05/17 09:01

1.      工厂方法模式——定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个。工厂方法让类把实例化推迟到子类。


(这个图就别看了,本来不想要,画了半天觉得可惜不想扔掉~)


好,老规矩,源码之下,了无秘密。

假设你开了一家比萨店,并且在不同的地方有分店,销售不同风味的比萨

public abstract class PizzaStore { abstract Pizza createPizza(String item); public Pizza orderPizza(String type) {Pizza pizza = createPizza(type);System.out.println("--- Making a " + pizza.getName() + " ---");pizza.prepare();pizza.bake();pizza.cut();pizza.box();return pizza;}

createPizza就是工厂。说白了我们就是要把制作不同的比萨的责任放到createPizza这个工厂中,工厂负责将客户从具体的类型中解耦。关键的就那么一句

Pizza pizza = createPizza(type);


接下来就是把制作比萨的任务放到子类中去

public class NYPizzaStore extends PizzaStore {Pizza createPizza(String item) {if (item.equals("cheese")) {return new NYStyleCheesePizza();} else if (item.equals("veggie")) {return new NYStyleVeggiePizza();} else if (item.equals("clam")) {return new NYStyleClamPizza();} else if (item.equals("pepperoni")) {return new NYStylePepperoniPizza();} else return null;}

NYStyleCheesePizza和NY其他种类的比萨怎么制作出来的我就不管了,只需要知道他们都扩展自Pizza类

在来看看定义:定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个。工厂方法让类把实例化推迟到子类。

创建对象的接口:

abstract Pizza createPizza

子类NYPizzaStore决定实例化哪一个


怎么样,是不是很符合定义呀。


下面就是具体的一个实例化

public class NYStyleCheesePizza extends Pizza {public NYStyleCheesePizza() { name = "NY Style Sauce and Cheese Pizza";dough = "Thin Crust Dough";sauce = "Marinara Sauce"; toppings.add("Grated Reggiano Cheese");}}

重点是:这样做到底有什么好处?

好处就是:把创建对象的代码集中在一个对象或者方法中,可以避免代码中的重复,并且方便以后的维护。这也意味着客户在实例化对象时,只会依赖于接口,而不是具体类。



好吧,看看完整的类图试着实现一把吧




2.抽象工厂

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

抽象工厂的任务是定义一个负责创建一组产品的接口。这个接口内的每一个方法都负责创建一个一个具体的产品,同时利用实现抽象工厂的子类来提供具体的做法。

源码之下,了无秘密:


首先定义一个接口,这个接口负责创建所有的原料:

public interface PizzaIngredientFactory { 
 //下面的每一个原料也都是接口类型public Dough createDough(); public Sauce createSauce();public Cheese createCheese();public Pepperoni createPepperoni();public Clams createClam(); }


,然后各个地方实现这个原料工厂

public class NYPizzaIngredientFactory implements PizzaIngredientFactory { public Dough createDough() {return 纽约比萨店需要的;} public Sauce createSauce() {return 纽约比萨店需要的Sauce;} ......}


来看看我们的比萨店怎么使用,和之前工厂方法中的createpizza比较下,现在已经不需要设计不同的类来处理不同风味的比萨了,让原料工厂来处理即可

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;}}


每个比萨店都会用到工厂提供的原料,纽约的比萨店就用纽约工厂提供的原料
PizzaIngredientFactory ingredientFactory = new NYPizzaIngredientFactory();

对于每一种比萨实例化一个新比萨,把原料工厂传递给每一个比萨,以便比萨能从工厂中抽取需要的原料

pizza = new CheesePizza(ingredientFactory);



public class CheesePizza extends Pizza {PizzaIngredientFactory ingredientFactory; public CheesePizza(PizzaIngredientFactory ingredientFactory) {this.ingredientFactory = ingredientFactory;} void prepare() {//准备原料}}


工厂方法与工厂模式比较:

所有的工厂都是用来封装对象的创建。

工厂方法使用继承,把对象的创建委托给子类,子类实现工厂方法来创建对象

抽象工厂使用对象组合,对象的创建被实现在工厂接口所暴力出来的方法中

所有工厂模式通过减少应用程序具体类之间的依赖促进松耦合。

抽象工厂提供一个用来创建家族的抽象类型,这个类型的子类定义了产品被产生的方法。要想使用这个工厂,必须先实例化它,然后将它传入一些针对抽象类型所写的代码中。










0 0
原创粉丝点击