23種設計模式之觀察者模式程式碼demo
阿新 • • 發佈:2020-12-21
定義:觀察者模式定義了物件之間一對多的依賴,讓多個觀察者物件同時監聽
,一個主體物件,當主體物件發生變化時,它的所有依賴者(觀察者)都會受到通知並更新,屬於行為型模式。
觀察者模式有時也叫做釋出訂閱模式。觀察者模式主要用於在關聯行為之間建立一套觸發機制的場景。
懶人原始碼:
掃描下面二維碼關注公眾號: 程式設計師修煉寶典 ,回覆:觀察者模式 獲取原始碼
java原始碼模擬朋友圈動態通知:
public class GPer extends Observable { private String name = "新野酒會"; private static GPer gPer = null; private GPer() {} public String getName() { return name; } public static GPer getInstance() { if (gPer == null) { gPer = new GPer(); } return gPer; } public void publishQuestion(Question question) { System.out.println(question.getUserName() + "在" + this.name + "上提交了一個問題。"); setChanged(); notifyObservers(question); } } public class Question { private String userName; private String content; public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public String getContent() { return content; } public void setContent(String content) { this.content = content; } } public class Teacher implements Observer { private String name; public Teacher(String name) { this.name = name; } public void update(Observable o, Object arg) { GPer gPer = (GPer) o; Question question = (Question) arg; System.out.println("=========================="); System.out.println(name + "老師,您好!\n" + "您收到了一份來自“" + gPer.getName() + "”的提問,希望您解答,問題內容如下:\n" + question.getContent() + "\n" + "提問者:" + question.getUserName()); } }
public class MainTest { public static void main(String[] args) { GPer gPer = GPer.getInstance(); Teacher lone = new Teacher("臥龍"); Teacher bird = new Teacher("鳳雛"); gPer.addObserver(lone); gPer.addObserver(bird); //業務邏輯程式碼 Question question = new Question(); question.setContent("臥龍鳳雛得一可得天下?"); question.setUserName("劉備"); gPer.publishQuestion(question); } }
2.使用觀察者模式設定一套滑鼠事件監聽器
/** * 監聽器的一種包裝,標準事件源格式的定義 * * 事件源管理 * @Author: * @Date: 2020/12/15 16:06 */ public class Event { //事件源 事件是由誰發起的, 儲存起來 private Object source; //事件觸發 要通知誰 private Object target; // 事件觸發 要做什麼動作,回撥 private Method callback; // 事件的名稱 觸發的是什麼事件 private String trigger; // 事件觸發的時間 private long time; public Event(Object target, Method callback) { this.target = target; this.callback = callback; } public Object getSource() { return source; } public Event setSource(Object source) { this.source = source; return this; } public Object getTarget() { return target; } public Event setTarget(Object target) { this.target = target; return this; } public Method getCallback() { return callback; } /* public Event setCallback(Method callback) { this.callback = callback; return this; }*/ public String getTrigger() { return trigger; } public Event setTrigger(String trigger) { this.trigger = trigger; return this; } public long getTime() { return time; } public void setTime(long time) { this.time = time; } @Override public String toString() { return "Event{" + "source=" + source + ", target=" + target + ", callback=" + callback + ", trigger='" + trigger + '\'' + ", time=" + time + '}'; } }
監聽器
public class EventLisenter {
//jdk底層的lisenter通常也是這種設計
protected Map<String, Event> events = new HashMap<>();
//通過事件名稱和一個目標物件來觸發事件
public void addLisenter(String eventType, Object target) {
try {
String upperEventType = "on" + toUpperFirstCase(eventType);
this.addLisenter(eventType, target, target.getClass().getMethod(upperEventType, Event.class));
}
catch (Exception e) {
e.printStackTrace();
}
}
private void addLisenter(String eventType, Object target, Method callBack) {
//註冊事件
events.put(eventType, new Event(target, callBack));
}
/**
* 觸發,只要有動作就觸發
* @param
* @return
*/
private void trigger(Event event) {
event.setSource(this);
event.setTime(System.currentTimeMillis());
try {
//發起回撥
if (event.getCallback() != null) {
//用反射呼叫它的回撥函式
event.getCallback().invoke(event.getTarget(), event);
//也可以優化為策略模式組合,設定為不同的事件監聽內執行各種回撥函式
}
}
catch (IllegalAccessException e) {
e.printStackTrace();
}
catch (InvocationTargetException e) {
e.printStackTrace();
}
}
protected void trigger(String trigger) {
if (!this.events.containsKey(trigger)) {
System.out.println("事件" + trigger + "未註冊");
return;
}
trigger(this.events.get(trigger).setTrigger(trigger));
}
private String toUpperFirstCase(String eventType) {
char[] chars = eventType.toCharArray();
chars[0] -= 32;
return String.valueOf(chars);
}
}
事件管理:
/**
* 事件
* @Author: Zhangdongdong
* @Date: 2020/12/15 16:32
*/
public class Mouse extends EventLisenter {
public void click() {
System.out.println("呼叫單擊方法");
this.trigger(MouseEventType.ON_CLICK);
}
public void doubleClick() {
System.out.println("呼叫雙擊方法");
this.trigger(MouseEventType.ON_DOUBLE_CLICK);
}
public void up() {
System.out.println("呼叫彈起方法");
this.trigger(MouseEventType.ON_UP);
}
public void down() {
System.out.println("呼叫按下方法");
this.trigger(MouseEventType.ON_DOWN);
}
public void move() {
System.out.println("呼叫移動方法");
this.trigger(MouseEventType.ON_MOVE);
}
public void wheel() {
System.out.println("呼叫滾動方法");
this.trigger(MouseEventType.ON_WHEEL);
}
public void over() {
System.out.println("呼叫懸停方法");
this.trigger(MouseEventType.ON_OVER);
}
public void blur() {
System.out.println("呼叫失焦方法");
this.trigger(MouseEventType.ON_BLUR);
}
public void focus() {
System.out.println("呼叫獲焦方法");
this.trigger(MouseEventType.ON_FOCUS);
}
}
回撥函式:
/**
* 監聽後執行事件
* @Author: Zhangdongdong
* @Date: 2020/12/15 16:37
*/
public class MouseEventCallback {
public void onClick(Event e) {
System.out.println("=============== 觸發滑鼠單擊事件 ===============" + "\n" + e);
}
public void onDoubleClick(Event e) {
System.out.println("=============== 觸發滑鼠雙擊事件 ===============" + "\n" + e);
}
public void onUp(Event e) {
System.out.println("=============== 觸發滑鼠彈起事件 ===============" + "\n" + e);
}
public void onDown(Event e) {
System.out.println("=============== 觸發滑鼠按下事件 ===============" + "\n" + e);
}
public void onMove(Event e) {
System.out.println("=============== 觸發滑鼠移動事件 ===============" + "\n" + e);
}
public void onWheel(Event e) {
System.out.println("=============== 觸發滑鼠滾動事件 ===============" + "\n" + e);
}
public void onOver(Event e) {
System.out.println("=============== 觸發滑鼠懸停事件 ===============" + "\n" + e);
}
public void onBlur(Event e) {
System.out.println("=============== 觸發滑鼠失焦事件 ===============" + "\n" + e);
}
public void onFocus(Event e) {
System.out.println("=============== 觸發滑鼠獲焦事件 ===============" + "\n" + e);
}
}
事件型別統一定義:
/**
* 事件型別定義
* @Author: Zhangdongdong
* @Date: 2020/12/15 16:27
*/
public interface MouseEventType {
//單擊
String ON_CLICK = "click";
//雙擊
String ON_DOUBLE_CLICK = "doubleClick";
//彈起
String ON_UP = "up";
//按下
String ON_DOWN = "down";
// 移動
String ON_MOVE = "move";
// 滾動
String ON_WHEEL = "wheel";
// 懸停
String ON_OVER = "over";
// 失焦
String ON_BLUR = "blur";
// 獲焦
String ON_FOCUS = "focus";
}
測試:
public class EventMainTest {
public static void main(String[] args) {
MouseEventCallback callback = new MouseEventCallback();
try {
//註冊事件
Mouse mouse = new Mouse();
mouse.addLisenter(MouseEventType.ON_CLICK, callback);
mouse.addLisenter(MouseEventType.ON_MOVE, callback);
mouse.addLisenter(MouseEventType.ON_WHEEL, callback);
mouse.addLisenter(MouseEventType.ON_OVER, callback);
mouse.click();
mouse.blur();
}
catch (Exception e) {
e.printStackTrace();
}
}
}
結果為: