设计模式—Factory Pattern

    xiaoxiao2021-03-25  90

    下面是点披萨系统中的一段代码:

    Pizza orderPizza(){ Pizza pizza = new Pizza(); pizza.prepare(); pizza.bake(); pizza.cut(); pizza.box(); return pizza; } 因为有许多种类型的披萨,所以我们要根据披萨的类型返回合适的披萨:

    Pizza orderPizza(String type){ Pizza pizza; //根据披萨类型返回合适的披萨 if(type.equals("chess")){ pizza = new CheesePizza(); }else if(type.equals("greek")){ pizza = new GreekPizza(); }else if(type.equals("pepperoni")){ pizza = new Pepperoni(); } //披萨的制作过程 pizza.prepare(); pizza.bake(); pizza.cut(); pizza.box(); return pizza; } 因为披萨的种类会不断地变化,所以我们要不断地修改以上代码违背了(classes should open for extention,closed for modification)原则,根据(encapsulate the things that vary)原则,我们可以将不断变化的东西从不变的东西中分离出来,可以看出根据披萨类型返回不同披萨的那部分的代码是不断变化的,而披萨的制作过程那部分代码是不会变化的。以下是分离之后的结果:

    Pizza orderPizza(String type){ Pizza pizza; pizza.prepare(); pizza.bake(); pizza.cut(); pizza.box(); return pizza; } public class SimplePizzaFactory { public Pizza createPizza(String type){ Pizza pizza = null; if(type.equals("cheese")){ pizza = new CheesePizza(); }else if(type.equals("pepperoni")){ pizza = new PepperoniPizza(); }else if(type.equals("clam")){ pizza = new ClamPizza(); }else if(type.equals("veggie")){ pizza = new VeggiePizza(); } return pizza; } } 分离之后,我们可以将orderPizza方法看作客户端代码,利用SimplePizzaFactory类提供的服务,对以上代码进一步完善:

    public class PizzaStore { SimplePizzaFactory factory; public PizzaStore(SimplePizzaFactory factory){ this.factory = factory; } public Pizza orderPizza(String type){ Pizza pizza; pizza = factory.createPizza(type); pizza.prepare(); pizza.bake(); pizza.cut(); pizza.box(); return pizza; } } 以上为Simple Factory idiom,并不是真正的设计模式,以下是它的类图:

    因为披萨店最近办得比较火,店主想多开几家店,每家店的地理位置不一样,生产的披萨种类也不一样,可以这样设计:

    public abstract class PizzaStore { public Pizza orderPizza(String type){ Pizza pizza; pizza = createPizza(type); pizza.prepare(); pizza.bake(); pizza.cut(); pizza.box(); return pizza; } protected abstract Pizza createPizza(String type); } 将以上的类作为父类,可以由子类决定createPizza抽象方法的实现:

    下面是NYPizzaStore类的实现:

    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("pepperoni")){ return new NYStylePepperoniPizza(); }else return null; } } 以下是披萨的实现:

    public abstract class Pizza { String name; String dough; String sauce; ArrayList toppings = new ArrayList(); void prepare(){ System.out.println("Preparing " + name); System.out.println("Tossing dough..."); System.out.println("Adding sauce..."); System.out.println("Adding toppings: "); for(int i = 0;i < toppings.size();i++){ System.out.println(" " + toppings.get(i)); } } void bake(){ System.out.println("Bake for 25 minutes at 350"); } void cut(){ System.out.println("Cutting the pizza into diagonal slices"); } void box(){ System.out.println("Place pizza in official PizzaStore box"); } public String getName(){ return name; } } 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"); } } public class ChicagoStyleCheesePizza extends Pizza { public ChicagoStyleCheesePizza(){ name = "Chicago Style Deep Dish Cheese Pizza"; dough = "Extra Thick Crust Dough"; sauce = "Plum Tomato Sauce"; toppings.add("Shredded Mozzarella Cheese"); } void cut(){ System.out.println("Cutting the pizza into square slices"); } } 测试代码:

    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.getName() + "\n"); pizza = chicagoStore.orderPizza("cheese"); System.out.println("Joel ordered a " + pizza.getName() + "\n"); } } 以上运用的是Factory Method Pattern,实现类图如下:

    Factory Method Pattern 定义:defines an interface for creating an object,but lets subclasses decide which class to instantiate.Factory Method Pattern lets a class defer instantiation to subclasses.类图如下:

    下面介绍Factory Method Pattern 所利用的一条设计准则:Dependency Inversion Principle。这条准则主要讲要依赖抽象,而不要依赖于具体的实现,比如以上的例子如果不用Factory Method Pattern,我们可以这样实现:

    public class DependentPizzaStore { public Pizza createPizza(String style,String type){ Pizza pizza = null; if(style.equals("NY")){ if(type.equals("cheese")){ pizza = new NYStyleCheesePizza(); }else if(type.equals("veggie")){ pizza = new NYStyleVeggiePizza(); }else if(type.equals("clam")){ pizza = new NYStyleClamPizza(); }else if(type.equals("pepperoni")){ pizza = new NYStylePepperoniPizza(); } }else if(style.equals("Chicago")){ if(type.equals("cheese")){ pizza = new ChicagoStyleCheesePizza(); }else if(type.equals("veggie")){ pizza = new ChicagoStyleVeggiePizza(); }else if(type.equals("clam")){ pizza = new ChicagoStyleClamPizza(); }else if(type.equals("pepperoni")){ pizza = new ChicagoStylePepperoniPizza(); } }else{ System.out.println("Error:invalid type of pizza"); return null; } pizza.prepare(); pizza.bake(); pizza.cut(); pizza.box(); return pizza; } } 依赖关系可以用如下图表示:

    从上图我们可以看出PizzaStore依赖于具体的Pizza的实现,Factory Method Pattern改善后的依赖关系可以用如下图表示:

    从上图可以看出,PizzaStore和具体的Pizza的实现都依赖于Pizza这个抽象类。

    由于每个地区人的口味都不一样,所以做pizza所用的材料也不一样,老板决定在每个地区建立工厂专门生产适合本地人口味的材料,下面为材料工厂接口设计:

    public interface PizzaIngredientFactory { public Dough createDough(); public Sauce createSauce(); public Cheese createCheese(); public Veggies[] createVeggies(); public Pepperoni createPepperoni(); public Clams createClam(); } 下面是纽约材料工厂的实现:

    public class NYPizzaIngredientFactory implements 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() { Veggies veggies[] = {new Garlic(),new Onion(),new Mushroom(),newRedPepper()}; return veggies; } @Override public Pepperoni createPepperoni() { return new SlicedPepperoni(); } @Override public Clams createClam() { return new FreshClams(); } } 下面对Pizza抽象类进行完善:

    public abstract class Pizza { String name; Dough dough; Sauce sauce; Veggies veggies[]; Cheese cheese; Pepperoni pepperoni; Clams clam; abstract void prepare(); void bake(){ System.out.println("Bake for 25 minutes at 350"); } void cut(){ System.out.println("Cutting the pizza into diagonal slices"); } void box(){ System.out.println("Place pizza in official PizzaStore box"); } public void setName(String name){ this.name = name; } public String getName(){ return name; } public String toString(){ //code to print pizza here } } Pizza具体类的实现如下:

    public class CheesePizza extends Pizza { PizzaIngredientFactory ingredientFactory; public CheesePizza(PizzaIngredientFactory ingredientFactory){ this.ingredientFactory = ingredientFactory; } @Override void prepare() { System.out.println("Preparing " + name); dough = ingredientFactory.createDough(); sauce = ingredientFactory.createSauce(); cheese = ingredientFactory.createCheese(); } } public class ClamPizza extends Pizza { PizzaIngredientFactory ingredientFactory; public ClamPizza(PizzaIngredientFactory ingredientFactory){ this.ingredientFactory = ingredientFactory; } @Override void prepare() { System.out.println("Preparing " + name); dough = ingredientFactory.createDough(); sauce = ingredientFactory.createSauce(); cheese = ingredientFactory.createCheese(); clam = ingredientFactory.createClam(); } } 下面重新实现 NYPizzaStore类:

    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 Pepperoni(ingredientFactory); pizza.setName("New York Style Pepperoni Pizza"); } return pizza; } } 以上介绍的是一种新的模式:Abstract Factory Pattern(provides an interface for creating families of related or dependent objects without specifying their concrete classes).类图如下所示:

    披萨店的材料工厂实现如下图所示:

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

    最新回复(0)