美文网首页
常用的设计模式(笔记)——观察者

常用的设计模式(笔记)——观察者

作者: 红鲤鱼与绿鲤鱼与驴与鱼 | 来源:发表于2022-03-17 10:19 被阅读0次

    个人理解:观察者就是当 对象A触发某个事件时 调用对象B 的方法,这种的就是观察者
    举例:现在有一孩子(Child)在睡觉,当孩子醒来时通知父母(Mom 和 Dad)做一些事情,其中孩子是被观察者 父母是观察者
    先定义一个观察者接口,观察者就是通过这个方法来观察 被观察者,换句话说就是被观察者调用观察者 doSomething方法来通知他们

    /**
     * 抽象的观察者
     * 观察者需要实现的接口
     */
    interface Observer {
        void doSomething(WakeupEvent event);
    }
    

    具体的观察者,都需要实现Observer接口

    /**
     * 具体的观察者
     */
    public class Dad implements Observer{
        public void playGame(){
            System.out.println("打游戏");
        }
        @Override
        public void doSomething(WakeupEvent event) {
            System.out.println("哪个事件源发出的:" + event.getSource().getClass());
            System.out.println("爸爸:孩子醒了就去打游戏");
            playGame();
        }
    }
    
    /**
     * 具体的观察者
     */
    public class Mom implements Observer {
        public void nurse() {
            System.out.println("给孩子喂奶");
        }
    
        @Override
        public void doSomething(WakeupEvent event) {
            System.out.println("哪个事件源发出的:" + event.getSource().getClass());
            System.out.println("妈妈:孩子醒了就喂奶");
            nurse();
        }
    }
    

    接下来就是被观察者,被观察者(Child) 是需要持有 观察者对象(Mom、Dad) 实例的

    /**
     * 这是被观察者
     */
    public class Child {
        /**
         * 存放具体的观察者,可能被多个人观察所以用 List
         */
        private ArrayList<Observer> observers = new ArrayList<>();
    
        /**
         * 添加观察者
         *
         * @param observer 具体的观察者
         */
        public void addObserver(Observer observer) {
            observers.add(observer);
        }
    
        /**
         * 孩子醒了
         */
        public void wakeUp() {
            long time = System.currentTimeMillis();
            Date date = new Date(time);
    
            WakeupEvent event = new WakeupEvent(date.getTime(), "床上", this);
            //通知观察者
            observers.forEach(observer -> {
                observer.doSomething(event);
            });
        }
    }
    
    

    还有一个类就是WakeupEvent,这个类是干什么的呢?
    这是一个事件类,根据面向对象的原则 被观察者观察者 之间通过这个对像来传递参数,当然如果不用这个类的话,那doSomething这个方法就要多传几个参数,比如 几点醒来的,在哪醒的,醒来后是个什么状态(哭、闹、笑)等等,所以要封装成对象
    注意 private Child source;这句话,为什么会有这个,因为当被观察者收到 WakeupEvent 对象时需要知道是哪个被观察者观察者不可能只观察一个东西(或事物)

    /**
     * 事件对象
     * 作用:被观察者发出此事件让观察者来接收并处理
     */
    public class WakeupEvent {
        private long time;
        private String location;
        //事件源对象,将事件源对象传递给观察者
        private Child source;
    
        public WakeupEvent(long time, String location, Child source) {
            this.time = time;
            this.location = location;
            this.source = source;
        }
    
        public long getTime() {
            return time;
        }
    
        public String getLocation() {
            return location;
        }
    
        public Child getSource() {
            return source;
        }
    }
    

    最后让孩子添加被观察者并执行 醒来(wakeUp())方法

    public class Main {
        public static void main(String[] args) {
            Child child = new Child();
            //添加观察者
            child.addObserver(new Mom());
            child.addObserver(new Dad());
            //
            child.wakeUp();
        }
    }
    

    输出如下:

    哪个事件源发出的:class observer.study_01.Child
    妈妈:孩子醒了就喂奶
    给孩子喂奶
    哪个事件源发出的:class observer.study_01.Child
    爸爸:孩子醒了就去打游戏
    打游戏
    

    略微优化:
    我们可以有自己的事件体系,看一下Android中的事件是怎么做的,以onTouchEvent为例,MotionEvent也包含着事件源对象

        @Override
        public boolean onTouchEvent(MotionEvent event) {
            event.getSource();//事件源对象
            return super.onTouchEvent(event);
        }
    

    MotionEvent.java
    这个事件类继承了InputEvent

    public final class MotionEvent extends InputEvent implements Parcelable {
    }
    

    InputEvent.java
    这是一个抽象类,里面有个抽象方法getSource(),不过他的返回值是int 我们可以用泛型T来代替,

    public abstract class InputEvent implements Parcelable {
        public abstract int getSource();
    }
    

    注意什么时候该用抽象类,什么时候该用接口?

    名词 用抽象类,动词用接口

    新建一个所有事件的父类

    /**
     * 所有事件的父类
     * @param <T>   事件源
     */
    public abstract class Event<T> {
        abstract T getSource();
    }
    

    让我们之前的·WakeupEvent.java 继承他

    /**
     * 事件对象
     * 作用:被观察者发出此事件让观察者来接收并处理
     */
    public class WakeupEvent extends Event<Child> {
        private long time;
        private String location;
        //事件源对象,将事件源对象传递给观察者
        private Child source;
    
        public WakeupEvent(long time, String location, Child source) {
            this.time = time;
            this.location = location;
            this.source = source;
        }
    
        public long getTime() {
            return time;
        }
    
        public String getLocation() {
            return location;
        }
    
        @Override
        Child getSource() {
            return source;
        }
    }
    
    

    相关文章

      网友评论

          本文标题:常用的设计模式(笔记)——观察者

          本文链接:https://www.haomeiwen.com/subject/onnvdrtx.html