6月更文挑战|设计模式 —— 观察者模式

127 阅读3分钟

这是我参与更文挑战的第12天,活动详情查看:更文挑战

观察者模式

观察者模式使用率上还是比较高的,可以将它理解为订阅-发布系统。它将观察者和被观察者解耦,使得它们之间依赖性变小。通常观察者模式常用在UI交互和底层业务逻辑解耦场景中,来应对交互应用场景多变,业务逻辑变化不大的情况。

实战

观察者模式主要是两部分:观察者和被观察者。先为观察者和被观察者定义抽象类Observer和Subject,观察者具有获取消息能力update,被观察者具有添加、删除观察者以及向被观察者发送消息的能力。EmailNoticeUser实现了Observer的update执行观察者在接收消息后执行的功能。SubscriptionSubject实现Subject被观察者方法,其中被观察者有一个集合用来暂存观察者集合,通过attach和detach去修改集合的观察者列表,当有订阅消息时被观察者调用notify遍历观察者集合发送消息。

// 抽象观察者
public interface Observer{
    public void update(String message);
}
// 具体观察者
public class EmailNoticeUser extends Observer{

    @override
    public void update(String message){
        //...
    }
}

// 抽象被观察者
public interface Subject{
    // 添加订阅
    public void attach(Observer observer);
    // 删除订阅
    public void detach(Observer observer);
    // 订阅通知
    public void notify(String message);
}
// 具体被观察者
public class SubscriptionSubject implements Subject {
    //保存订阅邮件的列表
    private List<Observer> EmailUserlist = new ArrayList<Observer>();

    @Override
    public void attach(Observer observer) {
        EmailUserlist.add(observer);
    }

    @Override
    public void detach(Observer observer) {
        EmailUserlist.remove(observer);
    }

    @Override
    public void notify(String message) {
        for (Observer observer : EmailUserlist) {
            observer.update(message);
        }
    }
}

SubscriptionSubject subscriptionSubject = new SubscriptionSubject();
EmailNoticeUser emailNoticeUser1 = new EmailNoticeUser();
EmailNoticeUser emailNoticeUser2 = new EmailNoticeUser();
EmailNoticeUser emailNoticeUser3 = new EmailNoticeUser();

subscriptionSubject.attch(emailNoticeUser1);
subscriptionSubject.attch(emailNoticeUser2);
subscriptionSubject.attch(emailNoticeUser3);
subscriptionSubject.notify("新邮件消息");
subscriptionSubject.detach(emailNoticeUser3);

举例EventBus

EventBus是Android下高效的发布/订阅事件总线机制,它也是采用观察者模式的典型。EventBus很好的将消息发生和结束进行解耦,在Android的模块化和组件化开发中提供了各个业务间事件消息无缝衔接方案。

EventBus基本使用非常简单。

  1. 定义一个事件消息类
public static class MessageEvent { // 可以携带参数}
  1. 在需要接收消息的观察者中预埋需要接收的消息类型MessageEvent和接收的线程模式。
@Subscribe(threadMode = ThreadMode.MAIN)  
public void onMessageEvent(MessageEvent event) {
    // 接收消息 进行处理
}
  1. 在合适的生命周期中注册和注销订阅
@Override
 public void onStart() {
     super.onStart();
     EventBus.getDefault().register(this);
 }

 @Override
 public void onStop() {
     super.onStop();
     EventBus.getDefault().unregister(this);
 }
  1. 被观察者发送消息
EventBus.getDefault().post(new MessageEvent());

总结

观察者模式的有点在于将观察者和被观察者之间是抽象耦合,更好的应对业务变化,具有可扩展性、灵活性。缺点主要在于观察者模式以消息的形式默认是顺序执行,需要认真考量观察者的执行效率是否会影响整体程序运行,通常情况观察者会以异步的方式执行。