寫一個觀察者模式程序:
public class Program {
public static void main(String[] args) {
Secretary tongzizhe = new Secretary();
// 看股票的同事
Observer tongshi1 = new StockObserver("小君", tongzizhe);
Observer tongshi2 = new NBAObserver("小海", tongzizhe);
// 前臺記下了兩位同事
tongzizhe.attach(tongshi1);
tongzizhe.attach(tongshi2);
// 發現老闆回來
tongzizhe.setAction("老闆回來了");
// 通知兩個同事
tongzizhe.notifyObserver();
}
}
interface Subject {
void attach(Observer observer);
void remove(Observer observer);
void notifyObserver();
}
class Secretary implements Subject{
// 同事列表
private List<Observer> observerList = new ArrayList<Observer>();
private String action;
// 增加
public void attach(Observer observer) {
observerList.add(observer);
}
// 移除
public void remove(Observer observer) {
observerList.remove(observer);
}
// 通知
public void notifyObserver() {
for (Observer observer : observerList) {
observer.update();
}
}
public String getAction() {
return action;
}
public void setAction(String action) {
this.action = action;
}
}
abstract class Observer {
protected String name;
protected Secretary sub;
public Observer(String name, Secretary sub) {
this.name = name;
this.sub = sub;
}
public abstract void update();
}
class StockObserver extends Observer{
public StockObserver(String name, Secretary sub) {
super(name, sub);
}
@Override
public void update() {
System.out.println(sub.getAction()+name+"關閉股市行情,繼續工作!");
}
}
class NBAObserver extends Observer {
public NBAObserver(String name, Secretary sub) {
super(name, sub);
}
@Override
public void update() {
System.out.println(sub.getAction()+name+"關閉NBA直播,繼續工作!");
}
}
觀察者模式的優缺點
優點
很好地解耦了通知者與觀察者,觀察者不需要了解通知者內部是怎樣實現的,方便於日後代碼的修改,體現了 依賴倒轉的原則。
缺點分析:
分析:
- “上面該機的代碼中抽象通知者還是依賴了抽象觀察者,萬一沒有抽象觀察者,那豈不是功能都完成不了啦!
- 還有你這上面代碼寫的,所以對象更新的動作都一樣的。萬一我對象更新不一樣呢?比如,看NBA球賽的聽見班主任來了就跑去上廁所,而看漫畫的聽見班主任來了就繼續看書。代碼又應該怎麼寫呢?”小A,揉了揉惺忪的睡眼,疑惑地問道。
- 小B說:“我去,我還以爲你睡着了呢!原來你在聽啊!我太高興了。下面我們就利用一種叫做“事件委託”的東東去解決這個問題哈!”
- 小A說:“我滴個神,什麼叫事件委託啊?”
解決方法
1.解決方法,使用事件委託
當觀察者不實現Observer的時候,要採用事件委託。
public class Program {
public static void main(String[] args) {
Secretary tongzizhe = new Secretary();
// 看股票的同事
Observer tongshi1 = new StockObserver("小君", tongzizhe);
NBAObserver tongshi2 = new NBAObserver("小海", tongzizhe);
// 前臺記下了兩位同事
tongzizhe.addListener(tongshi1, "update");
tongzizhe.addListener(tongshi2, "closeNBA");
// 發現老闆回來
tongzizhe.setAction("老闆回來了");
// 通知兩個同事
tongzizhe.notifyObserver();
}
}
class Event{
// 要執行方法的對象
private Object object;
// 要執行方法的名稱
private String methodName;
// 要執行方法的參數
private Object[] params;
// 要執行方法的參數類型
private Class[] paramTypes;
public Event(){}
public Event(Object object, String methodName,Object...args){
this.object = object;
this.methodName = methodName;
this.params = args;
contractParamTypes(this.params);
}
//根據參數數組生成參數類型數組
private void contractParamTypes(Object[] params){
this.paramTypes = new Class[params.length];
for(int i = 0; i < params.length; i++){
this.paramTypes[i] = params[i].getClass();
}
}
public Object getObject() {
return object;
}
/**
* 根據該對象的方法名,方法參數,利用反射機制,執行該方法
* @throws Exception
*/
public void invoke() throws Exception{
Method method = object.getClass().getMethod(this.getMethodName(), this.getParamTypes());
if(null == method){
return;
}
method.invoke(this.getObject(), this.getParams());
}
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[] getParamTypes() {
return paramTypes;
}
public void setParamTypes(Class[] paramTypes) {
this.paramTypes = paramTypes;
}
}
class EventHandler {
private List<Event> objects;
public EventHandler(){
objects = new ArrayList<>();
}
public void addEvent(Object object, String methodName,Object...args){
objects.add(new Event(object, methodName, args));
}
//通知所有的對象執行指定的事件
public void notifyX() throws Exception{
for(Event e : objects){
e.invoke();
}
}
}
abstract class Subject {
private EventHandler eventHandler = new EventHandler();
private String action;
public EventHandler getEventHandler() {
return eventHandler;
}
public void setEventHandler(EventHandler eventHandler) {
this.eventHandler = eventHandler;
}
public String getAction() {
return action;
}
public void setAction(String action) {
this.action = action;
}
abstract void addListener(Object object, String methodName,
Object... args);
abstract void notifyObserver();
}
class Secretary extends Subject{
@Override
void addListener(Object object, String methodName, Object... args) {
EventHandler handler = this.getEventHandler();
handler.addEvent(object, methodName, args);
}
@Override
void notifyObserver() {
try {
this.getEventHandler().notifyX();
} catch (Exception e) {
e.printStackTrace();
}
}
}
abstract class Observer {
protected String name;
protected Subject sub;
public Observer(String name, Subject sub) {
this.name = name;
this.sub = sub;
}
public abstract void update();
}
class StockObserver extends Observer{
public StockObserver(String name, Subject sub) {
super(name, sub);
}
@Override
public void update() {
System.out.println(sub.getAction()+name+"關閉股市行情,繼續工作!");
}
}
class NBAObserver{
protected String name;
protected Subject sub;
public NBAObserver(String name, Subject sub) {
this.name = name;
this.sub = sub;
}
public void closeNBA() {
System.out.println(sub.getAction()+name+"關閉NBA直播,繼續工作!");
}
}