代理模式的运用
考虑这样一种情况。某个系统要根据用户的权限来判断是否能操作。那么可以这么写:
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();