代码解释很全面,复制到IDE中,可以更方便查看如何使用的
包含观察者,被观察者以及使用者
祝君早日掌握
本来想改一下这样的写法的,但想来想去还是这样好,最原始的的observer用法
package observe;
import java.util.Observable;
import java.util.Observer;
//TODO 总体流程:先执行具体类中的——————引用自observer的抽象change方法,
// 在执行observer中的update方法,
// 最后执行Observable中的具体设计接口,
// 被观察者通知观察者的循序是遵循“先订阅loginOutObservable.addObserver(loginoutObserver1);
// loginOutObservable.addObserver(loginoutObserver3);
// loginOutObservable.addObserver(loginoutObserver2);
// 后通知 loginOutObservable.setLoginOut(true);”的循序,
//TODO 总结:1、观察者
//(Observer)将自己注册到被观察对象(Subject)中,被观察对象将观察者存放在一个容器(Container)里。
//
//2、被观察对象
//被观察对象发生了某种变化,从容器中得到所有注册过的观察者,将变化通知观察者。
public class observer {
//TODO 总体说明:
// Android中的观察者需要实现Observer接口,当数据发生改变时,观察者的update()方法就会被调用,被观察者继承Observable类,
// 在数据发生改变时,需要调用setChanged(); this.notifyObservers(obj);这两个方法才可以通知观察者,
//TODO 被观察者
public abstract class LoginOutObservable extends Observable {
private String userName = "admin";
/**
* 设置是否登出,如果是,则需要通知观察者
*
* @param isLoginOut isLoginOut
*/
public void setLoginOut(boolean isLoginOut) {
if (isLoginOut) {
String data = "被观察者告诉你:你已经退出登录,请重新登录!";
/* 注意注意注意:下面这两个方法是要同时调用的,否则不会通知观察者数据发生了变化 */
setChanged();
this.notifyObservers(data);
onUserLoginOut("这是在被观察者内部调用的方法:" + data);
}
}
/**
* 设置用户名,如果用户名和上次的不一样,则需要通知观察者
*
* @param name name
*/
public void setUserName(String name) {
if (!name.equals(userName)) {
this.userName = name;
String data = "被观察者告诉你:用户名已经改变了!新的名字为:" + name;
/* 注意注意注意:下面这两个方法是要同时调用的,否则不会通知观察者数据发生了变化 */
setChanged();
this.notifyObservers(data);
//TODO 执行完所有订阅之后才去执行
onUserNameChanged("这是在被观察者内部调用的方法:" + data);
}
}
/**
* 当用户名字发生改变时,用于在本类中将数据打印出来
* <p>
* 感悟:
* 抽象方法,凡是继承此类的子类,都需要重写此方法
* 但是我们可以再本类里调用此方法,然后实例化此类的时候,要求实现类实现本类里头的抽象方法
*
* @param newUserName
*/
public abstract void onUserNameChanged(String newUserName);
/**
* 当用户登出时,在本类中用于将数据打印出来
* <p>
* 感悟:
* 抽象方法,凡是继承此类的子类,都需要重写此方法
* 但是我们可以再本类里调用此方法,然后实例化此类的时候,要求实现类实现本类里头的抽象方法
*
* @param message message
*/
public abstract void onUserLoginOut(String message);
}
//TODO 观察者
public abstract class LoginoutObserver implements Observer {
@Override
public void update(Observable o, Object arg) {
/* 当被观察者因为数据发生了改变,并通知了相关的观察者后,观察者将会调用此方法进行相应
* 我们这里调用的是本地的抽象方法进行数据输出 */
onDataChanged("观察者从被观察者中的消息:", arg);
}
/**
* 这里给出一个抽象方法给实现类实现,然后我们会在updat()方法被调用的时候,调用这个方法,给实现类相应
*
* @param message message
* @param object object
*/
public abstract void onDataChanged(String message, Object object);
}
public void observerTest() {
/* 被观察者:登出/修改用户名类,实例 */
LoginOutObservable loginOutObservable = new LoginOutObservable() {
@Override
public void onUserNameChanged(String newUserName) {
printer(newUserName);
}
@Override
public void onUserLoginOut(String message) {
printer(message);
}
};
/*观察者1:并实现了观察者类的抽象方法,实现在这里进行数据的打印输出 */
LoginoutObserver loginoutObserver1 = new LoginoutObserver() {
@Override
public void onDataChanged(String message, Object object) {
printer("我是观察者1-->" + message + "," + object.toString());
}
};
/*观察者2:并实现了观察者类的抽象方法,实现在这里进行数据的打印输出 */
LoginoutObserver loginoutObserver2 = new LoginoutObserver() {
@Override
public void onDataChanged(String message, Object object) {
printer("我是观察者2-->message:" + message + "," + object.toString());
}
};
LoginoutObserver loginoutObserver3 = new LoginoutObserver() {
@Override
public void onDataChanged(String message, Object object) {
printer("我是观察者3-->message:" + message + "," + object.toString());
}
};
/**
* 这里像是被观察者订阅了观察者,看起来是有点别扭的哈;
* 就像和反射里面调用invoke方法:method.invoke(obj, args);
* 具体可以参考这篇文章:
* 但是不要被混淆了,最好记的一点就是:外国人说话看起来都是和中文"反过来"的
*/
loginOutObservable.addObserver(loginoutObserver1);
loginOutObservable.addObserver(loginoutObserver3);
loginOutObservable.addObserver(loginoutObserver2);
/* 这里是模拟被观察者登出操作,登出了必须要通知用户重新登录啊 */
loginOutObservable.setLoginOut(true);
/* 这里是模拟被观察者修改了用户名操作,导致前后用户名不一致而引起数据变化了 */
loginOutObservable.setUserName("tanksu");
}
public void printer(String content) {
System.out.println(content);
}
}