zoukankan      html  css  js  c++  java
  • 《Head First 设计模式》 读书笔记04 工厂模式(一)

    《Head First 设计模式》读书笔记04 工厂模式

     

    问题的提出

      如何将实例化具体类的代码从应用中抽离,或者封装起来,使它们不会干扰应用的其他部分?

      假设你有一个披萨店,那么代码最初可能是这样:

    最初的披萨店代码
    Pizza oderPizza(String type)
    {
        //Pizza是一个接口
        Pizza pizza;
    
        //随着时间改变的地方
        if(type.equals("cheese"))
        {
            pizza = new CheesePizza();
        }
        else if(type.equals("greel"))
        {
            pizza = new GreekPizza();
        }
        else if(type.equals("pepperoni"))
        {
            pizza = new PepperoniPizza();
        }
    
        //不改变的地方
        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("greel"))
            {
                pizza = new GreekPizza();
            }
            else if(type.equals("pepperoni"))
            {
                pizza = new PepperoniPizza();
            }
            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;
        }
    }

     

       类图:

      

     

     

    重要提醒

      在设计模式中,所谓的“实现一个接口”并不一定表示“写一个类,并用implements关键字来实现某个Java接口”。

      “实现一个接口”泛指“实现某个超类型(可以是类或接口)的某个方法”。

     

    有更多不同地区的加盟披萨店

      一种做法:设计出不同的工厂类

      每个地区用自己的工厂类加工披萨,每个地区也有自己的PizzaStore对象,建立对象时将自己的工厂类对象加入。框架不变。

      想要更多的质量控制

      把createPizza()方法放回到PizzaStore中,设置成抽象方法,然后为每个区域风味创建一个PizzaStore的子类。

      这种方法实现起来代码如下:

     

    工厂方法实现披萨店
    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);
    }

    工厂方法

      上面的例子中,实例化披萨的责任被移到一个方法中,这个方法就如同是一个“工厂”。

      工厂方法用来处理对象的创建,并将这样的行为封装在子类中。

      这样,客户程序中关于超类的代码就和子类对象创建代码解耦了。

      abstract Product factoryMethod(String type);

      工厂方法是抽象的,所以依赖子类来处理对象的创建。

      工厂方法必须返回一个产品。超类中定义的方法,通常使用到工厂方法的返回值。

      工厂方法将客户(也就是超类中的代码,如orderPizza())和实际创建具体产品的代码分隔开来。

      工厂方法可能需要参数(也可能不需要)来指定所需要的产品。

     

    工厂方法模式

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

      工厂方法让类把实例化推迟到子类。

      见类图:

      

     

      ConcreteCreator可以有一个或多个,选择了子类,则选择了实际创建的工厂方法。

      这个具体的工厂可以只创建一种对象,也可以根据传入的参数创建不同的对象。

      工厂方法和Creator并不总是抽象的,也可以提供默认的具体实现。

     

    设计原则——依赖倒置原则Dependency Inversion Principle

      要依赖抽象,不要依赖具体类。

      不能让高层组件依赖底层组件。

      前面所说的做法就体现了这个设计原则,倒置依赖后:让高层组件PizzaStore依赖于一个抽象的Pizza,而各种具体的披萨也依赖于这个抽象的Pizza。

      几个指导方针帮助你遵循此原则:

      变量不可以持有具体类的引用。

      如果使用new,就会持有具体类的引用,可以使用工厂来避开这样的做法。

      不要让类派生自具体类。

      如果派生自具体类,就会依赖具体类。要派生自抽象类或接口。

      不要覆盖基类中已实现的方法。

      如果覆盖基类已实现的方法,那么基类不是一个真正适合被继承的抽象。基类中已实现的方法应该由所有的子类共享。

      这些原则应尽量达到,而不是随时都要遵循,有时候有足够的理由,就可以违反这些方针。(Orz)。

  • 相关阅读:
    IO 输入输出流
    「做自己」​​​​​​​写出我心(八十)
    「关于爱情,关于婚姻」​​​​​​​写出我心(七十九)
    「如何冥想?」​​​​​​​写出我心(七十八)
    「对这个世界温柔一点」​​​​​​写出我心(七十七)
    「7tips-克服焦虑」​​​​​写出我心(七十六)
    「十步学习法」​​​​写出我心(七十五)
    「成功的人生是台阶式向上」​​​写出我心(七十四)
    「世界是自己的」​​写出我心(七十三)
    「​八点工作中的小建议」​写出我心(七十二)
  • 原文地址:https://www.cnblogs.com/mengdd/p/2844868.html
Copyright © 2011-2022 走看看