基于Java的设计模式-观察者模式

观察者模式指定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。

观察者模式主要是解决一个对象状态改变给其他对象通知的问题。总共分为四部分:

  • 抽象被观察者角色:抽象主题,它把所有对观察者对象的引用保存在一个集合中,每个主题都可以有任意数量的观察者。抽象主题提供一个接口,可以增加和删除观察者角色。
  • 抽象观察者角色:抽象观察者,是观察者者的抽象类,它定义了一个更新接口,在得到主题通知时更新自己。
  • 具体被观察者角色:具体的主题,在集体主题的内部状态改变时,所有订阅过的观察者发出通知。
  • 具体观察者角色:具体观察者,实现抽象观察者定义的更新接口,以便在得到主题更改通知时更新自身的状态。

实现

抽象观察者角色

复制代码
public interface Observer {
	public void updateInfo(String message);
}

具体观察者角色

复制代码
public class ManObserver implements Observer {

	@Override
	public void updateInfo(String message) {
		System.out.println("男士接受的信息:"+message);
	}
}


=====


public class WomanObserver implements Observer {

	@Override
	public void updateInfo(String message) {
		System.out.println("女士接受的信息:"+message);
	}

}

抽象被观察者角色

复制代码
public interface SubInfoService {
	//发送消息
	public void subMessage(String message);
	//订阅
	public void addObservers(Observer observer);
	//取消订阅
	public void cancerObservers(Observer observer);
}

具体被观察者角色

复制代码
import java.util.ArrayList;
import java.util.List;

public class SubInfo implements SubInfoService{
	private List<Observer> observers; 
	
	private String message;
	
	public SubInfo(){
		observers = new ArrayList<Observer>();
	}
	//发布信息
	public void subMessage(String message){
		this.message=message;
		notifyAllObserver();
	}
	//订阅
	public void addObservers(Observer observer){
		observers.add(observer);
	}
	
	//每个订阅者都发布信息
	public void notifyAllObserver(){
		for (Observer observer : observers) {
			observer.updateInfo(message);
		}
	}
	//取消订阅
	@Override
	public void cancerObservers(Observer observer) {
		observers.remove(observer);
	}
}

测试

复制代码
public class TestSub {
	public static void main(String[] args) {
		WomanObserver wo = new WomanObserver();
		ManObserver mo = new ManObserver();
		SubInfo sub = new SubInfo();
		sub.addObservers(mo);
		sub.addObservers(wo);
		sub.subMessage("信息来了");
		System.out.println("=======");
		sub.subMessage("你们好啊!");
		System.out.println("=======");
		sub.cancerObservers(wo);
		sub.subMessage("我们聊聊");
	}
}

结果

复制代码
男士接受的信息:信息来了
女士接受的信息:信息来了
=======
男士接受的信息:你们好啊!
女士接受的信息:你们好啊!
=======
男士接受的信息:我们聊聊

这个观察者模式优点就是观察者和被观察者是抽象耦合的。缺点就是当订阅者过多的时候,所有观察者通知会花费很多时间。如果观察者和被观察者之间循环调用就会使得系统崩溃。

在Spring的事件机制中就体现了观察者模式。

我在SSM的项目实现这样的功能,当用户注册的时候,发送一封邮件给该用户。

EmailEvent.java

复制代码
import org.springframework.context.ApplicationEvent;

public class EmailEvent extends ApplicationEvent{

	private static final long serialVersionUID = -5948806306069839382L;

	private String emailAddress;
	public EmailEvent(String emailAddress) {
		super(emailAddress);
		this.emailAddress =emailAddress;
	}
	public String getEmailAddress() {
		return emailAddress;
	}
	public void setEmailAddress(String emailAddress) {
		this.emailAddress = emailAddress;
	}	
}

EmailEventListener.java

复制代码
import org.simplejavamail.email.Email;
import org.simplejavamail.email.EmailBuilder;
import org.simplejavamail.mailer.Mailer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;

@Component
public class EmailEventListener implements ApplicationListener<EmailEvent> {

	private static Logger log = LoggerFactory.getLogger(EmailEventListener.class);
	
	@Autowired
	private Mailer mailer;
	
	@Value("${user.email.name}")
	private String emailName;
	
	@Override
	public void onApplicationEvent(EmailEvent event) {
		String email = event.getEmailAddress();
		log.info("事件监听,获取到注册邮件是:"+email);
		
		//发送邮件
		Email em = EmailBuilder.startingBlank()
		          .from("商家",emailName)  
				  .to("用户", email)
		          .withSubject("请查收你的邮件")
		          .withPlainText("非常感谢你的注册,快来逛一逛我们网站吧")
		          .buildEmail();
		 
	
		mailer.sendMail(em);
	}

}

EmailEventPublish.java

复制代码
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.stereotype.Component;

@Component
public class EmailEventPublish implements ApplicationEventPublisherAware{

	private ApplicationEventPublisher applicationEventPublisher;
	
	@Override
	public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
		this.applicationEventPublisher=applicationEventPublisher;
	}
	
	public void publish(String email){
		EmailEvent event = new EmailEvent(email);
		applicationEventPublisher.publishEvent(event);
	}
}

applicationContext.xml

复制代码
	<context:component-scan base-package="com.plf" />

UserController.java

复制代码
@Autowired    
private ApplicationContext applicationContext;  

public String register(User user){
	...
	applicationContext.publishEvent(new EmailEvent(user.getEmail()));
	...
}
相关推荐
挺菜的12 分钟前
【算法刷题记录(简单题)003】统计大写字母个数(java代码实现)
java·数据结构·算法
掘金-我是哪吒1 小时前
分布式微服务系统架构第156集:JavaPlus技术文档平台日更-Java线程池使用指南
java·分布式·微服务·云原生·架构
亲爱的非洲野猪1 小时前
Kafka消息积压的多维度解决方案:超越简单扩容的完整策略
java·分布式·中间件·kafka
wfsm1 小时前
spring事件使用
java·后端·spring
微风粼粼2 小时前
程序员在线接单
java·jvm·后端·python·eclipse·tomcat·dubbo
缘来是庄2 小时前
设计模式之中介者模式
java·设计模式·中介者模式
rebel2 小时前
若依框架整合 CXF 实现 WebService 改造流程(后端)
java·后端
代码的余温3 小时前
5种高效解决Maven依赖冲突的方法
java·maven
慕y2743 小时前
Java学习第十六部分——JUnit框架
java·开发语言·学习
paishishaba4 小时前
Maven
java·maven