頻道欄目
首頁 > 資訊 > 其他 > 正文

GOF設計模式之OBSERVER(觀察者)

16-12-05        來源:[db:作者]  
收藏   我要投稿

概述

本文將和讀者一起來理解GOF設計模式之OBSERVER(觀察者)。同樣,本文將用JAVA對GOF中的示例代碼改些,同時附上測試用例。

模式結構

GOF對觀察者的模式結構描述如

這里寫圖片描述

觀察者要完成的任務是,當Subject執行Notify的時候,將觸發Observer.Update。實現很直白,維護一個o: Observer的數組用以保存Observer,在Notify方法中遍歷o: Observer,調用Update方法。

這么做的好處在于Observer和Subject的功能拆分得很獨立。Subject不用管Observer的處理邏輯,只需要調用Notify通知Observer對象即可。而Observer將在Update中執行觸發相應的處理邏輯。從而Subject和Observer完成了一定程度的解耦。

GOF列舉了11中行為模式,其中觀察者模式又是里頭應用廣泛的一個。PHP中,觀察者模式單獨被提出作為SPL類庫使用,足以可見其常用型。

代碼示例

這里寫圖片描述

AnalogClock與DigitalClock作為兩種時鐘,將觀察定時器任務對象SubjectTimerTask,當SubjectTimerTask調用Run方法時將觸發其Update方法。代碼如下:

package gof.observer;
public class AnalogClock extends Observer{
    protected SubjectTimerTask timerSubject;
    public AnalogClock(SubjectTimerTask timerSubject) {
        this.timerSubject = timerSubject;
        this.timerSubject.subject.Attach(this);
    }
    protected void finalize() {
        this.timerSubject.subject.Detach(this);
    }
    public void Update(Subject theChangedSubject) {
        if(this.timerSubject.subject.equals(theChangedSubject)) {
            this.Draw();
        }
    }
    public void Draw() {
        System.out.println("draw in AnalogClock");
    }
}
package gof.observer;

public class DigitalClock extends Observer{
    protected SubjectTimerTask timerSubject;
    public DigitalClock(SubjectTimerTask subject) {
        this.timerSubject = subject;
        this.timerSubject.subject.Attach(this);
    }
    protected void finalize() {
        this.timerSubject.subject.Detach(this);
    }
    public void Update(Subject theChangedSubject) { 
        if(this.timerSubject.subject.equals(theChangedSubject)) {
            this.Draw();
        }
    }
    public void Draw() {
        System.out.println("draw in Digital Clock");
    }
}
package gof.observer;

public abstract class Observer {
    public abstract void Update(Subject subject);
}
package gof.observer;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class Subject {
    protected List<observer> observers = new ArrayList<observer>();
    public void Attach(Observer observer) {
        this.observers.add(observer);
    }
    public void Detach(Observer observer) {
        Iterator<observer> iterator = this.observers.iterator();
        if (iterator.hasNext()) {
            Observer next = iterator.next();
            if (next.equals(observer)) {
                iterator.remove();
            }
        }
    }
    public void Notify() {
        Iterator<observer> iterator = this.observers.iterator();
        while(iterator.hasNext()) {
            iterator.next().Update(this);
        }
    }
}
package gof.observer;

public class SubjectTimerTask {
    Subject subject;
    public SubjectTimerTask(Subject subject) {
        this.subject = subject;
    }
    public void run() {
        this.subject.Notify();
    }
}

測試用例:

package gof.observer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan
public class ObserverConfig {
    @Bean
    public Subject subject() {
        return new Subject();
    }
    @Bean
    public SubjectTimerTask subjectTimerTask(Subject subject) {
        return new SubjectTimerTask(subject);
    }
    @Bean
    public AnalogClock analogClock(SubjectTimerTask timerSubject) {
        return new AnalogClock(timerSubject);
    }
    @Bean
    public DigitalClock digitalClock(SubjectTimerTask timerSubject) {
        return new DigitalClock(timerSubject);
    }
}
package gof.observer;

import static org.junit.Assert.*;

import org.junit.Rule;
import org.junit.Test;
import org.junit.contrib.java.lang.system.StandardOutputStreamLog;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.support.AnnotationConfigContextLoader;

@ContextConfiguration(classes=ObserverConfig.class,loader=AnnotationConfigContextLoader.class)
@RunWith(SpringJUnit4ClassRunner.class)
public class ObserverTest {
    @Rule
    public final StandardOutputStreamLog log = new StandardOutputStreamLog();
    @Autowired
    protected ApplicationContext context;
    @Autowired
    protected SubjectTimerTask task;
    @Autowired
    protected AnalogClock aclock;
    @Autowired
    protected DigitalClock dclock;
    protected String newLineMark;
    @Autowired
    public void setNewLineMark() {
        this.newLineMark = System.getProperty("line.separator");
    }
    @Test
    public void draw() {
        this.task.run();
        assertEquals("draw in AnalogClock" + this.newLineMark
                + "draw in Digital Clock" + this.newLineMark, this.log.getLog());
    }
}
相關TAG標簽
上一篇:臺積電:絕大多數7nm客戶都會轉向6nm_IT新聞_博客園
下一篇:最后一頁
相關文章
圖文推薦

關于我們 | 聯系我們 | 廣告服務 | 投資合作 | 版權申明 | 在線幫助 | 網站地圖 | 作品發布 | Vip技術培訓 | 舉報中心

版權所有: 紅黑聯盟--致力于做實用的IT技術學習網站

美女MM131爽爽爽毛片