JAVA23种设计模式之观察者模式

  1. 观察者模式:
    是一种对象的行为模式,又叫做发布订阅模式,相当于现在的订阅微信公众号功能。微信公众号是被观察者,关注公众号的用户是观察者。这些被观察者与观察者之间存在一对多的关系,当被观察者发生变化时,会通知观察者,让他们能知悉。公众号推送消息,所有的关注用户都可以接收到消息,就是这个道理。
  2. 观察者模式分类:
    观察者模式分为两大类:推模型和拉模型
    • 推模型:被观察者发生改变主动向观察者推送,不管观察者是否需要,推送的信息通常是主题对象的全部或部分数据。这类似于微信公众号的消息推送功能。
    • 拉模型:被观察对象在发生变化时,只推送少量信息给到观察者,如果观察者需要更加具体的信息,则需要主动去被观察的对象中拉取。一般需要被观察者提供对应的方法给到观察者。
    • 比较:
    1. 推模型是假定被观察对象知道观察对象需要哪些数据,而拉模型是被观察对象不知道观察者需要哪些数据,只能将自身全部传递给到观察者。
    2. 推模型由于数据参数是确定的,后期不利于扩展,如果后面有新的内容加入就需要新建不懂参数的方法,相比较下,拉模型就不会出现这种情况,因为拉模型是将被观察者整个传递给到观察者。已经包涵了所有被观察者的信息了。
  3. 观察者模式示意图:

在这里插入图片描述

  1. 观察者模式设计到的角色:
  • 抽象被观察者角色: 图上的Subject角色, 改角色一般为接口或者抽象类,主要用于提供方法来将所有的观察者存储到一个集合中,另外还需要提供接口方法来添加观察者和移除观察者,以及通知到信息给到所有观察者。
  • 抽象观察者: 为所有的具体观察者定义一个接口,在得到被观察者通知时更新自己。
  • 具体被观察者角色: 实现或者集成抽象被观察者的方法,在自身内部发生变化时,通知给到所有注册或者登记过的观察者。
  • 具体观察者角色: 实现抽象观察者的方法,一旦检测到被观察者有变动,立即更新自身信息,使本身的状态与被观察者的状态一致。
  1. 示例:(该示例包含了观察者模式中的推模式和拉模式)
    场景:微信公众号推送消息给到关注的微信用户。
    **抽象被观察者角色:**提供注册、移除、通知所有观察者变更信息的方法,
public interface Subject {

   //注册观察者
   void reigsterObserver(Observer o);

   //移除观察者
   void removeObserver(Observer o );

   //通知所有观察者
   void notifyAllObserver();

   //拉模型中的推送方法
   void notifyAllObserverByPull();
}

**抽象观察者:**主要提供实时更新或者显示信息的方式

public interface Observer {

    //显示信息(被观察者主动推送的信息)
    void show(String info);

    //主动拉数据
    void showByPull(Subject subject);
}

**具体被观察者角色:**主要实现具体的抽象被观察者的方法,以及推送信息的方法

public class WechatSever implements Subject {

    private ArrayList<Observer> users = new ArrayList<Observer>();
    private String info;
    private String href;

    @Override
    public void reigsterObserver(Observer o) {
        users.add(o);
    }

    @Override
    public void removeObserver(Observer o) {
        if (users.contains(o)){
            users.remove(o);
        }else{
            System.out.println("订阅者不存在");
        }
    }

    @Override
    public void notifyAllObserver() {
        for (Observer user: users ) {
                user.show(info);
        }
    }

    public void sendInfo(String s){
        info = s;
        notifyAllObserver();
    }

    //拉模型
    @Override
    public void notifyAllObserverByPull() {
        for (Observer user: users ) {
            user.showByPull(this);
        }
    }
    
    public void sendInfoByPull(){
        this.setInfo("JAVA Is Very Nice!!!!");
        this.setHref("www.baidu.com");
        notifyAllObserverByPull();
    }

    public String getInfo() {
        return info;
    }

    public void setInfo(String info) {
        this.info = info;
    }

    public String getHref() {
        return href;
    }

    public void setHref(String href) {
        this.href = href;
    }
}

具体观察者角色:

public class User implements Observer{

    private String username;

    public User(String username) {
        this.username = username;
    }

    @Override
    public void show(String info) {
        System.out.println(username+":"+info);
    }

    //拉数据
    @Override
    public void showByPull(Subject subject) {
        String info = ((WechatSever)subject).getInfo();
        String href =  ((WechatSever)subject).getHref();
        System.out.println("Pull>>>>>"+username+":"+href);
    }
}

测试函数:

public class Main {
    public static void main(String[] args) {
        //初始化微信公众号
        WechatSever wechatSever = new WechatSever();

        //初始化订阅用户
        User user = new User("ZhangSan");
        User user_1 = new User("LiSi");
        User user_2 = new User("WangWu");

        //注册用户为观察者
        wechatSever.reigsterObserver(user);
        wechatSever.reigsterObserver(user_1);
        wechatSever.reigsterObserver(user_2);

        //推送微信消息
       // wechatSever.sendInfo("今天是2019年一月6号,天气小雨,注意保暖");

        //ZhangSan取消订阅
        wechatSever.removeObserver(user);

        //再次推送
        //wechatSever.sendInfo("再次推送消息");

        //拉数据
        wechatSever.sendInfoByPull();

    }
}
  1. 观察者模式的优缺点
  • 优点:
    1. 在这个模式下观察者和被观察者是松耦合的,观察者模式的扩展性高。
    2. 当被观察发生变动时,观察者可以很快获取到。
  • 缺点:
    1. 如果有很多的观察者,会影响到系统的性能,因为此时被观察者需要花费大量的时间去通知观察者。
    2. 如果观察者之间有依赖关系的情况下,循环调用会导致系统宕机。
  1. JAVA自带的观察者模式:
    使用JAVA内置的观察者需要以下操作:
    被观察者对象: 需要继承Observable,该类提供添加及移出观察者对像方法,数据发生哟完成时并通知所有已经添加进来的观察者对象。
public class SubjectForJava extends Observable {

    private String info;

    public String getInfo() {
        return info;
    }

    public void setInfo(String info) {
        this.info = info;
    }

    public void setWork(String info){
        this.info=info;
        setChanged();
        notifyObservers();
        //notifyObservers(this);
    }
}

**观察者对象:**实现Observer接口,监听被观察者对象数据变化。

public class ObserverForJava implements Observer {

    @Override
    public void update(Observable o, Object arg) {
        SubjectForJava subjectForJava = (SubjectForJava) o;
        System.out.println(">>>>>>>"+subjectForJava.getInfo());
    }
}

测试主函数:

public class Main {

    public static void main(String[] args) {
        SubjectForJava subjectForJava = new SubjectForJava();
        ObserverForJava observerForJava = new ObserverForJava();
        subjectForJava.addObserver(observerForJava);
        subjectForJava.setWork("你好!JAVA!");
    }
}

JAVA自带的观察者方式既提供了用于推模型的方法,也提供了用于拉模型的方法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值