Java设计模式-6、观察者模式

观察者模式

       观察者模式主要⽤于处理对象间的⼀对多的关系,是⼀种对象⾏为模式。 该模式的实际应⽤场景⽐较容易确认,当⼀个对象状态发⽣变化时,所有 该对象的关注者均能收到状态变化通知,以进⾏相应的处理。

Subject: 抽象被观察者,仅提供注册和删除观察者对象的接⼝声明。
ConcreteSubject: 具体被观察者对象,该对象中收集了所有需要被通知的 观察者,并可以动态的增删集合中的观察者。当其状态发⽣变化时会通知 所有观察者对象。
Observer: 抽象观察者,为所有观察者定义获得通知的统⼀接⼝;
ConcreteObserver: 观察者对象,其关注对象为 Subject ,能接受 Subject
变化时发出的通知并更新⾃身状态。

 1. 观察者模式的应用场景

  1. 消息队列
  2. 公众号
  3. java中的监听器
  4. 1)spring中ioc的应用
    2)事件监听

......

2 观察者模式的优缺点

优点:
1. 被观察者和观察者之间是抽象耦合的;
2. 耦合度较低,两者之间的关联仅仅在于消息的通知;
3. 被观察者⽆需关⼼他的观察者;
4. ⽀持⼴播通信;

缺点:
1. 观察者只知道被观察对象发⽣了变化,但不知变化的过程和缘由;
2. 观察者同时也可能是被观察者,消息传递的链路可能会过⻓,完成所有
通知花费时间较多;
3. 如果观察者和被观察者之间产⽣循环依赖,或者消息传递链路形成闭
环,会导致⽆限循环; 

3 你的项⽬是怎么⽤的观察者模式?

在⽀付场景下,⽤户购买⼀件商品,当⽀付成功之后三⽅会回调⾃身,在 这个时候系统可能会有很多需要执⾏的逻辑(如:更新订单状态,发送邮 件通知,赠送礼品… ),这些逻辑之间并没有强耦合,因此天然适合使⽤ 观察者模式去实现这些功能,当有更多的操作时,只需要添加新的观察者 就能实现,完美实现了对修改关闭,对扩展开放的开闭原则。也是应用场景中消息队列的应用,新消息发送给消息队列的主题Topic,新增一个消费对象就新增一个订阅主题的对象。

4. 代码实例

1. 观察者需要实现的接口

/**
 * 观察者需要实现的接口
 * 
 * @author WHM
 */
public interface ApplicationContextAware {
	// 注入ioc容器
	void setApplicationContext(ApplicationContext applicationContext);
}

2 观察者实现类

/**
 * 观察者实现类
 * @author WHM
 */
public class LoginFilter implements ApplicationContextAware {

	@SuppressWarnings("unused")
	private ApplicationContext applicationContext;
	public LoginFilter(ApplicationContext applicationContext) {
		//将当前对象当如ioc
		applicationContext.registerObserver(this);
	}
	
	public void setApplicationContext(ApplicationContext applicationContext) {
	System.out.println("ioc被注入了LoginFilter");
	this.applicationContext = applicationContext;
	}

}

3 被观察者接口

package pattern.observer;

/**
 * 被观察者 需要实现三个接口
 * 
 * @author WHM
 */
public interface ApplicationContext {
	/**
	 * 注册观察者,也就是ioc的容器(bean)
	 * 
	 * @author WHM
	 */
	void registerObserver(ApplicationContextAware applicationContextAware);

	/**
	 * 移除观察者
	 * 
	 * @author WHM
	 */
	void clearObserver(ApplicationContextAware applicationContextAware);

	/**
	 * 更新观察者的状态
	 * 
	 * @author WHM
	 */
	void notifyObserver();

	/**
	 * 创建容器
	 * 
	 * @author WHM
	 */
	void onCreate();

	public int observerGs();
}

4 被观察者实现类

package pattern.observer;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * 被观察者具体实现类
 * @author WHM
 */
public class WebAppLicationContext implements ApplicationContext {

	private Map<String,ApplicationContextAware> observers = new HashMap<String,ApplicationContextAware>();
	
	public WebAppLicationContext() {
		
	}
	
	@Override
	public void registerObserver(ApplicationContextAware applicationContextAware) {
		this.observers.put(applicationContextAware.getClass().getSimpleName(), applicationContextAware);
	}

	@SuppressWarnings("unlikely-arg-type")
	public void clearObserver(ApplicationContextAware applicationContextAware) {
		this.observers.remove(applicationContextAware).getClass().getSimpleName();
	}

	@Override
	public void notifyObserver() {
          Set<String> observerNames = observers.keySet();
          if(observerNames.size() <= 0) {
        	  return;
          }
          for(String oName : observerNames) {
        	  this.observers.get(oName).setApplicationContext(this);
          }
	}

	@Override
	public void onCreate() {
		System.out.println("ioc  容器在初始化中");
		//通知观察者
        this.notifyObserver();
	}
	
	public int observerGs() {
		return observers.size();
	}
	
}

5 验证类

/**
 * 模拟spring中bean获取ioc状态
 * 
 * @author WHM
 */
public class TMain {

	@SuppressWarnings("unused")
	public static void main(String[] args) {
		ApplicationContext context = new WebAppLicationContext();
		LoginFilter SimpleUrlHandlerMapping = new LoginFilter(context);
		context.onCreate();
		System.out.println("容器bean个数:" + context.observerGs());
	}
}

6 结果

5 总结:

不管叫什么名字 发布订阅也好, 观察者也好。这个模式的核心就是 当一个对象改变时,同时要去改变多个订阅的对象
目前很场景的就是公众号,订阅号,我订阅了很多公众号,每天都有精彩的文章可以看到,也能知道技术的更新程度,毕竟有大牛分享。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值