代理模式的运用

考虑这样一种情况。某个系统要根据用户的权限来判断是否能操作。那么可以这么写:

class ViewAction{
	String permission;
	public ViewAction(String permission ){
		this.permission = permission;
	}
	
	public void DoAction(){
		if(permission.equals("VIEW")){
			System.out.println("查看信息!");
		}
	}
}

class AddAction{
	String permission;
	public AddAction(String permission ){
		this.permission = permission;
	}
	
	public void DoAction(){
		if(permission.equals("ADD")){
			System.out.println("添加信息!");
		}
	}
}

public class proxy {
	public static void main(String[] args){
		//赋予用户查看权限
		String permission = "VIEW";
		ViewAction user = new ViewAction(permission);
		user.DoAction();
		AddAction user1 = new AddAction(permission);
		user1.DoAction();
	  }
}

 可以看到,虽然执行了添加 查看操作,可是最后只执行了查看操作。

 

但是这样子将权限和操作放在一起,违反了类的单一性原则。不利用程序维护。

 

既然有这么多的问题,我们有必要对该类进行重新设计。其实大家早已想到,这个类应该使用代理模式。和我们买火车票的动作一样,动作类不能直接执行那个动作,而是要先检查权限,然后才能执行;先检查权限,后执行的那各类其实就是一个代理类,修改后的代码如下:

 

interface Action{
	public void DoAction();
}

class ViewAction implements Action{
	public void DoAction(){
		System.out.println("查看信息!");
	}
}

class AddAction implements Action{
	public void DoAction(){
		System.out.println("添加信息!");
	}
}

class ProxyViewAction implements Action {
	private Action action = null;
	private User user = new User() ;
	public ProxyViewAction(Action act) {
		action = act;
	}

	public void DoAction() {
		// 调用权限类的方法取得用户权限
		if (user.getPermission().equals("VIEW")) {
			action.DoAction();
		}
	}
}

//用户信息
class User{
	private String permission = "VIEW" ;

	public String getPermission() {
		return permission;
	}

	public void setPermission(String permission) {
		this.permission = permission;
	}
}

public class proxy {
	public static void main(String[] args){
		ProxyViewAction proxy = new ProxyViewAction(new ViewAction());
		proxy.DoAction();
		//将用户信息的权限变成ADD,则上面的方法不能执行。
	  }
}

 在我们的ProxyViewAction类中,除了做了客户真正想要做的动作:DoAction()以外,还进行了额外的动作检查用户的权限。而作核心动 作DoAction()是在一个干干净净的类:ViewAction中进行,这个类只做核心动作,对其他的不关心,满足了单一职责原则。

 

客户端通过调用代理类来执行动作,而代理类一是将权限判断和动作的执行分离开来,满足了单一职责原则

 

代理又被称为委派,说的是代理类并不真正的执行那个核心动作,而是委派给另外一个类去执行,如ProxyView类中,ProxyView类并没有真正执行doAction()方法,而是交给ViewAction类去执行。

 

我们再来看代理类ProxyViewAction,可以看到它不仅依赖于接口Action,而且依赖于具体的实现ViewAction。这样对我们的系统 扩展很不利,比如我们有Add动作、Delete动作、Modify动作等等,我们需要对每一个动作都写一个代理类,而这些代理类都做同样的事情,先进行 权限判断,然后再委派。所以我们需要对这些代理再进行一次抽象,让它只依赖接口Action,而不依赖于具体的实现。    要实现这样的想法,我们需要将代理类中的具体实现提走,让代理的使用者在运行期提供具体的实现类,即所谓的依赖注入,代码如下


interface Action{
	public void DoAction();
}

class ViewAction implements Action{
	public void DoAction(){
		System.out.println("查看信息!");
	}
}

class AddAction implements Action{
	public void DoAction(){
		System.out.println("添加信息!");
	}
}

class ProxyAction implements Action {
	private Action action = null;
	private User user = new User() ;
	public ProxyAction(Action act) {
		action = act;
	}

	public void DoAction() {
		// 调用权限类的方法取得用户权限
		if (user.getPermission().equals(action.getClass().getSimpleName())) {
			action.DoAction();
		}
	}
}

//用户信息
class User{
	private String permission = "ViewAction" ;

	public String getPermission() {
		return permission;
	}

	public void setPermission(String permission) {
		this.permission = permission;
	}
}

public class proxy {
	public static void main(String[] args){
		Action action = new ProxyAction(new ViewAction());
		action.DoAction();
		//将用户信息的权限变成AddView,则上面的方法不能执行。
	  }
}

 这样,我们就将所有实现了Action接口的实现使用一个代理类来代理它们。除了ViewAction类能用,以后扩展的AddAction、       ModifyAction、DeleteAction类等等,都可以使用一个代理类:ProxyAction。

 

    而我们的客户端类似如下:
Action action = new ProxyAction(new ViewAction());
action.DoAction();

    通过对代理类的依赖注入,我们使得代理类初步有了一定扩展性。但是我们还要看到,这个代理类依赖于某一个确定的接口。这仍然不能满足我们的实际要求,如我 们的系统的权限控制一般是整个系统级的,这样系统级的权限控制,我们很难在整个系统里抽象出一个统一的接口,可能会有多个接口,按照上面的代理模式,我们 需要对每一个接口写一个代理类,同样,这些类的功能都是一样的。这显然不是一个好地解决办法。

    基于上面的原因,我们需要解决一个系统在没有统一的接口的情况下,对一些零散的对象的某一些动作使用代理模式的问题。JAVA API为我们引入了动态代理或动态委派的技术。

   
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值