• 设计模式之观察者模式(Observer pattern)


    最近参加了一次面试,其中笔试题有一道编程题,在更换掉试题的描述场景后,大意如下:

    上课铃声响起,学生A/B/C/D进入教室;下课铃声响起,学生A/B/C/D离开教室。

    要求使用设计模式的思想完成铃与学生两个类的解耦并画出UML类图。

    看到这道题之后自己第一时间便想到了装饰器模式,定义一个装饰类继承铃的接口,在上课铃与下课铃的接口中添加学生们的动作,UML类图如下:

    最后的确做到了解耦,但总觉得与装饰器模式的应用场景不太匹配,最后面试官给了个提示——观察者模式——于是豁然开朗,本题的场景毫无疑问更适合使用观察者模式来解决,观察者模式定义对象间的一种一对多依赖关系,使得每当一个对象状态发生改变时,其相关依赖对象皆得到通知并被自动更新

    该道题使用观察者模式的UML类图如下:

    实现代码如下(Java:jdk1.8.0_144):

    import java.util.Observable;
    
    public abstract class IBell extends Observable {
        public enum State {
            上课, 下课
        }
    
        public abstract void firstRing();
    
        public abstract void secondRing();
    }
    public class Bell extends IBell {
    
        @Override
        public void firstRing() {
            System.out.println("上课铃响了!!!");
            super.setChanged();// 修改对象状态才能触发观察者的通知事件
            this.notifyObservers(State.上课);
        }
    
        @Override
        public void secondRing() {
            System.out.println("下课铃响了!!!");
            super.setChanged();// 修改对象状态才能触发观察者的通知事件
            this.notifyObservers(State.下课);
        }
    
    }
    import java.util.Observable;
    import java.util.Observer;
    
    import org.lxp.dailylog.web.util.IBell.State;
    
    public abstract class IStudent implements Observer {
        public abstract void enterClassRoom();
    
        public abstract void leaveClassRoom();
    
        @Override
        public void update(Observable o, Object arg) {
            switch (State.valueOf(arg.toString())) {
            case 上课:
                enterClassRoom();
                break;
            case 下课:
                leaveClassRoom();
                break;
            }
        }
    
    }
    public class Student extends IStudent {
        private String name;
    
        public Student(String name) {
            this.name = name;
        }
    
        @Override
        public void enterClassRoom() {
            System.out.println("Student " + this.name + " enters classroom");
        }
    
        @Override
        public void leaveClassRoom() {
            System.out.println("Student " + this.name + " leaves classroom");
        }
    }
    public class Test {
    
        public static void main(String[] args) {
            Student A = new Student("A");
            Student B = new Student("B");
            Student C = new Student("C");
            Student D = new Student("D");
            Bell bell = new Bell();
            bell.addObserver(D);
            bell.addObserver(C);
            bell.addObserver(B);
            bell.addObserver(A);
            bell.firstRing();
            bell.secondRing();
        }
    
    }

    输出结果如下:

  • 相关阅读:
    Flask—09-项目部署(01)
    Flask—08-建立自己的博客(02)
    Flask—07-建立自己的博客(01)
    Day 22:网络编程(3)
    Day 21:网络编程(2)
    Day 20:网络编程(1)
    Day 19:Properties配置文件类、打印流(printStream) 、 编码与解码
    Day 18:SequenceInputStream、合并切割mp3、对象输入输出流对象
    Day 17:缓冲输出字符流和用缓冲输入输出实现登录、装饰者设计模式
    Day 16:输入输出字符流、缓冲输入字符流
  • 原文地址:https://www.cnblogs.com/hiver/p/7441028.html
Copyright © 2020-2023  润新知