设计模式-代理模式-以权限控制为例

简介

代理模式是指为一些对象提供一个代理来控制外部对于这些对象的访问。这样避免了客户端直接访问外部对象。
代理模式在生活中非常的常见,中介也是代理的一种。代理不止可以提供对对象的控制也可以扩充访问对象本身的功能。
在JAVA中代理模式根据代理类生成的时机又可以分为静态代理和动态代理,静态代理代理类在编译期生成,而动态代理代理类在Java运行时动态生成。

适用场景

(1)当客户端对象需要访问远程主机中的对象时可以使用远程代理。
(2)当需要用一个消耗资源较少的对象来代表一个消耗资源较多的对象,从而降低系统开销、缩短运行时间时可以使用虚拟代理,例如一个对象需要很长时间才能完成加载时。
(3)当需要为某一个被频繁访问的操作结果提供一个临时存储空间,以供多个客户端共享访问这些结果时可以使用缓冲代理。通过使用缓冲代理,系统无须在客户端每一次访问时都重新执行操作,只需直接从临时缓冲区获取操作结果即可。
(4)当需要控制对一个对象的访问,为不同用户提供不同级别的访问权限时可以使用保护代理。
(5)当需要为一个对象的访问(引用)提供一些额外的操作时可以使用智能引用代理。

代理模式结构

代理模式主要由三部分构成:

  1. 抽象主题类:定义开放给代理类的真正主题类接口。
  2. 真正主题类:实现抽象主题类中的接口功能,是被代理对象
  3. 代理类:提供与真实主题相同的接口,其内部含有对真实主题的引用,可以访问、控制、扩展真实主题的功能

案例

这里我举一个非常简单的例子,就是对服务器通过代理做一个访问控制,由代理来管理服务器权限,当然在实际中的访问控制比这个要复杂的多

静态代理

抽象主题类

public interface ServerInterface {
    void access();
    void setLevel(int i);
}

真正主题类

public class Server implements ServerInterface{
    @Override
    public void access() {
        System.out.println("访问成功");
    }
    //服务器不负责权限控制
    @Override
    public void setLevel(int i) {

    }
}

代理类

public class ServerProxy implements ServerInterface{
    private Server server=new Server();
    private int level=0;


    @Override
    public void access() {
        if(level<3){
            System.out.println("权限不足");
            return ;
        }
        System.out.println("权限验证通过");
        server.access();
    }

    @Override
    public void setLevel(int i) {
        this.level=i;
    }
}

测试

  @Test
    public void proxy()
    {
        ServerProxy serverProxy=new ServerProxy();
        serverProxy.setLevel(3);
        serverProxy.access();
    }

测试结果

权限验证通过
访问成功

动态代理

关于动态代理的原理我这里不做介绍,常用的JAVA动态代理也有JDK与CGlib两种方式,我这里写一下JDK动态代理的实现方法。

抽象主题类和具体主题类和上面一致

代理类

public class ServerProxyFactory {
    private int level=0;
    private Server server=new Server();
    public ServerInterface getProxyObject(){
        ServerInterface serverInterface = (ServerInterface) Proxy.newProxyInstance(server.getClass().getClassLoader(), server.getClass().getInterfaces(), new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                if(method.getName().equals("setLevel")) {
                    level=(int)args[0];
                    System.out.println("权限等级设为:"+level);
                }
                if(method.getName().equals("access")){
                    if(level<3){
                        System.out.println("权限不足");
                        return null;
                    }
                    System.out.println("权限通过,允许访问");
                }
                Object obj = method.invoke(server, args);
                return obj;
            }
        });
        return serverInterface;
    }
}

测试类

    @Test
    public void proxy()
    {
        ServerProxyFactory serverProxyFactory=new ServerProxyFactory();
        ServerInterface proxyObject = serverProxyFactory.getProxyObject();
        proxyObject.setLevel(1);
        proxyObject.access();
    }

测试结果

权限等级设为:1
权限不足

总结

代理模式的应用在实际中非常多,这里无法全部一一介绍,每个代理模式应用的具体实现也可能会有较大的区别,不过通过案例也可以了解到,代理模式本身相当于在客户端与目标对象直接额外增加一层关口,可以起到管控的作用也可以起到扩展的作用。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
代理模式是一种结构型设计模式,它允许你提供一个代理对象,用来控制对另一个对象的访问。在 TypeScript 中,可以使用接口来定义代理对象和被代理对象的共同接口,并使用类来实现代理对象和被代理对象。 下面是一个简单的 TypeScript 代理模式示例: ```typescript interface Subject { request(): void; } class RealSubject implements Subject { public request(): void { console.log("RealSubject: Handling request."); } } class Proxy implements Subject { private realSubject: RealSubject; constructor(realSubject: RealSubject) { this.realSubject = realSubject; } public request(): void { if (this.checkAccess()) { this.realSubject.request(); this.logAccess(); } } private checkAccess(): boolean { console.log("Proxy: Checking access prior to firing a real request."); return true; } private logAccess(): void { console.log("Proxy: Logging the time of request."); } } function clientCode(subject: Subject) { subject.request(); } console.log("Client: Executing the client code with a real subject:"); const realSubject = new RealSubject(); clientCode(realSubject); console.log(""); console.log("Client: Executing the same client code with a proxy:"); const proxy = new Proxy(realSubject); clientCode(proxy); ``` 在这个示例中,`Subject` 接口定义了被代理对象(`RealSubject`)和代理对象(`Proxy`)的共同接口。`RealSubject` 实现了 `Subject` 接口,表示真正的对象。而 `Proxy` 类也实现了 `Subject` 接口,成为真正对象的代理。 `Proxy` 类包含一个指向 `RealSubject` 对象的引用,当客户端调用 `request()` 方法时,它会首先执行 `checkAccess()` 方法来检查是否有足够的权限来访问真正的对象。如果有,它会调用 `RealSubject` 对象的 `request()` 方法,并在访问结束后记录访问时间。 客户端代码可以使用 `RealSubject` 对象或 `Proxy` 对象来执行 `request()` 方法,因为它们都实现了 `Subject` 接口。但是,使用代理对象可以提供更多的控制和安全性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值