抽象概念:两个角色,一个观察者,一个主题(被观察者),主题提供注册接口,观察者提供通知接口,观察者将自己注册到主题中,主题发生变化时通知所有注册的观察者(并把信息传递给观察者)。
形象的比喻:主题为房东,观察者为租客,租客在房东那里登记留下联系方式(注册的过程),等到有了空房时候房东打电话给租客(主题变化通知观察者的过程)。
实例代码:
主题抽象接口
package com.youyouzhixin.designpattern.subject;
import com.youyouzhixin.designpattern.observer.Observer;
/**
*
* 描述:主题抽象接口
* @since
*/
public interface Subject {
/**
*
* 描述:观察者注册
* @since
* @param observer
*/
public void registerObserver(Observer observer);
/**
*
* 描述:删除观察者
* @since
* @param observer
*/
public void removeObserver(Observer observer);
/**
*
* 描述:当主题有变化时调用,用于通知观察者
* @since
*/
public void notifyObserver();
}
观察者抽象接口
package com.youyouzhixin.designpattern.observer;
/**
*
* 描述:观察者抽象接口
* @since
*/
public interface Observer {
/**
*
* 描述:呼叫我
* @since
* @param info 通知内容
*/
public void callMe(String info);
}
房东(具体主题)
package com.youyouzhixin.designpattern;
import java.util.ArrayList;
import java.util.List;
import com.youyouzhixin.designpattern.observer.Observer;
import com.youyouzhixin.designpattern.subject.Subject;
/**
*
* 描述:房东(具体主题)
*
* @since
*/
public class Landlord implements Subject {
private String name;
private List<Observer> observers;
private String houseInfo;
private String messageInfoFormate;
public Landlord(String myname) {
observers = new ArrayList<Observer>();
houseInfo = "";
name = myname;
messageInfoFormate = name + "最新空房源户型[%s]价位[%s]元。";
}
/**
* 租客登记
*/
@Override
public void registerObserver(Observer observer) {
this.observers.add(observer);
}
/**
* 租客撤销
*/
@Override
public void removeObserver(Observer observer) {
int i = observers.indexOf(observer);
if (i >= 0) {
observers.remove(i);
}
}
/**
* 通知租客
*/
@Override
public void notifyObserver() {
for (int i = 0; i < observers.size(); i++) {
Observer observer = (Observer) observers.get(i);
observer.callMe(houseInfo);
}
}
/**
*
* 描述:发布空房源信息
*
* @since
* @param houseInfoNew
*/
public void publishInfo(String... houseInfoNew) {
if (houseInfoNew != null) {
this.houseInfo = String.format(messageInfoFormate,
(Object[]) houseInfoNew);
System.out.println("[" + name + "]发布信息:" + houseInfo);
this.notifyObserver();
}
}
}
租客(具体观察者)
package com.youyouzhixin.designpattern;
import com.youyouzhixin.designpattern.observer.Observer;
public class Renter implements Observer {
private String name;
public Renter(String myname) {
this.name = myname;
}
/**
* 最新空房源信息通知
*/
@Override
public void callMe(String info) {
System.out.println(name + "接收通知信息:" + info);
}
}
测试类
package com.youyouzhixin.designpattern;
public class OSpatternTest {
public static void main(String[] args) {
Landlord landlord = new Landlord("房东甲");
Renter renterA = new Renter("租客A");
landlord.registerObserver(renterA);
Renter renterB = new Renter("租客B");
landlord.registerObserver(renterB);
Renter renterC = new Renter("租客C");
landlord.registerObserver(renterC);
landlord.publishInfo("单间","950");
System.out.println();
landlord.publishInfo("一房一厅","1100");
System.out.println();
landlord.publishInfo("二房一厅","1300");
}
}
思考:
多观察者需要串行调用,可不可以群发节省时间成本呢?如何引入多线程解决?(本人会在后续文章《观察者模式(二)——多线程与CountDownLatch浅析》给出一种解决思路)
温馨提醒:以上只是个人理解,如有不对之处还请各位大神指正。