zoukankan      html  css  js  c++  java
  • 用java观察者模式解耦经典三层架构

    三层架构是一个很经典的架构模式,依据系统的职责不同。将系统分成了表现层,逻辑层和数据訪问层,而且配合数据实体进行传输数据,能够大大的封装性和复用性。

    经典的三层架构图:


    我们再深入到架构图内部。看看详细的类图,用简单的登陆举例吧:


    这里通过LoginUI。调用了LoginLogService和LoginVerificationService两个类。通过类图能够看得出,U层和Service层(本文把BLL层称为了Service层)直接採用了直接调用的方式。

    在面向对象的设计中。一直强调要面向接口编程,好我们把接口加上:



    好了。加上接口以后。再用上工厂方法或者依赖管理的框架spring,就能够实现U层和Service层的解耦了。我们随时针对LoginLogService和LoginVerificationService进行替换。这既符合针对接口编程。由符合开闭原则。也符合里氏替换。

    好。那我有一个问题。我不想更改当前的两个逻辑,想加入第三个逻辑。是不是得改U层的类了?

    好了,接下来是观察者模式应该出场的时候了,让我们看看怎么利用这个模式来解决逻辑加入,来实现三层架构的真正解耦(这里主要指U层和Service层的耦合)。事实上观察者模式就是java托付的实现方式。

    首先说明下思路。我们把LoginUI作为事件源,发usernamepassword作为消息发送出去。注冊过的Service能够处理消息,也就是说通过消息对U层和Service层进行了解耦。来看下类图


    这里LoginUI变成了LoginEventSource,变成了事件源,而且继承了EventSource抽象类,两个Service类继承了Listener接口,成为了监听者。

    那详细是怎么解耦的呢?

    首先看EventSource抽象类。该抽象类实现了事件源的注冊、删除和通知方法。

    package com.tgb.chargeSystem;
    
    import java.util.ArrayList;
    
    public abstract class EventSource {
    	//keep registered listener 
    	private ArrayList<Listener> listeners=new ArrayList<Listener>();
    	
    	//register listener to EventSource
    	//EventSource have data that Listener interested in
    	public void registerListener(Listener listener){
    		listeners.add(listener);
    	}
    	
    	//stop focuse on this event
    	public void removeListener(Listener listener){
    		int i=listeners.indexOf(listener);
    		if(i>0){
    			listeners.remove(i);
    		}
    	}
    	
    	//EventSource notify listener and send itself as message 
    	public void notifyListenner(){
    		for(int i=0;i<listeners.size();i++){
    			Listener listener=listeners.get(i);
    			listener.actionPerformed(this);
    		}
    	}
    	
    }


    接下来看下EventSource的子类LoginEventSource,它提供了两个回调方法。

    package com.tgb.chargeSystem;
    
    import java.util.ArrayList;
    
    public class LoginEventSource extends EventSource{
    	private String username="xqf";
    	private String password="123";
    	
    	//Callback method ,when success in verification,be invoked 
    	public String LoginSuccess(){
    		System.out.println(this.getClass().getName()+"print:Login Success");
    		return "Success";
    	}
    	//Callback method ,when fail in verification,be invoked 
    	public String LoginFail(){
    		System.out.println(this.getClass().getName()+"print:Login Fail");
    		return "Fail";
    	}
    	
    	public String getUsername() {
    		return username;
    	}
    	public void setUsername(String username) {
    		this.username = username;
    	}
    	public String getPassword() {
    		return password;
    	}
    	public void setPassword(String password) {
    		this.password = password;
    	}
    }

    接下来看看Listener接口

    package com.tgb.chargeSystem;
    
    public interface Listener {
    	void actionPerformed(EventSource e);
    }

    实现了Listener接口的LoginLogListener类

    package com.tgb.chargeSystem;
    
    public class LoginLogListener implements Listener {
    	
    	public LoginLogListener(EventSource eventSource){
    		eventSource.registerListener(this);
    	}
    	@Override
    	public void actionPerformed(EventSource e) {
    		
    		System.out.println("======保存日志到txt文件==========");
    		System.out.println("username:"+((LoginEventSource)e).getUsername()+",password:"+((LoginEventSource)e).getPassword());
    		System.out.println("=======保存完成==========");
    		
    	}
    
    }


    实现了Listener接口的LoginVerificationListener类:

    package com.tgb.chargeSystem;
    
    public class LoginVerificationListener implements Listener{
    	
    	private static final String USERNAME="xqf";
    	private static final String PASSWORD="123"; 
    	
    	public LoginVerificationListener(EventSource eventSource){
    		//register itself to EventSource
    		eventSource.registerListener(this);
    	}
    	@Override
    	public void actionPerformed(EventSource e) {
    		System.out.println(this.getClass().getName()+"print: invoke actionPerformed method");
    		LoginEventSource les=(LoginEventSource)e;
    		//according to username and passowrd,call Callback method
    		if(les.getUsername().equals(USERNAME)&&les.getPassword().equals(PASSWORD)){
    			les.LoginSuccess();
    		}else{
    			les.LoginFail();
    		}
    	}
    	
    }
    

    到此,我们还须要一个类,把listener类注冊到事件源,这样。事件源也就是U层就能够发消息给Service层了,这里我们暂且把这个类放到U层。

    这是当我们再想加入逻辑,仅仅须要实现Listener接口,而且改动一下以下这个类,把新加入的类注冊到LoginEventSource上就能够了。

    public static void main(String[] args){
    		
    		
    		LoginEventSource loginEventSource=new LoginEventSource();
    		
    		LoginLogListener lll=new LoginLogListener(loginEventSource);
    		LoginVerificationListener lvl=new LoginVerificationListener(loginEventSource);
    		
    		loginEventSource.notifyListenner();
    }









  • 相关阅读:
    [Linux]yum开启rpm包缓存
    [Linux]centOS7-1-1503-x86_64下安装VM-TOOLS
    [Linux]centOS7下RPM安装Perl
    vue 之 pageage.json 和 webpack.config.js
    node 之 apache
    node 之 express
    node 之 基础知识
    npm nvm nrm的关系
    echarts 学习笔记
    git 操作学习
  • 原文地址:https://www.cnblogs.com/wgwyanfs/p/6737125.html
Copyright © 2011-2022 走看看