设计模式之观察者模式(有源码简单实现及java函数简单实现)

2023-04-25 20:45:37
 简介:观察者模式(Observer)完美的将观察者和被观察的对象分离开。举个例子,用户界面可以作为一个观察者,业务数据是被观察者,用户界面观察业务数据的变化,发现数据变化后,就显示在界面上。面向对象设计的一个原则是:系统中的每个类将重点放在某一个功能上,而不是其他方面。一个对象只做一件事情,并且将他做好。观察者模式在模块之间划定了清晰的界限,提高了应用程序的可维护性和重用性。
 观察者设计模式定义了对象间的一种一对多的依赖关系,以便一个对象的状态发生变化时,所有依赖于它的对象都得到通知并自动刷新。
  观察者模式使用的六个重要的方面
  1:确定目标与观察者的之间的关系(是多对一还是一对多等等)
  2:它们之间的关系是单方向依赖(观察者和目标是单向依赖的主动权在目标手中)
  3:命名建议
    (1)目标接口的定义,建议在名称后面跟Subject
    (2)观察者接口定义,建议在名称后面跟Observer
    (3)观察者接口的更新方法,建议在名称为update
  4:触发通知的时机(要在完成数据状态维护之后触发通知,不然会造成通知数据的错误)
  5:观察者模式的调用顺序示意图
  ![这里写图片描述](https://img-blog.csdn.net/20160604095036940)、
  6:通知顺序(多个观察的顺序是平行的,互相不应该存在有依赖关系)

建议以下情况下使用观察者模式
1.当一个抽象模型有俩个方面,其中一个方面的操作依赖与另一个方面的状态变化
2.如果在更改一个对象的时候需要连带修改其他的对象,而且不知道究竟应该有多少对象需要被连带修改
3.当一个对象必须通知其他的对象,但是又希望这个对象和其他被他通知的对象时松散耦合的

这就是观察者模式的一个简单的结构图

这里写图片描述
Attach:是注册观察者
Detach:是删除观察者
Notify:是通知所有的观察者
Update:获取目标类的状态同步到观察者的状态中
这里写图片描述
源码实现拉模型的例子:推模型就是把注释有拉模型的注释掉,把注释有推模型的释放出来
Observer.java


/**
 * @ClassName: Observer
 * @Description: 这是一个观察着的接口  定义一个更新的接口给那些在目标发生改变的时候被通知的对象
 * @author: Administrator
 * @date: 2016年5月31日 下午3:55:32
 */
public interface Observer {

    //观察者自动更新的接口   subject是传入目标对象的状态  方便获取相应的目标对象的状态
    //public void update(WeatherSubject subject);//拉模型
    public void update(String content);//推模型
}

ConcreteWeatherSubject.java



/**
 * @ClassName: ConcreteSubject
 * @Description: 具体的一个目标对象  负责把有关状态存入相应的观察着对象中
 * @author: Administrator
 * @date: 2016年5月31日 下午3:53:53
 */
public class ConcreteWeatherSubject extends WeatherSubject{

    //目标对象的状态信息
    private String weatherContent;

    public String getWeatherContent() {
        return weatherContent;
    }

    public void setWeatherContent(String weatherContent) {
        this.weatherContent = weatherContent;

        //这表示状态发生改变的时候就会通知每一个观察者
        //this.notifyObservers();//拉模型
        this.notifyObservers(weatherContent);//推模型
    }

} 

ConcreteObserver.java



/**
 * @ClassName: ConcreteObserver
 * @Description: 这是一个具体观察者对象  实现更新方法  是自身的状态和目标状态保持一致
 * @author: Administrator
 * @date: 2016年5月31日 下午3:58:20
 */
public class ConcreteObserver implements Observer {
    //观察者的状态名字
    private String observerName;

    //观察者所要知道的信息  这个消息从目标处获取
    private String weatherContent;

    //提醒的内容   不同的观察者要提醒不同的内容
    private String remindThing;

    //获取目标类的状态的同步道观察者的状态中
    @Override
    //public void update(WeatherSubject subject) {//拉模型
    public void update(String content){//推模型
        //weatherContent=((ConcreteWeatherSubject)subject).getWeatherContent();//拉模型
        weatherContent=content;//推模型
        System.out.println(observerName+"收到了"+weatherContent+","+remindThing);
    }

    public String getObserverName() {
        return observerName;
    }

    public void setObserverName(String observerName) {
        this.observerName = observerName;
    }

    public String getWeatherContent() {
        return weatherContent;
    }

    public void setWeatherContent(String weatherContent) {
        this.weatherContent = weatherContent;
    }

    public String getRemindThing() {
        return remindThing;
    }

    public void setRemindThing(String remindThing) {
        this.remindThing = remindThing;
    }
}

WeatherSubject.java

import java.util.ArrayList;
import java.util.List;

/**
 * @ClassName: Subject
 * @Description: 目标对象  它知道观察它的观察着  并提供注册(添加)和删除观察者的接口
 * @author: Administrator
 * @date: 2016年5月31日 下午3:50:47
 */
public class WeatherSubject {
    //用来保存注册的观察者的对象
    private List<Observer> observers = new ArrayList<Observer>();

    //attach detach notifyObervers
    //添加集合观察者
    public void attach(Observer observer){
        observers.add(observer);
    }
    //删除集合中的观察者
    public void detach(Observer observer){
        observers.remove(observer);
    }
    //通知所有注册的观察者对象
//  protected void notifyObservers(){//拉模型
    protected void notifyObservers(String content){//推模型
        for(Observer observer:observers){
            //observer.update(this);//拉模型
            observer.update(content);//推模型
        }
    }
}

测试运行的Client.java


public class Client {
    public static void main(String[] args) {
        //1创建一个目标
        ConcreteWeatherSubject weather = new ConcreteWeatherSubject();

        //2创建观察者
        ConcreteObserver observerGril = new ConcreteObserver();
        observerGril.setObserverName("姚鸿的女朋友");
        observerGril.setRemindThing("第一次约会的地点,大连民族学院南门,不见不散哦");

        ConcreteObserver observerBoy = new ConcreteObserver();
        observerBoy.setObserverName("夏文齐");
        observerBoy.setRemindThing("走,去吃饭");

        //注册观察者
        weather.attach(observerGril);
        weather.attach(observerBoy);

        //4目标发布的天气
        weather.setWeatherContent("没下雨");
    }
}

直接用java的函数实现
这里写图片描述
Client.java


/**
 * @ClassName: Client
 * @Description: 测试类
 * @author: Administrator
 * @date: 2016年5月31日 下午8:34:19
 */
public class Client {
    public static void main(String[] args) {
        //创建天气作为一个目标  也可以说是被观察
        ConcreteWeatherSubject subject = new ConcreteWeatherSubject();
        //创建一个观察者
        ConcreteObserver gril =  new ConcreteObserver();
        gril.setObserverName("小花");
        //创建第二个观察者
        ConcreteObserver boy = new ConcreteObserver();
        boy.setObserverName("兄弟");

        //注册观察者
        subject.addObserver(gril);
        subject.addObserver(boy);

        //目标更新的情况
        subject.setContent("今天天气不错哦");
    }
}

ConcreteObserver.java

import java.util.Observable;
import java.util.Observer;

/**
 * @ClassName: ComcreteObserver
 * @Description: 具体的观察者对象
 * @author: Administrator
 * @date: 2016年5月31日 下午8:29:08
 */
public class ConcreteObserver implements Observer {
    //观察者的名称对象
    private String observerName;

    @Override
    public void update(Observable o, Object arg) {
        //第一种是推的方式
        System.out.println(observerName+"收到了消息,目标推送过来的是"+arg);

        //第二种是拉的方式
        System.out.println(observerName+"收到消息,主动到目标对象中去拉,拉的内容是"+
        ((ConcreteWeatherSubject)o).getContent());
    }

    public String getObserverName() {
        return observerName;
    }

    public void setObserverName(String observerName) {
        this.observerName = observerName;
    }



}

ConcreteWeatherSubject.java

import java.util.Observable;

//天气目标的具体实现类
public class ConcreteWeatherSubject extends Observable{
    //天气情况的内容
    private String content;

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
        //天气情况有了  通知所有的观察者
        //注意通知之前  在用java中的Observer模式的时候  下面的这句话不可少
        this.setChanged();
        //然后主动通知   notifyObservers()不带参数的是拉模型    带参数的推模型
        this.notifyObservers(content);
        //this.notifyObservers();//拉模型
    }
}
  • 作者:学渣之路
  • 原文链接:https://blog.csdn.net/u013412790/article/details/51583133
    更新时间:2023-04-25 20:45:37