聊
这期我们一起学学观察者模式,《一起学策咯模式》是第一次写文章,总结了一下经验,感觉就一个字【太罗嗦】,所以这次来点新鲜的,简单的,不同以往的,超级棒的,无与伦比的,让你们读完就和我一样学会观察者模式的,并且还没看完就想点赞的。开始吧。
例
设计一个信用卡提醒功能的案例,上学就被信用卡坑过的我(完全不知道办理了一张信用卡,并进行了消费,也没有还款提醒,还超期未还年费,被银行无情的拉入了黑名单中,导致许多年都生活在可怕的信用卡阴影中),在不久前又鼓起了勇气办了一张信用卡,这次办卡经历还算不错,在开通时就选择了账单提醒功能,可以通过邮件、短信、微信公众号、挂号信等形式通知我,这次我们就用观察者模式实现一个简单的信用卡提醒功能。
假定我们已经开通信用卡,并且已有一个可以收到信用卡消费消息的类,完成一个可以任意选择提醒方式,并在进行消费后用多种方式同时通知本人消费情况。有兴趣可以自行实现一下再来对比对比我的实现。
设:
银行消息类{ 获得消费金额();获得消费场所();获得消费时间();消费通知方法();}
可以获得信用卡的每一笔消费金额及消费场所和时间.
短信通知类{通知更新方法();显示方法()}
微信通知类{通知更新方法();显示方法()}
邮件通知类{通知更新方法();显示方法()}
当银行获得模拟消费操作后,通过调用消费通知方法(),完成消费的通知,消费通知类收到通知后,各自调用显示方法()提醒消费信息;
将此系统设计成可扩展的,例如通知类可以新增,比如挂号信方式,电话通知方式,例如通知类型可随意开关,我只想要短信和邮件通知,并不需要微信,之后我又开通了微信,并想打开微信通知.诸如此类操作.
做
创建银行消息类:BankMessage
class BankMessage extends Observable {
private Float consumptionAmount;
private String consumptionAddress;
private Date consumptionDate;
//通知方法
private void consumptionNotify() {
//改变标记
setChanged();
//通知观察者,参数为this
notifyObservers(this);
}
//模拟消费方法
void setConsumptionAction(Float consumptionAmount, String consumptionAddress, Date consumptionDate){
this.consumptionAddress = consumptionAddress;
this.consumptionAmount = consumptionAmount;
this.consumptionDate = consumptionDate;
consumptionNotify();
}
Float getConsumptionAmount() {
return consumptionAmount;
}
String getConsumptionAddress() {
return consumptionAddress;
}
Date getConsumptionDate() {
return consumptionDate;
}
}
创建消费通知接口:ConsumptionNotify
public interface ConsumptionNotify {
void display();
}
创建邮件通知类:MailNotify
public class MailNotify implements Observer, ConsumptionNotify {
private Observable observable;
private Float consumptionAmount;
private String consumptionAddress;
private Date consumptionDate;
public MailNotify(Observable observable) {
this.observable = observable;
observable.addObserver(this);
}
@Override
public void display() {
//模拟邮件发送
System.out.println("邮件消息:" + consumptionDate + "时,您在" +consumptionAddress+"消费了"+consumptionAmount+"元人民币");
}
@Override
public void update(Observable o, Object arg) {
if (o instanceof BankMessage) {
BankMessage bankMessage = (BankMessage) o;
//可自定义通知条件:达到10元以上才启用邮件形式
if (bankMessage.getConsumptionAmount() > 10) {
this.consumptionAmount = bankMessage.getConsumptionAmount();
this.consumptionAddress = bankMessage.getConsumptionAddress();
this.consumptionDate = bankMessage.getConsumptionDate();
display();
}
}
}
}
创建短信通知类:SMSNotify
public class SMSNotify implements Observer, ConsumptionNotify {
private Observable observable;
private Float consumptionAmount;
private String consumptionAddress;
private Date consumptionDate;
public SMSNotify(Observable observable) {
this.observable = observable;
observable.addObserver(this);
}
@Override
public void display() {
System.out.println("短信消息:" + consumptionDate + "时,您在" +consumptionAddress+"消费了"+consumptionAmount+"元人民币");
}
@Override
public void update(Observable o, Object arg) {
if (o instanceof BankMessage) {
BankMessage bankMessage = (BankMessage) o;
this.consumptionAmount = bankMessage.getConsumptionAmount();
this.consumptionAddress = bankMessage.getConsumptionAddress();
this.consumptionDate = bankMessage.getConsumptionDate();
display();
}
}
}
创建微信通知类:WechatNotify
public class WechatNotify implements Observer, ConsumptionNotify {
private Observable observable;
private Float consumptionAmount;
private String consumptionAddress;
private Date consumptionDate;
public WechatNotify(Observable observable) {
this.observable = observable;
observable.addObserver(this);
}
@Override
public void display() {
//模拟邮件发送
System.out.println("微信消息:" + consumptionDate + "时,您在" +consumptionAddress+"消费了"+consumptionAmount+"元人民币");
}
@Override
public void update(Observable o, Object arg) {
if (o instanceof BankMessage) {
BankMessage bankMessage = (BankMessage) o;
this.consumptionAmount = bankMessage.getConsumptionAmount();
this.consumptionAddress = bankMessage.getConsumptionAddress();
this.consumptionDate = bankMessage.getConsumptionDate();
display();
}
}
}
创建测试方法:TestMain
public class TestMain {
public static void main(String[] args) {
BankMessage data = new BankMessage();
SMSNotify smsNotify = new SMSNotify(data);
MailNotify mailNotify = new MailNotify(data);
WechatNotify wechatNotify = new WechatNotify(data);
data.setConsumptionAction(5.5F, "超市", new Date());
data.setConsumptionAction(15.5F, "餐厅", new Date());
data.deleteObserver(mailNotify);
data.setConsumptionAction(55.5F, "旅店", new Date());
}
}
通过运行测试方法即可看到结果,一个简单的观察者模式案例完成啦.
记
- 设计原则:独立出应用中可能需要变化部分,不要和那些不需要变化的代码混在一起。
- 设计原则:针对接口编程,而不是针对实现编程
- 设计原则:多用组合,少用继承
- 设计原则:为了交互对象之间的松耦合设计而努力
观察者模式定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新.
Observable类:java.util 包提供的观察者模式主题父类
可观察者继承后,提供一些添加删除观察者的方法.
Observer接口:接口定义了”推”或”拉”数据的方法,实现接口update方法,可任意自定义获取到的数据处理方式.
实
学习此设计模式后我第一个想到的实际应用就是之前做过的一个程序,对同类设备进行不同的检测,被检测设备的数量可能随时变化,可以定义成可观察类,并且定时进行设备更新,数量变化后,通知不同类型的检测类,分别进行检测,并且可随时控制某一类检测的开关.