观察者模式(自定义观察者和可观察者的接口)

定义:在对象之间定义一对多的依赖,这样一来,当一个对象改变状态,依赖它的对象都会收到通知,并自动更新。

类图:

代码:

定义可观察者(发布者)接口

/**
 * 报社接口
 * @author z_hh
 * @time 2018年7月23日
 */
public interface NewspaperOffice {

	/**
	 * 用户注册
	 * @param o 读者
	 */
	void registerReader(Reader o);
	
	/**
	 * 用户取消订阅
	 * @param o 读者
	 */
	void removeReader(Reader o);
	
	/**
	 * 通知所有读者
	 */
	void notifyReaders();
	
}

定义可观察者(发布者)实现类

/**
 * 新华报社
 * @author z_hh
 * @time 2018年7月23日
 */
public class PeopleNewspaper implements NewspaperOffice {

	// 所有已订阅读者的集合
	private List<Reader> observers;
	
	// 报纸最新期数
	private int latestTerm;
	
	// 构造器
	public PeopleNewspaper() {
		observers = new ArrayList<>();
	}

	/**
	 * 新用户注册
	 * @param o 读者
	 */
	@Override
	public void registerReader(Reader o) {
		if (Objects.nonNull(o)) {
			System.out.println("新用户注册:" + o.getClass().getSimpleName());
			observers.add(o);
		}
	}

	/**
	 * 用户取消订阅
	 * @param o 读者
	 */
	@Override
	public void removeReader(Reader o) {
		if (Objects.nonNull(o)) {
			System.out.println("用户取消订阅:" + o.getClass().getSimpleName());
			observers.remove(o);
		}
	}

	/**
	 * 提醒所有读者
	 */
	@Override
	public void notifyReaders() {
		if (observers.isEmpty()) {
			System.out.println("没有订阅者!");
			return;
		}
		observers.forEach(observer -> observer.update(latestTerm));
	}
	
	/**
	 * 发布新报纸
	 */
	public synchronized void publishNewspaper() {
		latestTerm++;
		notifyReaders();
	}
	
	/**
	 * 获取最新报纸期数
	 * @return
	 */
	public int getLatestTerm() {
		return latestTerm;
	}
}

定义观察者(订阅者)接口

/**
 * 读者接口
 * @author z_hh
 * @time 2018年7月23日
 */
public interface Reader {

	/**
	 * 定义更新接口,提供给报社调用
	 * @param latestTerm
	 */
	void update(int latestTerm);
	
}

定义观察者(订阅者)公共抽象类

/**
 * 抽象读者,提取公共部分
 * @author z_hh
 * @time 2018年7月23日
 */
public abstract class AbstractReader implements Reader {

	protected NewspaperOffice newspaperOffice;
	
	/**
	 * 提供给子类默认构造器
	 * @param newspaperOffice
	 */
	public AbstractReader(NewspaperOffice newspaperOffice) {
		this.newspaperOffice = newspaperOffice;
		newspaperOffice.registerReader(this);
	}
	
	/**
	 * 注册
	 * @param newspaperOffice
	 */
	// 可以设置为钩子方法
	public abstract void register(NewspaperOffice newspaperOffice);
	
	/**
	 * 取消订阅
	 * @param newspaperOffice
	 */
	// 可以设置为钩子方法
	public abstract void remove(NewspaperOffice newspaperOffice);
	
}

定义观察者(订阅者)实现类

/**
 * 读者周先生
 * @author z_hh
 * @time 2018年7月23日
 */
public class ZhouSir extends AbstractReader {

	public ZhouSir(NewspaperOffice newspaperOffice) {
		super(newspaperOffice);
	}

	@Override
	public void update(int latestTerm) {
		System.out.println("我是周先生,收到了第" + latestTerm + "期的报纸");

	}

	@Override
	public void register(NewspaperOffice newspaperOffice) {
		newspaperOffice.registerReader(this);
	}

	@Override
	public void remove(NewspaperOffice newspaperOffice) {
		newspaperOffice.removeReader(this);
	}

}
/**
 * 李先生
 * @author z_hh
 * @time 2018年7月23日
 */
public class LiSir extends AbstractReader {

	public LiSir(NewspaperOffice newspaperOffice) {
		super(newspaperOffice);
	}

	@Override
	public void update(int latestTerm) {
		System.out.println("我是李先生,收到了第" + latestTerm + "期的报纸");
	}

	@Override
	public void register(NewspaperOffice newspaperOffice) {
		newspaperOffice.registerReader(this);
	}

	@Override
	public void remove(NewspaperOffice newspaperOffice) {
		newspaperOffice.removeReader(this);
	}

}

测试:

public class Test {

	public static void main(String[] args) {
		// 创建新华报社,开始没有读者
		PeopleNewspaper peopleNewspaper = new PeopleNewspaper();
		peopleNewspaper.publishNewspaper();
		
		System.out.println("--------------完美分割线--------------");
		
		// 两位读者注册
		AbstractReader zhou = new ZhouSir(peopleNewspaper);
		AbstractReader li = new LiSir(peopleNewspaper);
		peopleNewspaper.publishNewspaper();
		
		// 周先生取消订阅
		System.out.println("--------------完美分割线--------------");
		zhou.remove(peopleNewspaper);
		peopleNewspaper.publishNewspaper();
		
		// 周先生重新订阅,李先生取消订阅
		System.out.println("--------------完美分割线--------------");
		zhou.register(peopleNewspaper);
		li.remove(peopleNewspaper);
		peopleNewspaper.publishNewspaper();

	}

}

结果:

没有订阅者!
--------------完美分割线--------------
新用户注册:ZhouSir
新用户注册:LiSir
我是周先生,收到了第2期的报纸
我是李先生,收到了第2期的报纸
--------------完美分割线--------------
用户取消订阅:ZhouSir
我是李先生,收到了第3期的报纸
--------------完美分割线--------------
新用户注册:ZhouSir
用户取消订阅:LiSir
我是周先生,收到了第4期的报纸

注意:该案例的可观察者和观察者均为我们自己定义,这样有利于加深对观察者模式的理解。

JDK也提供了可观察者和观察者的接口,方便我们使用,后面我们将做讲解。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值