通俗易懂设计模式(观察者模式)

78 阅读4分钟

观察者模式(Observer Pattern)是一种行为型设计模式,它定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生改变时,会通知所有观察者对象,使它们能够自动更新自己。

观察者模式的主要角色有:

  1. 主题(Subject):这是一个抽象类或接口,用于描述具体主题需要实现的方法,例如添加、删除观察者和通知观察者。
  2. 具体主题(ConcreteSubject):实现主题接口,具体主题需要维护一个观察者列表,当具体主题状态发生改变时,通知所有观察者。
  3. 观察者(Observer):这是一个抽象类或接口,用于描述具体观察者需要实现的方法,例如更新自己。
  4. 具体观察者(ConcreteObserver):实现观察者接口,当接收到具体主题的通知时,进行相应的操作。

优点:

  1. 观察者模式可以实现表示层和数据层的分离,使得数据层在状态发生改变时,可以通知所有观察者进行更新,而无需关心具体观察者的实现细节。
  2. 观察者模式有利于扩展,当有新的观察者需要添加时,只需实现观察者接口即可。

缺点:

  1. 观察者模式可能会导致循环依赖,当观察者和主题之间存在相互依赖时,可能会导致系统难以维护。
  2. 如果观察者太多,通知所有观察者可能会影响系统性能。

下面是一个使用 Java 实现的观察者模式的例子:

// 主题接口
interface Subject {
    void registerObserver(Observer observer);
    void removeObserver(Observer observer);
    void notifyObservers();
}

// 具体主题
class ConcreteSubject implements Subject {
    private List<Observer> observers = new ArrayList<>();
    private String subjectState;

    @Override
    public void registerObserver(Observer observer) {
        observers.add(observer);
    }

    @Override
    public void removeObserver(Observer observer) {
        observers.remove(observer);
    }

    @Override
    public void notifyObservers() {
        for (Observer observer : observers) {
            observer.update(subjectState);
        }
    }

    public void setSubjectState(String subjectState) {
        this.subjectState = subjectState;
        notifyObservers();
    }
}

// 观察者接口
interface Observer {
    void update(String subjectState);
}

// 具体观察者
class ConcreteObserver implements Observer {
    private String observerState;

    @Override
    public void update(String subjectState) {
        observerState = subjectState;
        System.out.println("观察者状态更新为:" + observerState);
    }
}

public class ObserverPatternDemo {
    public static void main(String[] args) {
        // 创建具体主题
        ConcreteSubject subject = new ConcreteSubject();

        // 创建具体观察者
        Observer observer1 = new ConcreteObserver();
        Observer observer2 = new ConcreteObserver();

        // 注册观察者
        subject.registerObserver(observer1);
        subject.registerObserver(observer2);

        // 修改主题状态,通知观察者
        subject.setSubjectState("新状态");
    }
}

在这个例子中,我们创建了一个具体主题 ConcreteSubject 和两个具体观察者 ConcreteObserver。当具体主题的状态发生改变时,会通知所有注册的观察者进行更新。

使用场景:

案例一:聊天室程序

在聊天室程序中,当有新的消息到达时,需要通知所有在线的用户。这里可以使用观察者模式来实现。

具体实现如下:

  1. 创建一个主题接口 ChatRoomSubject,包含添加、删除观察者和通知观察者的方法。
  2. 创建一个具体主题 ChatRoom,实现主题接口,维护一个在线用户列表。当有新消息到达时,遍历用户列表并调用用户的 receiveMessage 方法通知他们有新消息。
  3. 创建一个观察者接口 User,包含接收消息的方法 receiveMessage
  4. 创建一个具体观察者 OnlineUser,实现观察者接口,代表在线用户。当收到新消息时,显示消息内容。

案例二:股票交易系统

在股票交易系统中,当股票价格发生变化时,需要通知所有关注该股票的投资者。这里可以使用观察者模式来实现。

具体实现如下:

  1. 创建一个主题接口 StockSubject,包含添加、删除观察者和通知观察者的方法。
  2. 创建一个具体主题 Stock,实现主题接口,维护一个关注该股票的投资者列表。当股票价格发生变化时,遍历投资者列表并调用投资者的 updatePrice 方法通知他们价格变化。
  3. 创建一个观察者接口 Investor,包含接收价格变化的方法 updatePrice
  4. 创建一个具体观察者 Trader,实现观察者接口,代表投资者。当收到股票价格变化时,根据新的价格做出相应的交易决策。

以下是使用 Java 实现股票交易系统的观察者模式的例子:

// 主题接口
interface StockSubject {
    void registerObserver(Investor investor);
    void removeObserver(Investor investor);
    void notifyObservers();
}

// 具体主题
class Stock implements StockSubject {
    private List<Investor> investors = new ArrayList<>();
    private double price;

    @Override
    public void registerObserver(Investor investor) {
        investors.add(investor);
    }

    @Override
    public void removeObserver(Investor investor) {
        investors.remove(investor);
    }

    @Override
    public void notifyObservers() {
        for (Investor investor : investors) {
            investor.updatePrice(price);
        }
    }

    public void setPrice(double price) {
        this.price = price;
        notifyObservers();
    }
}

// 观察者接口
interface Investor {
    void updatePrice(double price);
}

// 具体观察者
class Trader implements Investor {
    private String name;
    private double stockPrice;

    public Trader(String name) {
        this.name = name;
    }

    @Override
    public void updatePrice(double price) {
        this.stockPrice = price;
        System.out.println(name + " 的股票价格更新为:" + stockPrice);
    }
}

public class ObserverPatternDemo {
    public static void main(String[] args) {
        // 创建具体主题
        Stock stock = new Stock();

        // 创建具体观察者
        Investor investor1 = new Trader("张三");
        Investor investor2 = new Trader("李四");

        // 注册观察者
        stock.registerObserver(investor1);
        stock.registerObserver(investor2);

        // 修改股票价格,通知观察者
        stock.setPrice(100.0);
    }
}

在这个例子中,我们创建了一个具体主题 Stock 和两个具体观察者 Trader。当股票价格发生变化时,会通知所有关注该股票的投资者进行更新。