设计模式 Day06 迭代器模式、观察者模式

1. 如何判断你已经掌握了某种设计模式?(非常重要)
  • ① 这个模式的意图是什么?它解决了什么问题、什么时候可以使用它
  • ② 它是如何解决的?掌握它的结构图,记住它的关键代码
  • ③ 至少能够想到它的两个应用实例,一个生活中的,一个软件中的
  • ④ 这个模式的缺点是什么?在使用时要注意什么

一、迭代器模式

1. 这个模式的意图是什么?它解决了什么问题、什么时候可以使用它
  • 什么时候使用它:
  • 将聚合类中负责遍历数据的方法提取出来,封装到专门的类中,实现数据存储和数据遍历分离,无须暴露聚合类的内部属性即可对其进行操作。
2. 他是如何解决的?掌握它的结构图,记住它的关键代码
image.png
  • 结构图:
  • Iterator(抽象迭代器):它定义了访问和遍历元素的接口,声明了用于遍历数据元素的方法。
  • ConcreteIterator(具体迭代器):它实现了迭代器接口,完成了对聚合对象的遍历,同时在具体迭代器中通过游标来记录在聚合对象中所处的当前位置。
  • Aggregate(抽象聚合类):它实现了在抽象聚合类中声明的 createIterator()方法。
  • ConcreteAggregate(具体聚合类):它实现了在抽象聚合类中什么的 createIterator()方法。
  • 关键代码:
  • 抽象迭代器
interface Iterator {
    public void first(); //将游标指向第一个元素
    public void next(); //将游标指向下一个元素
    public boolean hasNext(); //判断是否存在下一个元素
    public Object currentItem(); //获取游标指向的当前元素
}
  • 具体迭代器
class ConcreteIterator implements Iterator {
    private ConcreteAggregate objects; //维持一个对具体聚合对象的引用,以便于访问存储在聚合对象中的数据
    private int cursor; //定义一个游标,用于记录当前访问位置
    public ConcreteIterator(ConcreteAggregate objects) {
        this.objects=objects;
    }
 
    public void first() {  ......  }
        
    public void next() {  ......  }
 
    public boolean hasNext() {  ......  }
    
    public Object currentItem() {  ......  }
}
  • 抽象聚合类
interface Aggregate {
    Iterator createIterator();
}
  • 具体聚合类
class ConcreteAggregate implements Aggregate {  
    ......  
    public Iterator createIterator() {
    return new ConcreteIterator(this);
    }
    ......
}
3. 至少能够想到它的两个应用实例?一个生活中的,一个软件中的
  • 生活中的:待定
  • 软件中的:大部分集合类都是聚合类,而且都是用迭代器模式来实现对它们的遍历
4. 这个模式的缺点是什么?在使用时要注意什么
  • 要注意什么:
  • ① 由于迭代器模式将存储数据和遍历数据的职责分离,增加新的聚合类需要对应增加新的迭代器,类的个数成对增加,这在一定程度上增加了系统的复杂性。
  • ② 抽象迭代器的设计难度比较大,需要充分考虑到系统将来的扩展,创建一个考虑全面的抽象迭代器并不是一件很容易的事情。

二、观察者模式

1. 这个设计模式的意图是什么?它解决了什么问题、什么时候可以使用它
  • 什么时候使用它:
  • 它为实现对象之间的联动提供了一套完整的解决方法,凡是涉及到一对一或者一对多对象交互场景都可以使用观察者模式。
2. 它是如何解决的?掌握它的结构图,记住它的关键代码
image.png
  • 结构图:

  • Subject(目标):目标又称为主题,它是指被观察的对象。在目标中定义了一个观察者集合,一个观察目标可以接受任意数量的观察者来观察,它提供一系列方法来增加和删除观察者对象,同时它定义了通知方法notify()。目标类可以是接口,也可以是抽象类或具体类。

  • ConcreteSubject(具体目标):具体目标是目标类的子类,通常它包含有经常发生改变的数据,当它的状态发生改变时,向它的各个观察者发出通知;同时它还实现了在目标类中定义的抽象业务逻辑方法(如果有的话)。如果无须扩展目标类,则具体目标类可以省略。

  • Observer(观察者):观察者将对观察目标的改变做出反应,观察者一般定义为接口,该接口声明了更新数据的方法update(),因此又称为抽象观察者。

  • ConcreteObserver(具体观察者):在具体观察者中维护一个指向具体目标对象的引用,它存储具体观察者的有关状态,这些状态需要和具体目标的状态保持一致;它实现了在抽象观察者Observer中定义的update()方法。通常在实现时,可以调用具体目标类的attach()方法将自己添加到目标类的集合中或通过detach()方法将自己从目标类的集合中删除。

  • 关键代码:

  • 抽象目标

import java.util.*;
abstract class Subject {
    //定义一个观察者集合用于存储所有观察者对象
protected ArrayList observers = new ArrayList();
 
//注册方法,用于向观察者集合中增加一个观察者
    public void attach(Observer observer) {
    observers.add(observer);
}
 
    //注销方法,用于在观察者集合中删除一个观察者
    public void detach(Observer observer) {
    observers.remove(observer);
}
 
    //声明抽象通知方法
    public abstract void notify();
}
  • 具体目标类
class ConcreteSubject extends Subject {
    //实现通知方法
    public void notify() {
        //遍历观察者集合,调用每一个观察者的响应方法
        for(Object obs:observers) {
            ((Observer)obs).update();
        }
    }   
}
  • 抽象观察者
interface Observer {
    //声明响应方法
    public void update();
}
  • 具体观察者
class ConcreteObserver implements Observer {
    //实现响应方法
    public void update() {
        //具体响应代码
    }
}
3. 至少能够想到它的两个应用实例,一个生活中的,一个软件中的
  • 生活中:红绿灯变化(观察目标)控制着汽车(观察者)联动的行为
  • 软件中:广泛应用于各种编程语言的 GUI 事件处理
4. 这个模式的缺点是什么?在使用时需要注意什么
  • 缺点:
  • ① 如果一个观察目标对象有很多直接和间接观察者,将所有的观察者都通知到会花费很多时间。
  • ② 如果在观察者和观察目标之间存在循环依赖,观察目标会触发它们之间进行循环调用,可能导致系统崩溃。
  • ③ 观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化。

你可能感兴趣的:(设计模式 Day06 迭代器模式、观察者模式)