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


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

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

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

    实现

    抽象观察者角色

    public interface Observer {
    	public void updateInfo(String message);
    }
    
    • 1
    • 2
    • 3

    具体观察者角色

    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);
    	}
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    抽象被观察者角色

    public interface SubInfoService {
    	//发送消息
    	public void subMessage(String message);
    	//订阅
    	public void addObservers(Observer observer);
    	//取消订阅
    	public void cancerObservers(Observer observer);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    具体被观察者角色

    import java.util.ArrayList;
    import java.util.List;
    
    public class SubInfo implements SubInfoService{
    	private List observers; 
    	
    	private String message;
    	
    	public SubInfo(){
    		observers = new ArrayList();
    	}
    	//发布信息
    	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);
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    测试

    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("我们聊聊");
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    结果

    男士接受的信息:信息来了
    女士接受的信息:信息来了
    =======
    男士接受的信息:你们好啊!
    女士接受的信息:你们好啊!
    =======
    男士接受的信息:我们聊聊
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

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

    在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;
    	}	
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    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 {
    
    	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);
    	}
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39

    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);
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    applicationContext.xml

    	
    
    • 1

    UserController.java

    @Autowired    
    private ApplicationContext applicationContext;  
    
    public String register(User user){
    	...
    	applicationContext.publishEvent(new EmailEvent(user.getEmail()));
    	...
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
  • 相关阅读:
    MySQL统计近12个月的数据,如果某个月份没有数据则用0填充
    IE浏览器设置兼容性、清除缓存,重置浏览器、Edge浏览器设置兼容性
    GoJS 使用笔记
    从 0 到 1,看我玩弄千万日志于股掌
    面试题解答:Spring Lifecycle 和 SmartLifecycle 有何区别?
    控制期货开户保证金可以降低风险
    角谱计算时的fftshift及其原理
    【文件同步和备份软件】上海道宁为您带来GoodSync软件,让您轻松备份和同步您的文件
    【JVM】JVM的垃圾回收机制
    SpringBoot的自动装配源码分析(2022.11.07)
  • 原文地址:https://blog.csdn.net/flash_love/article/details/133068140