观察者模式

观察者模式(Observer) 应用场景:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象 都得到通知并被自动更新。 Spring 中 Observer 模式常用的地方是 Listener 的实现。如 ApplicationListener

1.观察者模式的概念

观察者模式又叫做发布-订阅(Publish/Subscribe)模式、 模型-视图(Model/View)模式、源-监听器(Source/Listener) 模式或从属者(Dependents)模式。

观察者模式定义了一种一对多的依赖关系,让多个观察 者对象同时监听某一个主题对象。这个主题对象在状态上发 生变化时,会通知所有观察者对象,使它们能够自动更新自 己。 

一个软件系统常常要求在某一个对象的状态发生变化的 时候,某些其它的对象做出相应的改变。做到这一点的设计 方案有很多,但是为了使系统能够易于复用,应该选择低耦 合度的设计方案。减少对象之间的耦合有利于系统的复用, 但是同时设计者需要使这些低耦合度的对象之间能够维持行 动的协调一致,保证高度的协作(Collaboration)。观察者模 式是满足这一要求的各种设计方案中重要的一种。 

2.观察者模式的结构 观察者模式的类图如图 1 所示。

观察者模式的实现由以下角色组成:

●抽象主题(Subject)角色:又称为抽象被观察者 (Observable) 角色,提供一个接口,把所有对观察者对象的引 用保存在一个聚集(Collection)里。每个主题可以有任意多数量 的观察者,可以增加和删除观察者对象。

●抽象观察者(Observer)角色:为所有的具体观察者定义 的一个接口,在得到主题的通知时更新自己,此接口叫做更 新接口。更新接口只包含一个方法,即 update(),一般由一个 抽象类或一个接口实现。

●具体主题(ConcreteSubject)角色:又称为具体被观察者角色(Concrete Observable),将相关状态存入具体观察者对象, 当具体主题的内部状态改变时,给所有登记过的观察者发出 通知,通常由一个具体子类实现

●具体观察者(ConcreteObserver)角色:存储与主题角色 相一致的状态。具体观察者角色实现抽象观察者角色所要求 的 update()接口,以便使本身的状态与主题的状态相协调,通 常由一个具体子类实现

从具体主题角色指向抽象观察者角色的合成关系,代表 具体主题对象可以有任意多个对抽象观察者对象的引用。之 所以使用抽象观察者而不是具体观察者,意味着主题对象不 需要知道引用了哪些 ConcreteObserver(具体观察者) 类型,而只知道抽象 Observer 类型。这就使得具体主题对象可以动态地维护一系 列的对观察者对象的引用,并在需要的时候调用每一个观察 者共有的 update()方法

参考博客https://blog.csdn.net/itachi85/article/details/50773358

实现方式:

/**
 * 事件的注册和监听
 * Created by Tom on 2018/3/17.
 */
public class EventLisenter {

    //Map相当于是一个注册器
    protected Map<Enum,Event> events = new HashMap<Enum,Event>();

    public void addLisenter(Enum eventType,Object target,Method callback){
        //注册事件
        //用反射调用这个方法
        events.put(eventType,new Event(target,callback));
    }

    private void trigger(Event e){
        e.setSource(this);
        e.setTime(System.currentTimeMillis());

        try {
            e.getCallback().invoke(e.getTarget(),e);
        } catch (Exception e1) {
            e1.printStackTrace();
        }
    }


    protected void trigger(Enum call){
        if(!this.events.containsKey(call)){ return ;}
        trigger(this.events.get(call).setTrigger(call.toString()));
    }


}
public enum SubjectEventType {
    ON_ADD,
    ON_RMOVE,
    ON_EDIT,
    ON_QUERY;

}

抽象观察者:

public interface Observer {
    public void advice(Event e);
}

具体观察者:

public class ConcreteObserver  implements Observer{


    public void advice(Event e){
        System.out.println("=========触发事件,打印日志========\n" + e);

        /*
        *  input
        *  input.addLisenter("click",function(){
        *
        *
        *  });
        *
        *
        * */
    }

}

抽象主题:

public interface Subject {
    //通常的话,采用动态里来实现监控,避免了代码侵入
    public void add();

    public void remove();
}

具体主题角色:

public class ConcreteSubject extends EventLisenter implements Subject{

