友情提示:如果本网页打开太慢或显示不完整,请尝试鼠标右键“刷新”本网页!阅读过程发现任何错误请告诉我们,谢谢!! 报告错误
一世书城 返回本书目录 我的书架 我的书签 TXT全本下载 进入书吧 加入书签

Java编程思想第4版[中文版](PDF格式)-第190章

按键盘上方向键 ← 或 → 可快速上下翻页,按键盘上的 Enter 键可回到本书目录页,按键盘上方向键 ↑ 可回到本页顶部!
————未阅读完?加入书签已便下次继续阅读!




Java 库中得到了应用,但下面这个例子显得更直接一些:  

  

//: SingletonPattern。java  

// The Singleton design pattern: you can  

// never instantiate more than one。  



                                                                  588 


…………………………………………………………Page 590……………………………………………………………

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: pile…time error。  

      // Singleton s3 = (Singleton)s2。clone();  

    } catch(Exception e) {}  

  }  

} ///:~  

  

创建单子的关键就是防止客户程序员采用除由我们提供的之外的任何一种方式来创建一个对象。必须将所有 

构建器都设为private (私有),而且至少要创建一个构建器,以防止编译器帮我们自动同步一个默认构建 

器(它会自做聪明地创建成为“友好的”——friendly,而非 private)。  

此时应决定如何创建自己的对象。在这儿,我们选择了静态创建的方式。但亦可选择等候客户程序员发出一 

个创建请求,然后根据他们的要求动态创建。不管在哪种情况下,对象都应该保存为“私有”属性。我们通 

过公用方法提供访问途径。在这里,getHandle()会产生指向 Singleton 的一个句柄。剩下的接口 

 (getValue()和 setValue())属于普通的类接口。  

Java 也允许通过克隆(Clone)方式来创建一个对象。在这个例子中,将类设为 final 可禁止克隆的发生。 

由于Singleton 是从Object 直接继承的,所以 clone()方法会保持 protected (受保护)属性,不能够使用 

它(强行使用会造成编译期错误)。然而,假如我们是从一个类结构中继承,那个结构已经过载了clone() 

方法,使其具有public 属性,并实现了Cloneable ,那么为了禁止克隆,需要过载clone(),并掷出一个 

CloneNotSupportedException (不支持克隆违例),就象第12章介绍的那样。亦可过载 clone(),并简单地 

返回 this。那样做会造成一定的混淆,因为客户程序员可能错误地认为对象尚未克隆,仍然操纵的是原来的 

那个。  

注意我们并不限于只能创建一个对象。亦可利用该技术创建一个有限的对象池。但在那种情况下,可能需要 

解决池内对象的共享问题。如果不幸真的遇到这个问题,可以自己设计一套方案,实现共享对象的登记与撤 

消登记。  



16。1。2 范式分类  



 《Design Patterns》一书讨论了23 种不同的范式,并依据三个标准分类(所有标准都涉及那些可能发生变 

化的方面)。这三个标准是:  



                                                                                        589 


…………………………………………………………Page 591……………………………………………………………

(1) 创建:对象的创建方式。这通常涉及对象创建细节的隔离,这样便不必依赖具体类型的对象,所以在新 

添一种对象类型时也不必改动代码。  

(2) 结构:设计对象,满足特定的项目限制。这涉及对象与其他对象的连接方式,以保证系统内的改变不会 

影响到这些连接。  

(3) 行为:对程序中特定类型的行动进行操纵的对象。这要求我们将希望采取的操作封装起来,比如解释一 

种语言、实现一个请求、在一个序列中遍历(就象在继承器中那样)或者实现一种算法。本章提供了“观察 

器”(Observer)和“访问器”(Visitor)的范式的例子。  

  

 《Design Patterns》为所有这 23 种范式都分别使用了一节,随附的还有大量示例,但大多是用 C++编写 

的,少数用 Smalltalk 编写(如看过这本书,就知道这实际并不是个大问题,因为很容易即可将基本概念从 

两种语言翻译到Java 里)。现在这本书并不打算重复《Design Patterns》介绍的所有范式,因为那是一本 

独立的书,大家应该单独阅读。相反,本章只准备给出一些例子,让大家先对范式有个大致的印象,并理解 

它们的重要性到底在哪里。  



16。2 观察器范式  



观察器(Observer )范式解决的是一个相当普通的问题:由于某些对象的状态发生了改变,所以一组对象都 

需要更新,那么该如何解决?在Smalltalk 的MVC (模型-视图-控制器)的“模型-视图”部分中,或在 

