14 观察者模式

参考
https://blog.csdn.net/caoxiaohong1005/article/details/79019706

1 准确定义

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

2 使用的意义

讲一个系统分割成一系列相互协作的类有一个不好的副作用,那就是需要维护相关对象的一致性。我们不希望为了维持一致性而使得各类紧密耦合,这样会给维护、扩展、重用带来不便。而观察者模式的关键对象是主题Subject和观察者Observer,一个Subject可以有多个依赖它的Observer,一旦Subject发生变化,所有的Observer都可以得到通知。
3、适用场景
3.1、当一个对象的改变需要同时改变其它对象。
3.2、这个对象并不知道它需要同时改变多少个依赖它的对象。
4、UML图
在这里插入图片描述
5、例子
5.1UML图
在这里插入图片描述
5.2、code

Client

package designmodel.fourteenthchapter;
 
/**
 * @Author: cxh
 * @CreateTime: 18/1/10 09:08
 * @ProjectName: JavaBaseTest
 */
public class Client {
    public static void main(String[] args) {
        Boss boss=new Boss();
        NBAObserver nbaObserver=new NBAObserver("李明浩",boss);
        TVObserver tvObserver=new TVObserver("李沁",boss);
        //add
        boss.add(nbaObserver);
        boss.add(tvObserver);
        //delete
 
        //boss状态转变,通知观察者
        boss.setSubjetctState("领导回来了");
        boss.notifyObservers();
    }
}

Subject

package designmodel.fourteenthchapter;
 
/**
 * @Author: cxh
 * @CreateTime: 18/1/9 23:29
 * @ProjectName: JavaBaseTest
 */
public abstract class Subject {
    abstract void add(Observer observer);
    abstract void delete(Observer observer);
    abstract void notifyObservers();
    private String subjetctState;
 
    //获取主题状态
    public String getSubjetctState() {
        return subjetctState;
    }
    //设置主题状态
    public void setSubjetctState(String subjetctState) {
        this.subjetctState = subjetctState;
    }
}

Boss

package designmodel.fourteenthchapter;
 
import java.util.ArrayList;
import java.util.List;
 
/**
 * @Author: cxh
 * @CreateTime: 18/1/10 09:11
 * @ProjectName: JavaBaseTest
 */
public class Boss extends Subject{
    private List<Observer> list=new ArrayList<>();
 
    //增加观察者
    public void add(Observer observer){
        list.add(observer);
    }
    //删除观察者
    public void delete(Observer observer){
        list.remove(observer);
    }
    //通知
    public void notifyObservers(){
        for(Observer s:list)
            s.update();
    }
}

Observer

package designmodel.fourteenthchapter;
 
/**
 * @Author: cxh
 * @CreateTime: 18/1/9 23:17
 * @ProjectName: JavaBaseTest
 */
public interface Observer {
    void update();
}

NBAObserver

package designmodel.fourteenthchapter;
 
/**
 * @Author: cxh
 * @CreateTime: 18/1/9 23:28
 * @ProjectName: JavaBaseTest
 */
public class NBAObserver implements Observer {
    private Subject subject;//关注主题
    private String name;//观察者名字
    public NBAObserver(String name,Subject subject){//参数Subject体现了:具体依赖抽象原则
        this.name=name;
        this.subject=subject;
    }
 
    @Override
    public void update() {
        System.out.println(subject.getSubjetctState()+","+name+","+"快继续工作~");
    }
}

TVObserver

package designmodel.fourteenthchapter;
 
/**
 * @Author: cxh
 * @CreateTime: 18/1/9 23:45
 * @ProjectName: JavaBaseTest
 */
public class TVObserver implements Observer {
    private String name;//看电视的人名字
    private Boss subject;//主题
    public TVObserver(String name,Boss subject){
        this.name=name;
        this.subject=subject;
    }
 
    @Override
    public void update() {
        System.out.println(subject.getSubjetctState()+","+name+","+"快继续工作~");
    }
}

输出:

领导回来了,李明浩,快继续工作~
领导回来了,李沁,快继续工作~
 
