zoukankan      html  css  js  c++  java
  • 设计模式之工厂模式

    Table of Contents

    1. 前言
    2. 三个面向对象设计原则
    3. 简单工厂模式
    4. 工厂方法模式
    5. 抽象工厂模式
    6. 综合理解
    7. 结语

    前言

    在多次接触设计模式的过程中,工厂模式留给我的印象是最深的,因为,它基本上是各种教程前面必然会出现的一个模式 (¬_¬)

    所以,我觉得还是有必要总结一下和工厂模式有关的内容。

    三个面向对象设计原则

    某种程度上,设计模式的设计依据便是面向对象的设计原则,这里先列出来个人认为有助于工厂模式的理解的三个原则:

    • 开闭原则:类应该对扩展开发,对修改关闭。也就是说,我们应该在尽量避免修改已有代码的情况下扩展增加功能
    • 依赖倒置原则:依赖抽象,不要依赖具体类。也就是说,我们应该避免对具体类的依赖,而要尽量的依赖抽象
    • 单一职责原则:类的职责要单一,不要将太多的职责放在一个类中

    简单工厂模式

    简单工厂模式不是一个设计模式,这是每个教程里面都会有的一句话,这里也不例外。

    简单工厂模式更像是一种编程习惯,其基本理念就是将创建具体类的过程抽取出来,放到某个工厂类的(静态)方法中:

    public class SimplePizzaFactory {
      public static 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;
      }
    }
    

    上面的代码是《Head First 设计模式》一书中的例子,它将创建披萨的过程单独的放在了 createPizza 方法中,使用时只需要传递相应的参数就可以了。

    这样一来,在使用简单工厂的地方,我们就只需要依赖一个简单工厂 SimplePizzaFactory 和一个 Pizza 类型,不需要关心具体的 Pizza 类型(依赖倒置原则)。

    但是简单工厂模式是存在一些问题的:

    1. 每当我们可以创建的具体对象的类型变多了,我们就需要修改简单工厂的代码,这违反了开闭原则
    2. 假如简单工厂中的代码存在错误,那么,所有使用了这个工厂的地方都会存在安全隐患,这违反了单一职责原则

    因此,我们需要改进简单工厂模式,让其遵守面向对象的设计原则。

    注:《Head First 设计模式》给出的源码中,方法 createPizza 并不是静态的,理由是:非静态的方法可以通过继承的方式进行重写。但我个人感觉不是很有必要,就改成静态的了。

    工厂方法模式

    工厂方法模式和简单工厂模式有点像,它在父类中声明用于创建具体对象的 抽象方法, 然后由 子类 来实现抽象方法。

    通过这种方式我们便可以通过增加子类的方式来扩展工厂的功能,而不是去修改已有的代码,其常见的结构为:

    • 抽象工厂:声明了用于创建具体对象的抽象方法
    • 具体工厂:实现了用于创建具体对象的抽象方法
    • 抽象产品:要被创建的具体对象的抽象父类
    • 具体产品:要被创建的具体对象

    类图:

    可以看到,工厂方法的扩展方式是通过增加子类实现的,因此避免了修改已有的代码。同时,每个子类只负责创建一种具体对象,符合了单一职责原则。

    但有些时候,也不能一味的符合单一职责原则,比如,需要创建一组相关的对象的时候。

    抽象工厂模式

    抽象工厂模式和工厂方法模式很接近,主要用于创建一组相关的对象,也就是经常会在一起被创建的对象,其类图如下:

    具体工厂和具体产品之间的依赖关系:

    可以发现,抽象工厂模式和工厂方法模式的差别并不是很大,只不过,一个负责创建一组对象,而另一个只创建某一类型的对象。如果将一组对象变成一个对象,那么抽象工厂模式和工厂方法模式就变得差不多了。

    虽然在抽象工厂模式中单个具体工厂的职责更多,但是,如果将需要经常在一起创建的对象分散到多个工厂中,反而会增加使用者的依赖和整体的复杂的,因此,抽象工厂模式在创建一组相关的对象的时候还是很有用的。

    综合理解

    设计模式的设计依据是面向对象的设计原则,因此,在理解设计模式的时候,应该参考相应的设计原则。

    简单工厂模式虽然简单,但是如果具体对象的类型会经常增加,那么工厂的代码也就会经常修改,频繁的修改就容易出现错误。

    而一旦出现错误,由于简单工厂的职责过重,所有使用简单工厂的地方都会出现问题,因此,出现了工厂方法和抽象工厂。

    无论是工厂方法还是抽象工厂,添加功能的时候都可以通过增加子类的方式完成,避免了对已有代码的修改。而工厂方法中的具体工厂的职责也很单一,这样一来,出现错误时,受影响的范围可以少一点。

    同时,虽然抽象工厂中的具体工厂需要负责创建多个对象,出现错误可能全军覆没,但是,抽象工厂创建的对象本来就是相关的,也就是说,就算分开了,一个地方出错还是会影响整体,因此,将相关的一组对象放在一起创建带来的好处是更多的。

    而且,使用这些工厂的时候,使用者都只需要依赖抽象工厂和抽象产品的类型,不需要依赖具体的类型,符合依赖倒置原则。

    结语

    据说学习设计模式容易陷入一个误区,那就是到处都在用设计模式,使得整体代码变得复杂且难以理解。

    所以说,应该只在有必要的时候使用设计模式,避免因为设计模式的原因让你的代码太过复杂。

  • 相关阅读:
    关于上传的种种(一)
    由SharePoint:ChangeContentType想到的
    关于上传的种种(二)
    关于上传的种种(三)
    SharePoint 2013 Suite Bar
    SharePoint 2013 商城
    自定义列表默认的视图文件
    InfoPath表单与SPD无代码工作流(一)
    列表的展示分页
    无处不在的SharePoint按钮(二)
  • 原文地址:https://www.cnblogs.com/rgbit/p/10922818.html
Copyright © 2011-2022 走看看