《Java编程思想第四版》第 16 章 设计范式-提到观察者模式

在由Gamma,Helm 和 Johnson 编著的《Design Patterns》一书中被定义成一个“里程碑”。那本书列出了解决这个问题的 23 种不同的方法

16.1.2 范式分类
《Design Patterns》一书讨论了 23种不同的范式,并依据三个标准分类(所有标准都涉及那些可能发生变
化的方面)。这三个标准是:
    (1) 创建:对象的创建方式。这通常涉及对象创建细节的隔离,这样便不必依赖具体类型的对象,所以在新
    添一种对象类型时也不必改动代码。
    (2) 结构:设计对象,满足特定的项目限制。这涉及对象与其他对象的连接方式,以保证系统内的改变不会
    影响到这些连接。
    (3) 行为:对程序中特定类型的行动进行操纵的对象。这要求我们将希望采取的操作封装起来,比如解释一
    种语言、实现一个请求、在一个序列中遍历(就象在继承器中那样)或者实现一种算法。本章提供了“观察
    器”(Observer)和“访问器”(Visitor)的范式的例子。
《Design Patterns》为所有这 23种范式都分别使用了一节,随附的还有大量示例,但大多是用 C++编写
的,少数用 Smalltalk 编写(如看过这本书,就知道这实际并不是个大问题,因为很容易即可将基本概念从
两种语言翻译到Java 里)。现在这本书并不打算重复《Design Patterns》介绍的所有范式,因为那是一本
独立的书,大家应该单独阅读。相反,本章只准备给出一些例子,让大家先对范式有个大致的印象,并理解
它们的重要性到底在哪里
16.1.1 单子
或许最简单的设计范式就是“单子”(Singleton),它能提供对象的一个(而且只有一个)实例。单子在
Java 库中得到了应用,但下面这个例子显得更直接一些:
    //: SingletonPattern.java
    // The Singleton design pattern: you can
    // never instantiate more than one.
    589
    package c16;
    // Since this isn't inherited from a Cloneable
    // base class and cloneability isn't added,
    // making it final prevents cloneability from
    // being added in any derived classes:
    final class Singleton {
        private static Singleton s = new Singleton(47);
        private int i;
        private Singleton(int x) { i = x; }
        public static Singleton getHandle() {
        return s;
        }
        public int getValue() { return i; }
        public void setValue(int x) { i = x; }
    }
    public class SingletonPattern {
        public static void main(String[] args) {
            Singleton s = Singleton.getHandle();
            System.out.println(s.getValue());
            Singleton s2 = Singleton.getHandle();
            s2.setValue(9);
            System.out.println(s.getValue());
            try {
            // Can't do this: compile-time error.
            // Singleton s3 = (Singleton)s2.clone();
            } catch(Exception e) {}
        }
    } ///:~
创建单子的关键就是防止客户程序员采用除由我们提供的之外的任何一种方式来创建一个对象。必须将所有
构建器都设为private(私有),而且至少要创建一个构建器以防止编译器帮我们自动同步一个默认构建
器(它会自做聪明地创建成为“友好的”——friendly,而非 private)。
此时应决定如何创建自己的对象。在这儿,我们选择了静态创建的方式。但亦可选择等候客户程序员发出一
个创建请求,然后根据他们的要求动态创建。不管在哪种情况下,对象都应该保存为“私有”属性。我们通
过公用方法提供访问途径。在这里,getHandle()会产生指向 Singleton 的一个句柄。剩下的接口(getValue()和 setValue())属于普通的类接口。
Java 也允许通过克隆(Clone)方式来创建一个对象。在这个例子中,将类设为 final 可禁止克隆的发生
16.2 观察器范式(观察者)
观察器(Observer)范式解决的是一个相当普通的问题:由于某些对象的状态发生了改变,所以一组对象都
需要更新,那么该如何解决?在Smalltalk 的MVC(模型-视图-控制器)的“模型-视图”部分中,或在
几乎等价的“文档-视图结构”中,大家可以看到这个问题。现在我们有一些数据(“文档”)以及多个视
图,假定为一张图(Plot)和一个文本视图。若改变了数据,两个视图必须知道对自己进行更新,而那正是
“观察器”要负责的工作。这是一种十分常见的问题,它的解决方案已包括进标准的 java.util 库中。
    在Java 中,有两种类型的对象用来实现观察器范式。其中,Observable 类用于跟踪那些当发生一个改变时
希望收到通知的所有个体——无论“状态”是否改变。如果有人说“好了,所有人都要检查自己,并可能要
进行更新”,那么Observable 类会执行这个任务——为列表中的每个“人”都调用 notifyObservers()方
法。notifyObservers()方法属于基础类Observable 的一部分。
    在观察器范式中,实际有两个方面可能发生变化:观察对象的数量以及更新的方式。也就是说,观察器范式
允许我们同时修改这两个方面,不会干扰围绕在它周围的其他代码。
    下面这个例子类似于第 14章的ColorBoxes 示例。箱子(Boxes)置于一个屏幕网格中,每个都初始化一种随
机的颜色。此外,每个箱子都“实现”(implement)了“观察器”(Observer)接口,而且随一个
Observable对象进行了注册。若点击一个箱子,其他所有箱子都会收到一个通知,指出一个改变已经发生。
这是由于Observable 对象会自动调用每个Observer 对象的 update()方法。在这个方法内,箱子会检查被点
中的那个箱子是否与自己紧邻。若答案是肯定的,那么也修改自己的颜色,保持与点中那个箱子的协调。

个人理解:一个对象改变了,通知所有已经关联的对象,并做相关的处理。
---待续
posted @ 2017-10-24 11:29  海蓝7  阅读(179)  评论(0编辑  收藏  举报