    //通常的话,采用动态里来实现监控,避免了代码侵入

    public void add(){
        System.out.println("调用添加的方法");
        trigger(SubjectEventType.ON_ADD);
    }

    public void remove(){
        System.out.println("调用删除的方法");
        trigger(SubjectEventType.ON_RMOVE);
    }

}

测试类:

public class ObserverTest {

    public static void main(String[] args) {

        try{

            //观察者
            ConcreteObserver observer = new ConcreteObserver();
            Method advice = ConcreteObserver.class.getMethod("advice", new Class<?>[]{Event.class});


            //这里写Lily
            ConcreteSubject subject = new ConcreteSubject();
            subject.addLisenter(SubjectEventType.ON_ADD,observer,advice);
            subject.addLisenter(SubjectEventType.ON_EDIT,observer,advice);
            subject.addLisenter(SubjectEventType.ON_RMOVE,observer,advice);
            subject.addLisenter(SubjectEventType.ON_QUERY,observer,advice);

            subject.add();
            subject.remove();

        }catch (Exception e){
            e.printStackTrace();
        }

    }

}

实现方式二:鼠标事件

public enum MouseEventType {
    ON_CLICK,
    ON_DOUBLE_CLICK,
    ON_UP,
    ON_DOWN,
    ON_WHEEL,
    ON_MOVE,
    ON_OVER;

}

具体主题:

/**
 * 被观察者
 * 如果做过Swing开发的话,有一种似曾相识的感觉
 * Created by Tom on 2018/3/17.
 */
public class Mouse extends EventLisenter{

    public void click(){
        System.out.println("鼠标单击");
        this.trigger(MouseEventType.ON_CLICK);
    }


    public void doubleClick(){
        System.out.println("鼠标双击");
        this.trigger(MouseEventType.ON_DOUBLE_CLICK);
    }

    public void up(){
        System.out.println("鼠标弹起");
        this.trigger(MouseEventType.ON_UP);
    }

    public void down(){
        System.out.println("鼠标按下");
        this.trigger(MouseEventType.ON_DOWN);
    }


    public void wheel(){
        System.out.println("鼠标滚动");
        this.trigger(MouseEventType.ON_WHEEL);
    }

    public void move(){
        System.out.println("鼠标移动");
        this.trigger(MouseEventType.ON_MOVE);
    }

    public void over(){
        System.out.println("鼠标悬停");
        this.trigger(MouseEventType.ON_OVER);
    }

}

具体观察者:

/**
 * 观察者
 *
 * 回调响应的逻辑,由自己实现
 * Created by Tom on 2018/3/17.
 */
public class MouseEventCallback {

    public void onClick(Event e){
        System.out.println("这是鼠标单击以后要执行的逻辑");
        System.out.println("=======触发鼠标单击事件========\n" + e);
    }

    public void onDoubleClick(Event e){
        System.out.println("=======触发鼠标双击事件========\n" + e);
    }

    public void onUp(Event e){
        System.out.println("=======触发鼠标弹起事件========\n" + e);
    }
    public void onDown(Event e){
        System.out.println("=======触发鼠标按下事件========\n" + e);
    }
    public void onMove(Event e){
        System.out.println("=======触发鼠标移动事件========\n" + e);
    }
    public void onWheel(Event e){
        System.out.println("=======触发鼠标滚动事件========\n" + e);
    }

    public void onOver(Event e){
        System.out.println("=======触发鼠标悬停事件========\n" + e);
    }

}

测试类:

public class MouseTest {

    public static void main(String[] args) {

        /*
        * var input = document.getElementById("username");
        * input.addLisenter("click",function(){
        *
        *     alert("鼠标点击了这个文本框");
        *
        * });
        *
        *
        * */

        //观察者和被观察者之间没有必然联系
        //注册的时候,才产生联系


        //解耦


        try {
//            MouseEventCallback callback = new MouseEventCallback();
//            Method onClick = MouseEventCallback.class.getMethod("onClick", Event.class);


            //人为的调用鼠标的单击事件
            Mouse mouse = new Mouse();
//            mouse.addLisenter(MouseEventType.ON_CLICK, callback,onClick);

            mouse.click();

        }catch (Exception e){
            e.printStackTrace();
        }

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值