博客网站做外贸可以吗,福州seo按天扣费,哪家公司建网站好,网站不做备案观察者模式 观察者模式也叫作发布-订阅模式#xff0c;也就是事件监听机制。观察者模式定义了一种一对多的依赖关系#xff0c;让多个观察者对象同时监听某一个主题对象#xff0c;这个主题对象在状态上发生变化时#xff0c;会通知所有观察者对象#xff0c;使他们能够自… 观察者模式 观察者模式也叫作发布-订阅模式也就是事件监听机制。观察者模式定义了一种一对多的依赖关系让多个观察者对象同时监听某一个主题对象这个主题对象在状态上发生变化时会通知所有观察者对象使他们能够自动更新自己。 观察者模式的结构 一个软件系统常常要求在某一个对象状态发生变化时某些其他的对象作出相应的改变。能做到这一点的设计方案有很多但是为了使系统能够易于复用应该选择低耦合度的设计方案。减少对象之间的耦合有利于系统的复用但是同时需要使这些低耦合度的对象之间能够维持行动的协调一致保证高度的协作。观察者模式是满足这一要求的各种设计方案中最重要的一种。 观察者模式所涉及的角色有 1、抽象主题角色 抽象主题角色把所有对观察者对象的引用保存在一个集合中每个主题都可以有任意数量的观察者。抽象主题提供一个接口可以增加和删除观察者对象。 2、具体主题角色 将有关状态存入具体观察者对象在具体主题的内部状态改变时给所有登记过的观察者发出通知。 3、抽象观察者角色 为所有的具体观察者提供一个接口在得到主题通知时更新自己 4、具体观察者角色 存储与主题的状态相关的状态。具体观察者角色实现抽象观察者角色所要求的更新接口以便使本身的状态与主题的状态协调 观察者模式实例 抽象主题角色有增加观察者、删除观察者、通知观察者的功能 登录后复制 public abstract class Subject
{/** 用来保存注册的观察者对象 */private ListObserver list new ArrayListObserver();/** 注册观察者对象 */public void attch(Observer observer){list.add(observer);System.out.println(Attached an observer);}/** 删除观察者对象 */public void detach(Observer observer){list.remove(observer);System.out.println(Detached an observer);}/** 通知所有注册的观察者对象 */public void notifyObservers(String newState){for (int i 0; i list.size(); i){list.get(i).update(newState);}}
} 1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.22.23.24.25.26.27.28. 具体主题角色这个change方法放在子类中是因为可能不同的主题在改变观察者状态的时候会做一些不同的操作因此就不统一放在父类Subject里面了 登录后复制 public class ConcreteSubject extends Subject
{private String state;public String getState(){return state;}public void change(String newState){state newState;System.out.println(主题状态为 state);// 状态发生改变时通知各个观察者this.notifyObservers(state);}
} 1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18. 观察者接口 登录后复制 public interface Observer
{void update(String state);
} 1.2.3.4. 具体观察者实现了观察者接口 登录后复制 public class ConcreteObserver implements Observer
{/** 观察者的状态 */private String observerState;public void update(String state){/** 更新观察者的状态 */observerState state;System.out.println(状态为 observerState);}
} 1.2.3.4.5.6.7.8.9.10.11.12. 客户端调用代码一旦主题调用了change方法改变观察者的状态那么观察者Observer里面的observerState全都改变了 登录后复制 public static void main(String[] args)
{/** 创建主题角色 */ConcreteSubject subject new ConcreteSubject();/** 创建观察者对象 */Observer observer new ConcreteObserver();/** 将观察者注册到主题对象上 */subject.attch(observer);/** 改变主题对象的状态 */subject.change(new state);
} 1.2.3.4.5.6.7.8.9.10.11.12.13.14. 运行结果为 登录后复制 Attached an observer
主题状态为new state
状态为new state 1.2.3. 这里只添加了一个观察者有兴趣的可以试试看多添加几个观察者效果都是一样的主题角色改变状态观察者状态全变。 观察者模式的两种模型 1、推模型 主题对象向观察者推送主题的详细信息不管观察者是否需要。推送的信息通常是主题对象的全部或部分数据上面的例子就是典型的推模型 2、拉模型 主题对象在通知观察者的时候只传递少量信息。如果观察者需要更具体的信息由观察者主动到主题对象中去获取相当于是观察者从主题对象中拉数据。一般这种模型的实现中会把主题对象自身通过update()方法传递给观察者这样观察者在需要获取数据的时候就可以通过这个引用来获取了。 两种模型的比较 1、推模型是假设主题对象知道观察者需要的数据拉模型是假设主题对象不知道观察者需要什么数据干脆把自身传递过去让观察者自己按需要取值 2、推模型可能会使得观察者对象难以复用因为观察者的update()方法是按需要定义的参数可能无法兼顾到没有考虑到的使用情况这意味着出现新的情况时可能要提供新的update()方法 观察者模式在Java中的应用及解读 JDK是有直接支持观察者模式的就是java.util.Observer这个接口 登录后复制 public interface Observer {/*** This method is called whenever the observed object is changed. An* application calls an ttObservable/tt objects* codenotifyObservers/code method to have all the objects* observers notified of the change.** param o the observable object.* param arg an argument passed to the codenotifyObservers/code* method.*/void update(Observable o, Object arg);
} 1.2.3.4.5.6.7.8.9.10.11.12.13. 这就是观察者的接口定义的观察者只需要实现这个接口就可以了。update()方法被观察者对象的状态发生变化时被观察者的notifyObservers()方法就会调用这个方法 登录后复制 public class Observable {private boolean changed false;private Vector obs;/** Construct an Observable with zero Observers. */public Observable() {obs new Vector();}/*** Adds an observer to the set of observers for this object, provided * that it is not the same as some observer already in the set. * The order in which notifications will be delivered to multiple * observers is not specified. See the class comment.** param o an observer to be added.* throws NullPointerException if the parameter o is null.*/public synchronized void addObserver(Observer o) {if (o null)throw new NullPointerException();if (!obs.contains(o)) {obs.addElement(o);}}...
} 1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.22.23.24.25.26.27.28. 这是被观察者的父类也就是主题对象。这是一个线程安全的类是基于Vector实现的。主题对象中有这些方法对观察者进行操作 方 法作 用addObserver(Observer o)如果观察者与集合中已有的观察者不同则向对象的观察者集合中添加此观察者clearChanged()、hasChanged()、setChanged()这三个方法算是一对用来标记此观察者对象(主题对象)是否被改变的状态的countObservers()返回观察者对象的数目deleteObserver(Observer o)从对象的观察者集合中删除某个观察者deleteObservers()清除观察者列表notifyObservers()、notifyObservers(Object arg)如果本对象有变化则通知所有等级的观察者调用update()方法 利用JDK支持的主题/观察者的例子 创建一个观察者 登录后复制 public class Watched extends Observable
{private String data ;public String getData(){return data;}public void setData(String data){if (!this.data.equals(data)){this.data data;setChanged();}notifyObservers();}
} 1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19. 创建一个主题 登录后复制 public class Watcher implements Observer
{String data;public Watcher(Observable o){o.addObserver(this);}public String getData(){return data;}public void update(Observable o, Object arg){this.data ((Watched)o).getData();System.out.println(状态发生改变 ((Watched)o).getData());}
} 1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20. 写一个main函数调用一下 登录后复制 public static void main(String[] args)
{/** 创建被观察者对象 */Watched watched new Watched();/** 创建观察者对象并将被观察者对象登记 */Watcher watcher new Watcher(watched);/** 给被观察者状态赋值 */watched.setData(start);watched.setData(run);watched.setData(stop);
} 1.2.3.4.5.6.7.8.9.10.11.12.13. 运行结果为 登录后复制 状态发生改变start
状态发生改变run
状态发生改变stop 1.2.3. 看到主题对象改变的时候观察者对象的状态也随之改变 观察者模式的优点以及实际应用 引入设计模式最主要的作用我认为就是两点 1、去重复代码使得代码更清晰、更易读、更易扩展 2、解耦使得代码可维护性更好修改代码的时候可以尽量少改地方 使用观察者模式可以很好地做到这两点。增加观察者直接new出观察者并注册到主题对象之后就完事了删除观察者主题对象调用方法删除一下就好了其余都不用管。主题对象状态改变内部会自动帮我们通知每一个观察者是不是很方便呢 观察者模式主要应用场景有 1、对一个对象状态的更新需要其他对象同步更新 2、对象仅需要将自己的更新通知给其他对象而不需要知道其他对象的细节如消息推送