几乎等价的“文档-视图结构”中,大家可以看到这个问题。现在我们有一些数据(“文档”)以及多个视 

图,假定为一张图(Plot )和一个文本视图。若改变了数据,两个视图必须知道对自己进行更新,而那正是 

 “观察器”要负责的工作。这是一种十分常见的问题,它的解决方案已包括进标准的java。util 库中。  

在Java 中,有两种类型的对象用来实现观察器范式。其中,Observable 类用于跟踪那些当发生一个改变时 

希望收到通知的所有个体——无论“状态”是否改变。如果有人说“好了,所有人都要检查自己,并可能要 

进行更新”,那么 Observable 类会执行这个任务——为列表中的每个“人”都调用 notifyObservers()方 

法。notifyObservers()方法属于基础类Observable 的一部分。  

在观察器范式中,实际有两个方面可能发生变化:观察对象的数量以及更新的方式。也就是说,观察器范式 

允许我们同时修改这两个方面,不会干扰围绕在它周围的其他代码。  

下面这个例子类似于第 14章的ColorBoxes 示例。箱子(Boxes)置于一个屏幕网格中,每个都初始化一种随 

机的颜色。此外,每个箱子都“实现”(implement)了“观察器”(Observer )接口,而且随一个 

Observable 对象进行了注册。若点击一个箱子,其他所有箱子都会收到一个通知,指出一个改变已经发生。 

这是由于Observable 对象会自动调用每个Observer 对象的 update()方法。在这个方法内,箱子会检查被点 

中的那个箱子是否与自己紧邻。若答案是肯定的,那么也修改自己的颜色,保持与点中那个箱子的协调。  

  

//: BoxObserver。java  

// Demonstration of Observer pattern using  

// Java's built…in observer classes。  

import java。awt。*;  

import java。awt。event。*;  

import java。util。*;  

  

// You must inherit a new type of Observable:  

class BoxObservable extends Observable {  

  public void notifyObservers(Object b) {  

    // Otherwise it won't propagate changes:  

    setChanged();  

    super。notifyObservers(b);  

  }  

}  

  

public class BoxObserver extends Frame {  

  Observable notifier = new BoxObservable ();  

  public BoxObserver(int grid) {  

    setTitle(〃Demonstrates Observer pattern〃);  



                                                                                 590 


…………………………………………………………Page 592……………………………………………………………

    setLayout(new GridLayout(grid; grid));  

    for(int x = 0; x 《 grid; x++)  

      for(int y = 0; y 《 grid; y++)  

        add(new OCBox(x; y; notifier));  

  }     

  public static void main(String'' args) {  

    int grid = 8;  

    if(args。length 》 0)  

      grid = Integer。parseInt(args'0');  

    Frame f = new BoxObserver(grid);  

    f。setSize(500; 400);  

    f。setVisible(true);  

    f。addWindowListener(  

      new WindowAdapter() {  

        public void windowClosing(WindowEvent e) {  

          System。exit(0);  

        }  

      });  

  }  

}  

  

class OCBox extends Canvas implements Observer {  

  Observable notifier;  

  int x; y; // Locations in grid  

  Color cColor = newColor();  

  static final Color'' colors = {   

    Color。black; Color。blue; Color。cyan;   

    Color。darkGray; Color。gray; Color。green;  

    Color。lightGray; Color。magenta;   

    Color。orange; Color。pink; Color。red;   

    Color。white; Color。yellow   

  };  

  static final Color newColor() {  

    return colors'  

      (int)(Math。random() * colors。length)  

    ';  

  }  

  OCBox(int x; int y; Observable notifier) {  

    this。x = x;  

    this。y = y;  

    notifier。addObserver(this);  

    this。notifier = notifier;  

    addMouseListener(new ML());  

  }  

  public void paint(Graphics  g) {  

    g。setColor(cColor);  

    Dimension s = getSize();  

    g。fillRect(0; 0; s。width; s。height);  

  }  

  class ML extends MouseAdapter {  

    public void mousePressed(MouseEvent e) {  

      notifier。notifyObservers(OCBox。this);  



                                                                                             591 


…………………………………………………………Page 593……………………………………………………………

    }  

  }  

  public void update(Obs
返回目录 上一页 下一页 回到顶部 0 0
未阅读完?加入书签已便下次继续阅读!
温馨提示: 温看小说的同时发表评论,说出自己的看法和其它小伙伴们分享也不错哦!发表书评还可以获得积分和经验奖励,认真写原创书评 被采纳为精评可以获得大量金币、积分和经验奖励哦!