设计模式之工厂模式(三)

上一次我们已经通过代码,简单的认识了工厂方法模式,具体的思路请移步到设计模式之工厂模式(二),进行查看。这次,让我们通过设计模式的思想,来好好认识下工厂方法模式。

创建者和产品

所有工厂模式都用来封装对象的创建。工厂方法模式(Factory Method Pattern)通过让子类决定该创建的对象是什么,来达到将对象创建的过程封装的目的。让我们来看看这些类图,以了解有哪些组成元素:

另一个观点:平行的类层级

上面已经看到,将一个orderPizza()方法和一个工厂方法联合起来,就可以成为一个框架。除此之外,工厂方法将生产知识封装进各个创建者,这样的做法,也可以被视为是一个框架。

让我们来看看这两个平行的类层级,并认清它们的关系:

定义工厂方法模式

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

工厂方法模式能够封装具体类型的实例化。看下面的类图,抽象的Creator提供了一个创建对象的方法的接口,也称为“工厂方法”。在抽象的Creator中,任何其他实现的方法,都可能使用到这个工厂方法所制造出来的产品,但只有子类真正实现这个工厂方法并创建产品。

对象依赖

假设你从未听过工厂模式,那么按照之前的,如果要开一家纽约和芝加哥的披萨店,并且有各种风味的披萨对象,你是否可以想象这个类所以来的具体披萨对象有几种呢?如果又增加了一种加州风味,又会有依赖多少个对象呢?不妨让你看看:

public lass DependentPizzaStore {
    public Pizza createPizza(String style, String type) {
        Pizza pizza = null;
        if(style.equals("NY")) {
            if(type.equals("cheese")) {
                pizza = new NYStyleCheesePizza();
            } else if(tpye.equals("clam")) {
                pizza = new NYStyleClamPizza();
            } else if(type.equals("pepperoni")) {
                pizza = new NYStylePrpperoniPizza();
            }
        } else if(style.equals("Chicago")) {
            if(type.equals("cheese")) {
                pizza = new ChicagoStyleCheesePizza();
            } else if(tpye.equals("clam")) {
                pizza = new ChicagoStyleClamPizza();
            } else if(type.equals("pepperoni")) {
                pizza = new ChicagoStylePrpperoniPizza();
            }
        } else {
            System.out.println("Error: invalid type of pizza");
            return null;
        }
    }
}

当你直接实例化一个对象时,就是在依赖它的具体类。如果把这个版本的披萨店和它的依赖对象画成一张画,看起来是这样的:

依赖倒置原则

从上面看到了,我们代码里减少对于具体类的依赖是一件好事。事实上,有一个OO设计原则就正式阐明了这一点;这个原则甚至还有一个又响亮又正式的名称:“依赖倒置原则”要依赖抽象,不要依赖具体类

这个原则和“针对接口编程,不针对实现编程”类似,但是这个原则,更强调“抽象”。这个原则说明了:不能让高层组件依赖低层组件,而且,不管高层或低层组件,“两者”都应该依赖于抽象。

所谓“高层”组件, 是是由其他低层组件定义行为的类。例如,PizzaStore是个高层组件,因为他的行为是由披萨定义的;PizzaStore创建所有不同的披萨对象,准备、烘烤、切片、装盒;而披萨本身属于低层组件。PizzaStore依赖这些具体披萨类。

原则的应用

非常依赖披萨店的主要问题在于:它依赖每个披萨类型。因为它是在自己的orderPizza()方法中,实例化这些具体类型的。

如何在orderPizza()方法中,将这些实例化对象的代码独立出来?我们都知道,工厂方法刚好派上用场了。应用了工厂方法之后,类图就改成了下面这个样子:

在应用工厂方法之后,你注意到了没,高层组件(PizzaStore)和低层组件(也就是这些披萨)都依赖了Pizza抽象。想要遵循依赖倒置原则,工厂方法并非是唯一的技巧,但却是最有威力的技巧之一了。

依赖倒置,究竟倒置在哪里?

在依赖倒置原则中的倒置指的是和一般OO设计的思考方式相反。看看上面的图,你会注意到低层组件现在竟然依赖高层的抽象。同样地,高层组件现在也依赖相同的抽象。以前绘制的依赖图都是自上而下的,现在却倒置了,而且高层和低层模块现在都依赖这个抽象。

