Observer模式
2018-07-16 本文已影响117人
吃啥呀
java的设计模式
作用 当观察对象的状态发生变化时,通知给观察者(观察者订阅被观察者的状态)
应用 需要根据对象状态进行相应处理的场景
创建Subject类
package com.company;
import javax.swing.text.html.HTMLDocument;
import java.util.ArrayList;
import java.util.Iterator;
public abstract class Subject{
private ArrayList observers = new ArrayList();//保存Observer们
public void addObserver(Observer observer){
observers.add(observer);
};//注册Obeserver
public void notifyObservers(){
//向Observer发送通知
Iterator it = observers.iterator();
while (it.hasNext()){
Observer observer = (Observer)it.next();
observer.update();
}
}
public abstract int getState();
public abstract void setState();\\写成抽象方法,便于拓展
}
Subject的子类
package com.company;
import java.util.Random;
public class Subjecta extends Subject{
private int number;
private Random random = new Random();
@Override
public int getState() {
return number;
}
@Override
public void setState() {
for(int i = 0 ;i < 10 ;i++){
number = random.nextInt(48);
notifyObservers();
}
}
}
创建抽象Observer类
package com.company;
public abstract class Observer {
protected Subject subject;\\有Subject类的实例化对象,便于获取被观察者的信息
public abstract void update();\\在子类中实现更新的具体操作
}
创建实体观察类
package com.company;
public class Observera extends Observer{
public Observera(Subject subject){
this.subject = subject;
this.subject.addObserver(this);
}
@Override
public void update() {
System.out.println( "Observera : " + subject.getState());
}
}
public class Observerb extends Observer{
public Observerb(Subject subject){
this.subject = subject;
this.subject.addObserver(this);
}
@Override
public void update() {
System.out.print("Observerb : ");
for(int i = 0 ;i< subject.getState();i++) {
System.out.print('-');
}
System.out.println();
}
}
在客户端(Main)使用
package com.company;
public class Main {
public static void main(String[] args) {
Subject subject = new Subjecta();
new Observera(subject);
new Observerb(subject);\\创建观察者
subject.setState();\\设置状态(改变状态)
}
}
另一种实现方法
- 将
抽象Observer类
变为为接口
——ObserverI - Subject的实例化对象
subject
变成接口ObserverI的update()方法的参数
(原来是抽象类Observer的私有成员)
package com.company;
public interface ObserverI {
public abstract void update(Subject subject);
}
- Observer类由抽象类变成了接口,Subject类中添加观察者的方法和向Observer发送通知的方法也应当重写
public abstract class Subject{
private ArrayList observers = new ArrayList();//保存Observer们
public void addObserver(Observer observer){
observers.add(observer);
};//第一种,注册obeserver
public void addObserver(ObserverI observer){
observers.add(observer);
};//第二种方法,注册Obeserver的方式
public void notifyObservers(){
//向Observer发送通知
Iterator it = observers.iterator();
while (it.hasNext()){
Observer observer = (Observer)it.next();
observer.update();
}
}//第一种
public void notifyObservers2(){
//向Observer发送通知
Iterator it = observers.iterator();
while (it.hasNext()){
ObserverI observer = (ObserverI)it.next();
observer.update(this);//改变后的update方法需要传入一个subject进去
}
}//第二种方法
//注意:在状态改变后(setState)应当调用的发送通知的方法也应当换成第二种对应的
}
-
继承
ObserverI接口,实现具体方法
package com.company;
public class ObserverI1 implements ObserverI{
@Override
public void update(Subject subject) {
System.out.println( "Observera : " + subject.getState());
}
}
public class ObserverI2 implements ObserverI{
@Override
public void update(Subject subject) {
System.out.print("Observerb : ");
for(int i = 0 ;i< subject.getState();i++) {
System.out.print('-');
}
System.out.println();
}
}
- 由于ObserverI接口只有抽象方法,在Observer的具体实现类中没有Subject类的实例化对象作为类成员,无法在构造函数中直接添加observer(注册observer),需要在
客户端(Main)添加
//第一种注册observer的方式
public class Observerb extends Observer{
public Observerb(Subject subject){
this.subject = subject;
this.subject.addObserver(this);//改变后
}
}//第一种只要创建了Subject具体实现类的实例化对象,就在被观察者中添加了观察者,
//第二种方法,注册Observer的方式
public class Main {
public static void main(String[] args) {
Subject subject = new Subjecta();
Observer observer1 = new Observera();
Observer observer2 = new Observerb();//创建观察者
subject.addObserver(observer1);
subject.addObserver(observer2);
subject.setState();\\设置状态(改变状态)
}
}//现在,创建观察者后,还需调用被观察者中添加观察者的方法)
注意点
Observer的顺序
Subject角色中有多个Observer角色,在示例代码中是先注册的Observer的update方法先被调用
Observer的行为对Subject的影响
Subject的状态变化 ---> 通知Observer ---> Observer调用Subject的方法 ---> 导致Subject的状态发生变化 ---> 通知Observer
导致方法被循环调用
update方法传入的参数
void update(Subject subject);
void update(int number);
void update(Subject subject,int number);
可以传入Subject实例对象,也可以传入该实例中的某些数据,第一种更加灵活
拓展
java.utill.Observer 接口
java.utill.Observable 类 ——被观察的Subject角色
public void update(Observable obj,Object arg)//Object类的实例是附加信息
缺陷:Subject
角色必须是java.utill.Observable 类的子类
,但是java是单一继承
以上完整的代码上传到了github仓库
https://github.com/chenshuyuhhh/DesignPatternDemo.git