java的設(shè)計模式
作用 當觀察對象的狀態(tài)發(fā)生變化時,通知給觀察者(觀察者訂閱被觀察者的狀態(tài))
應(yīng)用 需要根據(jù)對象狀態(tài)進行相應(yīng)處理的場景

Observer.png
創(chuàng)建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);
};//注冊O(shè)beserver
public void notifyObservers(){
//向Observer發(fā)送通知
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();
}
}
}
創(chuàng)建抽象Observer類
package com.company;
public abstract class Observer {
protected Subject subject;\\有Subject類的實例化對象,便于獲取被觀察者的信息
public abstract void update();\\在子類中實現(xiàn)更新的具體操作
}
創(chuàng)建實體觀察類
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);\\創(chuàng)建觀察者
subject.setState();\\設(shè)置狀態(tài)(改變狀態(tài))
}
}
另一種實現(xiàn)方法
- 將
抽象Observer類變?yōu)闉?code>接口——ObserverI - Subject的實例化對象
subject變成接口ObserverI的update()方法的參數(shù)(原來是抽象類Observer的私有成員)
package com.company;
public interface ObserverI {
public abstract void update(Subject subject);
}
- Observer類由抽象類變成了接口,Subject類中添加觀察者的方法和向Observer發(fā)送通知的方法也應(yīng)當重寫
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);
};//第二種方法,注冊O(shè)beserver的方式
public void notifyObservers(){
//向Observer發(fā)送通知
Iterator it = observers.iterator();
while (it.hasNext()){
Observer observer = (Observer)it.next();
observer.update();
}
}//第一種
public void notifyObservers2(){
//向Observer發(fā)送通知
Iterator it = observers.iterator();
while (it.hasNext()){
ObserverI observer = (ObserverI)it.next();
observer.update(this);//改變后的update方法需要傳入一個subject進去
}
}//第二種方法
//注意:在狀態(tài)改變后(setState)應(yīng)當調(diào)用的發(fā)送通知的方法也應(yīng)當換成第二種對應(yīng)的
}
-
繼承ObserverI接口,實現(xiàn)具體方法
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的具體實現(xiàn)類中沒有Subject類的實例化對象作為類成員,無法在構(gòu)造函數(shù)中直接添加observer(注冊observer),需要在
客戶端(Main)添加
//第一種注冊observer的方式
public class Observerb extends Observer{
public Observerb(Subject subject){
this.subject = subject;
this.subject.addObserver(this);//改變后
}
}//第一種只要創(chuàng)建了Subject具體實現(xiàn)類的實例化對象,就在被觀察者中添加了觀察者,
//第二種方法,注冊O(shè)bserver的方式
public class Main {
public static void main(String[] args) {
Subject subject = new Subjecta();
Observer observer1 = new Observera();
Observer observer2 = new Observerb();//創(chuàng)建觀察者
subject.addObserver(observer1);
subject.addObserver(observer2);
subject.setState();\\設(shè)置狀態(tài)(改變狀態(tài))
}
}//現(xiàn)在,創(chuàng)建觀察者后,還需調(diào)用被觀察者中添加觀察者的方法)
注意點
Observer的順序
Subject角色中有多個Observer角色,在示例代碼中是先注冊的Observer的update方法先被調(diào)用
Observer的行為對Subject的影響
Subject的狀態(tài)變化 ---> 通知Observer ---> Observer調(diào)用Subject的方法 ---> 導(dǎo)致Subject的狀態(tài)發(fā)生變化 ---> 通知Observer
導(dǎo)致方法被循環(huán)調(diào)用
update方法傳入的參數(shù)
void update(Subject subject);
void update(int number);
void update(Subject subject,int number);
可以傳入Subject實例對象,也可以傳入該實例中的某些數(shù)據(jù),第一種更加靈活
拓展
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