依赖倒置,还需要倒置你的思考方式。之前如果你需要设计一个披萨店,会从顶端开始,然后往下到具体类。现在就需要倒置你的想法,别从顶端开始,而是从披萨开始,然后想到抽象化一个Pizza类。继而想到必须要靠一个工厂来将这些类取出披萨店,不同的披萨类型都只能依赖一个抽象,同样的披萨店也会依赖这个抽象。

就这样,我们倒置了一个商店依赖具体类的设计,而且也倒置了你的思考方式。但是,也需要避免在OO设计中违反依赖倒置原则:

  1. 变量不可以持有具体类的引用:如果使用new,就会持有具体类的引用。你可以改用工厂来避开这样的做法
  2. 不要让类派生自具体类:如果派生自具体类,你就会依赖具体类。请派生自一个抽象(接口或抽象类)
  3. 不要覆盖基类中已实现的方法:如果覆盖基类已实现的方法,那么你的基类就不是一个真正适合被继承的抽象。基类中已实现的方法,应该由所有的子类共享

所以,这篇我们就在这里结束了。为什么呢,因为在下一篇,我们需要遵循这个设计原则,重新来整理整理我们的披萨店。我们要让披萨店的设计变得更棒:具有弹性的框架,而且遵循设计原则。这篇偏向理论知识了,请各位好好理解理解,看看创建者和产品类,看看依赖倒置原则,我们下篇再见咯。

爱生活,爱学习,爱感悟,爱挨踢

(0)

相关推荐

  • 设计模式之工厂模式(下篇)

    今天我们来讲一讲抽象工厂: 重要涉及原则:要依赖抽象,不要依赖具体. 首先我们需要了解一个设计原则--依赖倒置原则:减少对具体的依赖,所谓的倒置是倒置的                         ...

  • 工厂模式-将对象的创建封装起来

    工厂模式(Factory Design Pattern)可细分为三种,分别是简单工厂,工厂方法和抽象工厂,它们都是为了更好的创建对象. 所谓的"工厂",就是用来将创建对象的代码封装 ...

  • java设计模式2————工厂模式

    java设计模式2————工厂模式

  • 漫谈golang设计模式 简易工厂模式

    目前学习golang的主要需求是为了看懂TiDB的源码,下面我们复习一下简易工厂模式的思想 工厂类型分为三种,创建型模式,结构型模式,行为型模式. 简单工厂 使用场景:考虑一个简单的API设计,一个模 ...

  • 设计模式:工厂模式,解除耦合的利器

    工厂模式是使用频率很高的一种设计模式,在面试中也经常问到,今天我们就来学习它. 为什么要用工厂模式? 解答这个问题前,我们先来了解什么是工厂模式. 工厂模式其实也称创建模式,是用于创建对象的一种方式. ...

  • 设计模式之工厂模式(factory pattern)

    工厂顾名思义就是创建产品,根据产品是具体产品还是具体工厂可分为简单工厂模式和工厂方法模式,根据工厂的抽象程度可分为工厂方法模式和抽象工厂模式.该模式用于封装和管理对象的创建,是一种创建型模式.本文从一 ...

  • 设计模式——抽象工厂模式

    抽象工厂方法_将关联组件组装成产品 ** * 印刷抽象工厂类 * @author maikec * 2019/5/20 */ public abstract class AbstractPrintin ...

  • 设计模式之工厂模式(四)

    上篇我们从理论上了解了什么是工厂方法模式,也知道了创建者类和产品类的主要作用是什么.更重要的是,我们还学到了一个设计原则依赖倒置原则,这个原则能推导出我们为什么会使用工厂模式. 当然啦,上次还留下几个 ...

  • 设计模式-工厂模式

    工厂模式 当我们创建一个对象比较复杂时且客户端不关心于实例对象的创建过程时我们可以用工厂模式 类型: 简单工厂模式 工厂方法模式 抽象工厂模式 简单工厂模式 百度百科 简单工厂模式是属于创建型模式,又 ...

  • PHP设计模式之简单工厂模式

    PHP设计模式之简单工厂模式 先从简单工厂入门,不管是面试还是被他人面试,在问到设计模式的时候,大多数人都会提到工厂模式.毫无疑问,工厂相关的几种模式在设计模式中是最出名的也是应用比较广泛的一种模式. ...