要理解观察者模式(又叫发布与订阅模式),我们必须先了解以下概念:
观察者模式的主要角色如下。
1.抽象主题(Subject)角色:也叫抽象目标类,它提供了一个用于保存观察2.者对象的聚集类和增加、删除观察者对象的方法,以及通知所有观察者的抽象方法。
3.具体主题(Concrete Subject)角色:也叫具体目标类,它实现抽象目标中的通知方法,当具体主题的内部状态发生改变时,通知所有注册过的观察者对象。
4.抽象观察者(Observer)角色:它是一个抽象类或接口,它包含了一个更新自己的抽象方法,当接到具体主题的更改通知时被调用。
具体观察者(Concrete Observer)角色:实现抽象观察者中定义的抽象方法,以便在得到目标的更改通知时更新自身的状态。
当然,我们只看文字还是很难理解各个概念的具体意义,我们先来看一张UML图
通过UML图,或许让我们更了解了观察者模式了,我们通过一个简单的例子和代码片段来深入理解
【例1】利用观察者模式设计一个程序,分析“人民币汇率”的升值或贬值对进口公司进口产品成本或出口公司的出口产品收入以及公司利润率的影响。
分析:当“人民币汇率”升值时,进口公司的进口产品成本降低且利润率提升,出口公司的出口产品收入降低且利润率降低;当“人民币汇率”贬值时,进口公司的进口产品成本提升且利润率降低,出口公司的出口产品收入提升且利润率提升。
这里的汇率(Rate)类是抽象目标类,它包含了保存观察者(Company)的 List 和增加/删除观察者的方法,以及有关汇率改变的抽象方法 change(int number);而人民币汇率(RMBrate)类是具体目标, 它实现了父类的 change(int number) 方法,即当人民币汇率发生改变时通过相关公司;公司(Company)类是抽象观察者,它定义了一个有关汇率反应的抽象方法 response(int number);进口公司(ImportCompany)类和出口公司(ExportCompany)类是具体观察者类,它们实现了父类的 response(int number) 方法,即当它们接收到汇率发生改变的通知时作为相应的反应。
下图是该实例的UML图
接下来,我们用代码实现该实例
public class RMBrateTest {
public static void main(String[] args) {
Rate RMBrate = new RMBrate();
Company watcher1 = new ImportCompany();
Company watcher2 = new ExportCompany();
RMBrate.add(watcher1);
RMBrate.add(watcher2);
RMBrate.change(10);
RMBrate.change(-9);
}
}
//抽象目标,汇率
abstract class Rate{
//抽象观察者的实现类,具体观察者
protected List<Company> companies = new ArrayList<>();
//增加观察者方法
public void add(Company company){
companies.add(company);
}
//删除观察者方法
public void remove(Company company){
companies.remove(company);
}
public abstract void change(int number);
}
//具体目标,人民币汇率
class RMBrate extends Rate {
@Override
public void change(int number) {
for (Company company : companies) {
company.response(number);
}
}
}
//抽象观察者,公司
interface Company {
void response(int number);
}
//具体观察者1:进口公司
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) + "个基点,提升了进口产品成本,降低了进口公司利润率。");
}
}
}
//具体观察者2:出口公司
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) + "个基点,提升了出口产品收入,提升了出口公司的销售利润率。");
}
}
}
下图是运行结果
该文章只是纯粹记录个人学习笔记,可能会写的不太详细,请理解。