Observer觀察者設計模式是行爲模式的一種,它的作用是當一個對象的狀態發生變化時,能夠自動通知其他關聯對象,自動刷新對象狀態
Observer模式提供給關聯對象一種同步通信的手段,使某個對象與依賴它的其他對象之間保持狀態同步。如下用代碼的形式來展現被觀察者(新聞出版社)和觀察者(與之關聯的訂戶觀察者對象)是如何保持信息同步的。
1 被觀察者-新聞出版社
/**
* NewsPublisher: 新聞出版社
*/
class NewsPublisher extends Observable {
public void publishNews(String newsTitle, String newsBody) {
News news = new News(newsTitle, newsBody);
setChanged(); //通過setChanged()方法標明對象的狀態已發生變化
this.notifyObservers(news); //通知各Observer,併發送一個名爲news對象的消息
// ... ...
}
}
2 觀察者-訂戶觀察者
/**
* 訂戶觀察者。
* Created by myuser on 2014/11/29.
*/
public class SubscriberObserver implements Observer {
// 新聞出版社調用notifyObservers(news)方法,自動調用如下方法以保持信息同步。
public void update(Observable observee, Object param) {
if (param instanceof News) {
mail2Subscriber((News)param);
}
}
private void mail2Subscriber(News news) {
System.out.println("Mail to subscriber. A news published with title:" + news.getTitle());
}
}
3 構造者
被觀察者調用notifyObservers()方法後,爲什麼觀察者就能接收到呢?那是因爲有構造者這個角色,它將觀察者添加到被觀察者的依賴對象裏面,代碼如下:
public class Client {
/**
* Test Observer Pattern
*/
public static void main(String[] args) {
NewsPublisher publisher = new NewsPublisher();
// 添加訂戶觀察者依賴對象
publisher.addObserver(new SubscriberObserver());
//發佈新聞,觸發通知事件
publisher.publishNews("Hello news", "news body");
}
}
上面是一個簡單的Observer觀察者設計模式的實例。接下來看看大數據框架hadoop是如何應用該設計模式的。
應用場景如下:JobTracker收到作業後,並不會馬上對其初始化,而是交給調度器,由它按照一定的策略對作業進行初始化。
4 被觀察者-JobTracker
JobTracker進行作業添加(執行addJob()方法)時,會同步該消息到對應的觀察者(JobInProgressListener )那裏,代碼如下:
publicclass JobTracker {
privatefinal List<JobInProgressListener> jobInProgressListeners =
new CopyOnWriteArrayList<JobInProgressListener>();
private synchronized JobStatus addJob(JobID jobId, JobInProgress
job) {
... ...
for (JobInProgressListener listener : jobInProgressListeners) {
listener.jobAdded(job); //通知各Observer,併發送job消息
}
... ...
}
}
5 觀察者-JobQueueJobInProgressListener
class JobQueueJobInProgressListener extends JobInProgressListener {
private Map<JobSchedulingInfo, JobInProgress> jobQueue;
@Override
publicvoid jobAdded(JobInProgress job) {
// 將作業添加到作業隊列裏。
jobQueue.put(new JobSchedulingInfo(job.getStatus()), job);
}
}
6 構造者
接下來看一下JobTracker和JobQueueJobInProgressListener的依賴關係是如何建立起來的。
先看一下JobTracker類的一些信息,代碼如下所示:
publicclass JobTracker implements MRConstants, InterTrackerProtocol,
JobSubmissionProtocol, TaskTrackerManager, RefreshUserMappingsProtocol,
RefreshAuthorizationPolicyProtocol, AdminOperationsProtocol,
JobTrackerMXBean {
// 該類實例化的時候,會從配置文件的屬性mapred.jobtracker.taskScheduler獲取調度器的類名,然後實例化一個調度器作爲JobTracker的一個屬性。代碼如下所示:
JobTracker(final JobConf conf, String identifier, Clock clock, QueueManager qm) {
... ...
Class<? extends TaskScheduler> schedulerClass
= conf.getClass("mapred.jobtracker.taskScheduler",
JobQueueTaskScheduler.class, TaskScheduler.class);
taskScheduler = (TaskScheduler) ReflectionUtils.newInstance(schedulerClass, conf);
... ...
}
// JobTracker類被運行的時候會去調用startTracker()靜態方法和offerService(),代碼如下所示:
publicstaticvoid main(String argv[]
) throws IOException, InterruptedException {
... ...
JobTracker tracker = startTracker(new JobConf());
tracker.offerService();
... ...
}
// startTracker()靜態方法首先實例一個JobTracker類,然後將當前實例賦給調度器的taskTrackerManager屬性。
publicstatic JobTracker startTracker(JobConf conf, String identifier)
throws IOException, InterruptedException {
... ...
result = new JobTracker(conf, identifier);
result.taskScheduler.setTaskTrackerManager(result);
... ...
returnresult;
}
// offerService()方法調用調度器的start()方法。
publicvoid offerService() throws InterruptedException, IOException {
... ...
taskScheduler.start();
... ...
}
}
// 如下是調度器的start()方法,該方法將JobQueueJobInProgressListener類添加到JobTracker的依賴屬性裏,也即構造了JobTracker和JobQueueJobInProgressListener的被觀察者與觀察者關係。
class JobQueueTaskScheduler extends TaskScheduler {
public JobQueueTaskScheduler() {
this.jobQueueJobInProgressListener=new JobQueueJobInProgressListener();
}
publicsynchronizedvoid start() throws IOException {
... ...
taskTrackerManager.addJobInProgressListener(jobQueueJobInProgressListener);
... ...
}
}