设计模式读书笔记(三)

"Head First 设计模式第四章"

Posted by jhljx on January 29, 2018

目录

1. 工厂模式

工厂模式

在设计模式中,所谓的“实现一个接口”并不一定表示“写一个类,并利用implements关键字来实现某个Java接口”。“实现一个接口”泛指“实现某个超类型(可以是类或接口)的某个方法”。

工厂方法用来处理对象的创建,并将这样的行为封装在子类中。这样,客户程序中关于超类的代码就和子类对象创建代码解耦了。

工厂方法模式:

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

工厂方法模式能够封装具体类型的实例化。就算只有一个ConcreteCreator,工厂模式也可以帮助我们将产品的“实现”从“使用”中解耦。

工厂方法让子类决定要实例化的类是哪一个。这里的“决定”是只在编写创建者类时,不需要知道实际创建的产品是哪一个。选择了使用哪个子类,自然就决定了实际创建的产品是什么。

工厂模式的好处:

将创建对象的代码集中在一个对象(简单工厂)或方法(工厂方法)中,可以避免代码中的重复,并且更方便以后的维护。这也意味着客户在实例化对象时,只会依赖于接口,而不是具体类。我在学习中发现,这可以帮助我针对接口编程,而不针对实现编程。这让代码更具有弹性,可以应对未来的扩展。

依赖倒置原则(Dependency Inversion Principle)

设计原则
要依赖抽象,不要依赖具体类

该原则说明了:不能让高层组件依赖低层组件,而且不管高层或低层组件,“两者”都应该依赖于抽象。

这里“倒置”的意思从PizzaStore这个高层组件和具体的Pizza这些低层组件都会共同依赖Pizza这个抽象可以看出。

几个指导方针

下面几个指导方针可以避免在OO设计中违反依赖倒置原则:

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

如果每个工厂实例内部有某一种通用的“机制”需要实现,就可以把这个例子改写成抽象类。

抽象工厂模式

通过抽象工厂所提供的接口,可以创建产品的家族,利用这个接口书写代码,我们的代码将从实际工厂解耦,以便在不同上下文中实现各式各样的工厂,制造出各种不同的区域。

抽象工厂模式定义:

抽象工厂模式提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类。

抽象工厂定义了一个接口,所有的具体工厂都必须实现此接口,这个接口包含一组方法用来生产产品。

抽象工厂中的每个方法看起来都像是工厂方法。抽象工厂的方法经常以工厂方法的方式实现,抽象工厂的任务是定义一个负责创建一组产品的接口。这个接口内的每个方法都负责创建一个具体产品,同时我们利用实现抽象工厂的子类来提供这些具体的做法。所以在抽象工厂中利用工厂方法实现生产方法是相当自然的做法。

工厂方法和抽象工厂的区别

  • 工厂方法模式——定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个。工厂方法让类把实例化推迟到子类。
  • 抽象工厂模式——提供了一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类。

工厂方法使用的是继承来创建对象,抽象工厂使用对象的组合来创建对象。

工厂方法模式是通过子类来创建对象,负责将客户从具体类型中解耦。

抽象工厂方法提供一个用来创建一个产品家族的抽象类型,这个类型的子类定义了产品被产生的方法。要想使用这个工厂,必须实例化它,然后将它传入一些针对抽象类型所写的代码中。此外,它的一个优点是可以把一群相关的产品集合起来。但是如果接口的方法需要改变就必须改变接口,而改变接口就意味着必须深入改变每个子类的接口。

工厂方法可以把客户代码从需要实例化的具体类中解耦。

OO 原则

  • 多用组合,少用继承
  • 针对接口编程,不针对实现编程
  • 为交互对象之间的松耦合设计而努力
  • 类应对扩展开放,对修改关闭
  • 依赖抽象,不要依赖具体类