• 设计模式之工厂方法模式


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

      举个例子:开Pizza店

      为了满足面向对象村村民对比萨的向往,你决定开一家Pizza店。

      你的代码可能这样子写:

    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("cheese")) {//下面一共有三种比萨
            pizza = new CheesePizza();
        }else if(type.equals("greek")) {
            pizza = new GreekPizza();
        }else if(type.equals("pepperoni")) {
            pizza = new PepperoniPizza();
        }
        
        pizza.prepare();
        pizza.bake();
        pizza.cut();
        pizza.box();
        return pizza;
    }

      但是过了几个月你发现面向对象村的村民希望加入新的口味,于是你又一次修改了代码:

    Pizza orderPizza(String type) {
        Pizza pizza;
        
        if(type.equals("cheese")) {//你有添加了Clam(蛤蜊比萨) Veggie(素食比萨)
            pizza = new CheesePizza();
        }else if(type.equals("greek")) {
            pizza = new GreekPizza();
        }else if(type.equals("pepperoni")) {
            pizza = new PepperoniPizza();
        }else if(type.equals("clam")) {
            pizza = new ClamPizza();
        }else if(type.equals("veggie")) {
            pizza = new VeggiePizza();
        }
        
    }

      但是这样做明显违背了“开放封闭原则”,那么我们不如把创建比萨的代码移到另一个对象中,这个类专门来创建比萨。

      我们称它为简单工厂:

    public class SimplePizzaFactory {
        public Pizza createPizza(String type) {//通过传入的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;
    }

      现在重现开店咯:

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

       简单模式其实也不是一个设计模式,反而比较像是一种编程习惯。但由于经常被使用,所以我们给它一个“OO Pattern荣誉奖”。不要以为简单工厂不是一个“真正的”模式,就忽略它的用法。让我们来看看新的比萨店类图。

      

      由于经营有成,击败了各种竞争者,现在大家希望面向对象的比萨店能够在附近有加盟店。但是由于区域的差异,每家加盟店可能提供的口味不相同,比如说(纽约、芝加哥、加州)。因此为了满足不同区域的消费者的要求,现在需要重新安排我们的Pizza工厂。

      一个想法就是利用SimplePizzaFactory,写出三个不同的工厂,分别为NYPizzaFactory、ChicagoPizzaFactory、CaliforniaPizzaFactory。

    NYPizzaFactory nyFactory = new NYPizzaFactory();
    PizzaStore nyStore = new PizzaStore(nyFactory);
    nyStore.orderPizza("Veggie");
    
    ChicagoPizzaFactory chicagoFactory = new ChicagoPizzaFactory();
    PizzaStore chicagoStore = new PizzaStore(chicagoFactory);
    chicagoStore.orderPizza("Veggie");

      但是问题来了,每个加盟店都开始使用属于自己的一套制作pizza流程,因此我们需要给比萨店构造一个合适的框架:

    public abstract class PizzaStore() {//现在PizzaStore是抽象的
        
        public Pizza orderPizza(String type){
            Pizza pizza;
            
            pizza = createPizza(type);
            
            pizza.prepare();
            pizza.bake();
            pizza.cut();
            pizza.box();
            
            return pizza;
        }
        abstract Pizza createPizza(String type);//“工厂方法”也是抽象的
    }

      我们需要让每一个加盟店自己决定自己的pizza制作流程,依旧是让子类来作出决定:

      

      

    Public Pizza createPizza(type) {//纽约的pizza店创造属于自己的独特口味
        if(type.equals("cheese")) {
            pizza = new NYStyleCheesePizza();
        }else if(type.equals("greek")) {
            pizza = new NYStyleGreekPizza();
        }else if(type.equals("pepperoni")) {
            pizza = new NYStylePepperoniPizza();
        }else if(type.equals("clam")) {
            pizza = new NYStyleClamPizza();
        }else if(type.equals("veggie")) {
            pizza = new NYStyleVeggiePizza();
        }
    }
    Public Pizza createPizza(type) {//芝加哥的pizza店创造属于自己的独特口味
        if(type.equals("cheese")) {
            pizza = new ChicagoStyleCheesePizza();
        }else if(type.equals("greek")) {
            pizza = new ChicagoStyleGreekPizza();
        }else if(type.equals("pepperoni")) {
            pizza = new ChicagoStylePepperoniPizza();
        }else if(type.equals("clam")) {
            pizza = new ChicagoStyleClamPizza();
        }else if(type.equals("veggie")) {
            pizza = new ChicagoStyleVeggiePizza();
        }
    }

      现在让我们开始加盟店:

    public class NYPizzaStore extends PizzaStore {//纽约的pizza点
        Pizza createPizza(String item) {
            if(item.equals("cheese")){
                return new NYStyleCheesePizza();
            }else if(item.equals("veggie")){
                return new NYStyleVeggiePizza();
            }else if(item.equals("clas")){
                return new NYStyleClamPizza();
            }else if(item.equals("pepperoni")){
                return new NYStylePepperoniPizza();
            }else return null;
        }
    }

       

    public class ChicagoPizzaStore extends PizzaStore {//芝加哥的pizza店
        Pizza createPizza(String item) {
            if(item.equals("cheese")){
                return new ChicagoStyleCheesePizza();
            }else if(item.equals("veggie")){
                return new ChicagoStyleVeggiePizza();
            }else if(item.equals("clas")){
                return new ChicagoStyleClamPizza();
            }else if(item.equals("pepperoni")){
                return new ChicagoStylePepperoniPizza();
            }else return null;
        }
    }

      声明一个工厂方法:

    public abstract class PizzaStore() {
        
        public Pizza orderPizza(String type){
            Pizza pizza;
            
            pizza = createPizza(type);
            
            pizza.prepare();
            pizza.bake();
            pizza.cut();
            pizza.box();
            
            return pizza;
        }
        abstract Pizza createPizza(String type);
    
            //其他方法      
    }

      我们忽略了很重要的一件事:比萨本身!

    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 baek(){
            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 offical 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 and 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();//纽约pizza店
            PizzaStore chicagoStore = new ChicagoPizzaStore();//芝加哥pizza店
            
            Pizza pizza = nyStore.orderPizza("cheese");
            System.out.println("I ordered a "+pizza.getName()+"
    ");
            
            pizza = new chicagoStore.orderPizza("cheese");
            System.out.println("You ordered a "+pizza.getName()+"
    ");
        }
    }

     

      上面便是我们的工厂模式用途之一;现在我们正式介绍我们强大的工厂模式:

      

  • 相关阅读:
    ORA01102 cannot mount database in EXCLUSIVE mode
    VC中cl.exe命令参数详解
    (转)LIB和DLL的区别与使用
    (转)DOS循环:bat/批处理for命令详解之一 (史上虽详尽的总结和说明~~)
    常用Win IDE库函数
    (转)Windows下多媒体计时器使用举例
    (转)C++进阶必读书籍
    (转)sql 行专列 列转行 普通行列转换
    VLFeat(1)——SIFT图像特征提取(VC++实现)
    (转)SIFT算法研究
  • 原文地址:https://www.cnblogs.com/zpfbuaa/p/5503538.html
Copyright © 2020-2023  润新知