抽象概念:两个角色,一个观察者,一个主题(被观察者),主题提供注册接口,观察者提供通知接口,观察者将自己注册到主题中,主题发生变化时通知所有注册的观察者(并把信息传递给观察者)。
形象的比喻:主题为房东,观察者为租客,租客在房东那里登记留下联系方式(注册的过程),等到有了空房时候房东打电话给租客(主题变化通知观察者的过程)。
实例代码:
主题抽象接口
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浅析》给出一种解决思路)
温馨提醒:以上只是个人理解,如有不对之处还请各位大神指正。