📜  观察者模式 |设置 2(实施)

📅  最后修改于: 2021-09-10 02:39:43             🧑  作者: Mango

我们强烈建议在继续阅读这篇文章之前参考下面的 Set 1。

观察者模式 – 介绍

在第一组中,我们讨论了下面的问题,一个没有观察者模式的问题的解决方案和解决方案的问题。

假设我们正在构建一个板球应用程序,通知观众有关当前分数、运行率等信息。假设我们已经制作了两个显示元素 CurrentScoreDisplay 和 AverageScoreDisplay。 CricketData 拥有所有数据(跑步、保龄球等),每当数据更改时,显示元素都会收到新数据通知,并相应地显示最新数据

将观察者模式应用于上述问题:
让我们看看如何使用观察者模式改进应用程序的设计。如果我们观察数据流,我们可以很容易地看到 CricketData 和显示元素遵循主题 – 观察者关系。

新类图:
o3

Java实现:

// Java program to demonstrate working of
// onserver pattern
import java.util.ArrayList;
import java.util.Iterator;
  
// Implemented by Cricket data to communicate
// with observers
interface Subject
{
    public void registerObserver(Observer o);
    public void unregisterObserver(Observer o);
    public void notifyObservers();
}
  
class CricketData implements Subject
{
    int runs;
    int wickets;
    float overs;
    ArrayList observerList;
  
    public CricketData() {
        observerList = new ArrayList();
    }
  
    @Override
    public void registerObserver(Observer o) {
        observerList.add(o);
    }
  
    @Override
    public void unregisterObserver(Observer o) {
        observerList.remove(observerList.indexOf(o));
    }
  
    @Override
    public void notifyObservers()
    {
        for (Iterator it =
              observerList.iterator(); it.hasNext();)
        {
            Observer o = it.next();
            o.update(runs,wickets,overs);
        }
    }
  
    // get latest runs from stadium
    private int getLatestRuns()
    {
        // return 90 for simplicity
        return 90;
    }
  
    // get latest wickets from stadium
    private int getLatestWickets()
    {
        // return 2 for simplicity
        return 2;
    }
  
    // get latest overs from stadium
    private float getLatestOvers()
    {
        // return 90 for simplicity
        return (float)10.2;
    }
  
    // This method is used update displays
    // when data changes
    public void dataChanged()
    {
        //get latest data
        runs = getLatestRuns();
        wickets = getLatestWickets();
        overs = getLatestOvers();
  
        notifyObservers();
    }
}
  
// This interface is implemented by all those
// classes that are to be updated whenever there
// is an update from CricketData
interface Observer
{
    public void update(int runs, int wickets,
                      float overs);
}
  
class AverageScoreDisplay implements Observer
{
    private float runRate;
    private int predictedScore;
  
    public void update(int runs, int wickets,
                       float overs)
    {
        this.runRate =(float)runs/overs;
        this.predictedScore = (int)(this.runRate * 50);
        display();
    }
  
    public void display()
    {
        System.out.println("\nAverage Score Display: \n"
                           + "Run Rate: " + runRate +
                           "\nPredictedScore: " +
                           predictedScore);
    }
}
  
class CurrentScoreDisplay implements Observer
{
    private int runs, wickets;
    private float overs;
  
    public void update(int runs, int wickets,
                       float overs)
    {
        this.runs = runs;
        this.wickets = wickets;
        this.overs = overs;
        display();
    }
  
    public void display()
    {
        System.out.println("\nCurrent Score Display:\n"
                           + "Runs: " + runs +
                           "\nWickets:" + wickets +
                           "\nOvers: " + overs );
    }
}
  
// Driver Class
class Main
{
    public static void main(String args[])
    {
        // create objects for testing
        AverageScoreDisplay averageScoreDisplay =
                          new AverageScoreDisplay();
        CurrentScoreDisplay currentScoreDisplay =
                          new CurrentScoreDisplay();
  
        // pass the displays to Cricket data
        CricketData cricketData = new CricketData();
  
        // register display elements
        cricketData.registerObserver(averageScoreDisplay);
        cricketData.registerObserver(currentScoreDisplay);
  
        // in real app you would have some logic to
        // call this function when data changes
        cricketData.dataChanged();
  
        //remove an observer
        cricketData.unregisterObserver(averageScoreDisplay);
  
        // now only currentScoreDisplay gets the
        // notification
        cricketData.dataChanged();
    }
}

输出:

Average Score Display: 
Run Rate: 8.823529
PredictedScore: 441

Current Score Display:
Runs: 90
Wickets:2
Overs: 10.2

Current Score Display:
Runs: 90
Wickets:2
Overs: 10.2

注意:现在我们可以在不改变主题的情况下添加/删除尽可能多的观察者。

参考:

  1. https://en.wikipedia.org/wiki/Observer_pattern
  2. Head First Design Patterns 书(强烈推荐)