Process finished with exit code 0

6 观察者模式不足

  • 抽象通知者仍然依赖抽象观察者
  • 每个具体观察者被通知时,通知方法名必须一样,而实际中很难一样

7 优化观察者模式:事件委托实现

  • 事件委托解决的问题:一个委托可以搭载多个方法,所有方法被一次唤起。更重要的是委托可以使得委托对象所搭载的方法并不属于同一个类,从而实现通知者和抽象观察者解耦。
  • 委托是什么:是一种引用方法的类型。一旦为委托分配了方法,则委托和该方法拥有完全相同的行为。委托方法的使用可以和其它任何方法一样,具有参数和返回值。委托可以看作是对函数的抽象 ,是函数的“类”,委托的实例将代表一个具体的函数。
  • 委托实质:用反射来实现。
  • 委托事件的前提:委托对象所搭载的所有方法必须具有相同的原形和形式,也就是拥有相同的参数列表和返回值类型。

8 委托代码实现观察者模式

8.1 应用场景

办公室里面有两类同事:
(1) 看NBA赛事直播的男人们 & 看电视剧的女人们。
(2) 通知忙里偷闲的同事,即:领导回来消息的岗哨。
通过使用委托,实现观察者中岗哨和观察者之间解耦。

8.2 code

Client

package designmodel.delegate;
 
import java.util.Date;
 
/**
 * @Author: cxh
 * @CreateTime: 18/1/12 16:40
 * @ProjectName: JavaBaseTest
 */
public class Client {
    public static void main(String[] args) {
        //观察者.  创建时起,开始做自己的事情
        NBAObserver nbaObserver=new NBAObserver();
        TVObserver tvObserver=new TVObserver();
        //主题(通知者)
        NotifierA notifierA=new NotifierA();
 
        //为主题添加观察者
        notifierA.addListener(nbaObserver,"stopWatchingNBA",new Date());
        notifierA.addListener(tvObserver,"stopWatchingTV",new Date());
 
        //主题状态改变,通知观察者
        notifierA.notifyX();
    }
}

Event

package designmodel.delegate;
 
import java.lang.reflect.Method;
 
/**
 * @Author: cxh
 * @CreateTime: 18/1/10 23:29
 * @ProjectName: JavaBaseTest
 */
public class Event{
    //要执行方法的对象
    private Object object;
    //要执行的方法名称
    private String methodName;
    //要执行方法的参数
    private Object[] params;
    //要执行方法的参数类型
    private Class[] paramType;
 
    //两个构造函数
    public Event(){}
    public Event(Object object,String methodName,Object... args){
        this.object=object;
        this.methodName=methodName;
        this.params=args;
        //获取参数类型
        getParaTypes(args);
    }
    private void getParaTypes(Object[] params){
        int size=params.length;
        this.paramType=new Class[size];//4个私有变量,只有这个变量实现了深拷贝
        for(int i=0;i<size;i++)
            paramType[i]=params[i].getClass();
    }
 
    //执行该对象的方法
    public void invoke() throws Exception{
        Method method=object.getClass().getMethod(getMethodName(),getParamType());
        if(null==method)
            return;
        method.invoke(getObject(),getParams());
    }
 
    //get,set方法
    public Object getObject() {
        return object;
    }
 
    public void setObject(Object object) {
        this.object = object;
    }
 
    public String getMethodName() {
        return methodName;
    }
 
    public void setMethodName(String methodName) {
        this.methodName = methodName;
    }
 
    public Object[] getParams() {
        return params;
    }
 
    public void setParams(Object[] params) {
        this.params = params;
    }
 
    public Class[] getParamType() {
        return paramType;
    }
 
    public void setParamType(Class[] paramType) {
        this.paramType = paramType;
    }
}

EventHandler

package designmodel.delegate;
 
import java.util.ArrayList;
import java.util.List;
 
/**
 * @Author: cxh
 * @CreateTime: 18/1/12 11:23
 * @ProjectName: JavaBaseTest
 */
