观察者模式

概念

观察者(Observer)模式的定义:指多个对象间存在一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新

顾客对某个特定品牌的产品非常感兴趣(例如最新型号的 iPhone 手机),而该产品很快将会在商店里出售。

顾客可以每天来商店看看产品是否到货。但如果商品尚未到货时,绝大多数来到商店的顾客都会空手而归。另一方面,每次新产品到货时,商店也可以向所有顾客发送邮件(可能会被视为垃圾邮件)。这样,部分顾客就无需反复前往商店了,但也可能会惹恼对新产品没有兴趣的其他顾客

似乎遇到了一个矛盾:要么让顾客浪费时间检查产品是否到货,要么让商店浪费资源去通知没有需求的顾客。

观察者模式建议,为发布者类添加订阅机制,让每个对象都能订阅或取消订阅发布者事件流。

观察者模式结构

观察者模式实例:人民币汇率

利用观察者模式设计一个程序,分析“人民币汇率”的升值或贬值对进口公司进口产品成本,或出口公司的出口产品收入的影响。

当“人民币汇率”升值时,进口公司的进口产品成本降低且利润率提升,出口公司的出口产品收入降低且利润率降低;当“人民币汇率”贬值时,进口公司的进口产品成本提升且利润率降低,出口公司的出口产品收入提升且利润率提升。

  • 这里的汇率(Rate)类是抽象目标类,它包含了保存观察者(Company)的List和增加/删除观察者的方法,以及有关汇率改变的抽象方法change(int number)
  • 而人民币汇率(RMBrate)类是具体目标,它实现了父类的change(int number)方法,即当人民币汇率发生改变时通过相关公司
  • 公司(Company)类是抽象观察者,它定义了一个有关汇率反应的抽象方法response(int number)
  • 进口公司(ImportCompany)类和出口公司(ExportCompany)类是具体观察者类,它们实现了父类的response(int number)方法,即当它们接收到汇率发生改变的通知时作为相应的反应。

订阅者及具体订阅者

package observer;

/**
 * 抽象观察者:公司
 * @author chenzufeng
 * @date 2021-2-8
 */
public interface Company {
    /**
     * 对汇率的反应
     * @param number 汇率
     */
    void response(int number);
}

出口公司:

package observer;

public class ExportCompany implements Company {
    @Override
    public void response(int number) {
        if (number > 0) {
            System.out.println("人民币汇率升值" + number + "个基点,降低了出口产品收入,降低了出口公司的销售利润率。");
        } else if (number < 0) {
            System.out.println("人民币汇率贬值" + (-number) + "个基点,提升了出口产品收入,提升了出口公司的销售利润率。");
        }
    }
}

进口公司:

package observer;

public class ImportCompany implements Company {
    @Override
    public void response(int number) {
        if (number > 0) {
            System.out.println("人民币汇率升值" + number + "个基点,降低了进口产品成本,提升了进口公司利润率。");
        } else if (number < 0) {
            System.out.println("人民币汇率贬值" + (-number) + "个基点,提升了进口产品成本,降低了进口公司利润率。");
        }
    }
}

发布者

package observer;

import java.util.ArrayList;
import java.util.List;

/**
 * 抽象目标:汇率
 */
abstract class Rate {
    protected List<Company> companyList = new ArrayList<>();

    /**
     * 增加观察者
     * @param company 公司
     */
    public void addCompany(Company company) {
        companyList.add(company);
    }

    /**
     * 删除观察者
     * @param company 公司
     */
    public void removeCompany(Company company) {
        companyList.remove(company);
    }

    /**
     * 汇率改变
     * @param number 汇率
     */
    public abstract void change(int number);
}
package observer;

/**
 * 具体目标:人民币汇率
 */
public class RMBrate extends Rate {
    @Override
    public void change(int number) {
        for (Company company : companyList) {
            company.response(number);
        }
    }
}

客户端

package observer;

public class Client {
    public static void main(String[] args) {
        Rate rate = new RMBrate();
        Company company1 = new ImportCompany();
        Company company2 = new ExportCompany();

        rate.addCompany(company1);
        rate.addCompany(company2);

        rate.change(10);
        rate.change(-5);
    }
}
posted @ 2021-03-12 12:13  chenzufeng  阅读(977)  评论(0)    收藏  举报