观察者模式(一)——入门学习与示例

抽象概念:两个角色,一个观察者,一个主题(被观察者),主题提供注册接口,观察者提供通知接口,观察者将自己注册到主题中,主题发生变化时通知所有注册的观察者(并把信息传递给观察者)。


形象的比喻:主题为房东,观察者为租客,租客在房东那里登记留下联系方式(注册的过程),等到有了空房时候房东打电话给租客(主题变化通知观察者的过程)。

实例代码

主题抽象接口

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浅析》给出一种解决思路)


温馨提醒:以上只是个人理解,如有不对之处还请各位大神指正。


猜你喜欢

转载自blog.csdn.net/a123abc123abc/article/details/80783023