public class EventHandler {
    //保存了很多event的引用
    private List<Event> objects;
    public EventHandler(){
        objects=new ArrayList<>();
    }
 
    //添加某个event
    public void addEvent(Object object,String name,Object... args){
        objects.add(new Event(object,name,args));
    }
    //触发所有引用的event
    public void notifyEvents() throws Exception{
        for(Event e:objects)
            e.invoke();
    }
}

NBAObserver

package designmodel.delegate;
 
import java.util.Date;
 
/**
 * @Author: cxh
 * @CreateTime: 18/1/12 16:30
 * @ProjectName: JavaBaseTest
 */
public class NBAObserver{
    public NBAObserver(){
        System.out.println("正在观看NBA比赛!当前时间为:"+new Date());
    }
    public void stopWatchingNBA(Date date){
        System.out.println("领导回来了,快关闭NBA赛事直播!当前时间为:"+date);
    }
}

TVObserver

package designmodel.delegate;
 
import java.util.Date;
 
/**
 * @Author: cxh
 * @CreateTime: 18/1/12 16:37
 * @ProjectName: JavaBaseTest
 */
public class TVObserver {
    public TVObserver(){
        System.out.println("正在观看电视剧<<甄嬛传>>,当前时间为:"+new Date());
    }
    public void stopWatchingTV(Date date){
        System.out.println("领导回来了,快关闭电视剧播放.当前时间为:"+date);
    }
}

Notifier

package designmodel.delegate;
 
/**
 * @Author: cxh
 * @CreateTime: 18/1/12 11:36
 * @ProjectName: JavaBaseTest
 */
public abstract class Notifier {
    private EventHandler eventHandler=new EventHandler();
    //增加需要帮忙放哨的同事
    public abstract void addListener(Object object,String name,Object... args);
    //告诉所有需要帮忙放哨的同事:领导回来啦
    public abstract void notifyX();
 
    //get,set
    public EventHandler getEventHandler() {
        return eventHandler;
    }
 
    public void setEventHandler(EventHandler eventHandler) {
        this.eventHandler = eventHandler;
    }
}

NotifierA

package designmodel.delegate;
 
/**
 * @Author: cxh
 * @CreateTime: 18/1/12 16:13
 * @ProjectName: JavaBaseTest
 */
public class NotifierA extends Notifier{
 
    @Override
    public void addListener(Object object, String name, Object... args) {
        getEventHandler().addEvent(object,name,args);
    }
 
    @Override
    public void notifyX(){
        try{
            getEventHandler().notifyEvents();
        }catch (Exception e){
            System.out.println("通知同事时出错!!!");
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
智慧校园建设方案旨在通过融合先进技术,如物联网、大数据、人工智能等,实现校园的智能化管理与服务。政策的推动和技术的成熟为智慧校园的发展提供了基础。该方案强调了数据的重要性,提出通过数据的整合、开放和共享,构建产学研资用联动的服务体系,以促进校园的精细化治理。 智慧校园的核心建设任务包括数据标准体系和应用标准体系的建设,以及信息化安全与等级保护的实施。方案提出了一站式服务大厅和移动校园的概念,通过整合校内外资源,实现资源共享平台和产教融合就业平台的建设。此外,校园大脑的构建是实现智慧校园的关键,它涉及到数据中心化、数据资产化和数据业务化,以数据驱动业务自动化和智能化。 技术应用方面,方案提出了物联网平台、5G网络、人工智能平台等新技术的融合应用,以打造多场景融合的智慧校园大脑。这包括智慧教室、智慧实验室、智慧图书馆、智慧党建等多领域的智能化应用,旨在提升教学、科研、管理和服务的效率和质量。 在实施层面,智慧校园建设需要统筹规划和分步实施,确保项目的可行性和有效性。方案提出了主题梳理、场景梳理和数据梳理的方法,以及现有技术支持和项目分级的考虑,以指导智慧校园的建设。 最后,智慧校园建设的成功依赖于开放、协同和融合的组织建设。通过战略咨询、分步实施、生态建设和短板补充,可以构建符合学校特色的生态链,实现智慧校园的长远发展。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值