设计模式-代理模式

个人博客原文链接

简介

  • 给目标对象(被代理对象)提供一个代理对象,并由代理对象控制对目标对象(被代理对象)的引用,代理对象相当于一个中介。
  • 通过引入代理对象的方式来间接访问目标对象,防止直接访问对象给系统带来不必要的复杂性。
  • 相当于,代理对象拥有被代理对象的所有功能,并且代理对象还添加了额外的功能来控制被代理对象。

静态代理

代理类与被代理类实现同一个接口,将被代理类组合到代理类中并添加控制操作。
实例:
共同的接口

public interface Sourceable {  
	    public void method();  
	}      

被代理类

public class Source implements Sourceable {  
	  
	    public void method() {  
	        System.out.println("the original method!");  
	    }  
	}

代理类

public class Proxy implements Sourceable {  
	  
	    private Source source;  
	    public Proxy(Source source){  
	        this.source = source;  
	    }  
	    public void method() {  
	        before();  
	        source.method();  
	        atfer();  
	    }  
	    private void atfer() {  
	        System.out.println("after proxy!");  
	    }  
	    private void before() {  
	        System.out.println("before proxy!");  
	    }  
}  

测试类

public class ProxyTest {  
	    public static void main(String[] args) {  
	        Source target = new Source();
	        Sourceable proxy = new Proxy(target);  
	        proxy.method();  
	    }  
	} 

动态代理

设计动态代理类时,不需要显式实现与被代理类相同的接口,而是将这种实现推迟到程序运行时由JVM来实现。
通过Java反射机制的method.invoke(),通过调用动态代理类对象方法,从而自动调用目标对象的方法。
实例:假设一个系统中有三个简单角色,“游客”,“会员”,“管理员”,当用一个用户User进行查看其它用户信息功能showUsersInfo的时候,但是只有管理员才能有权限使用这个功能。
用户类

public class User {
    String name;
    String id;

    public User(String name, String id) {
        this.name = name;
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    @Override
    public String toString() {
        return "User{" +
                "namae='" + name + '\'' +
                ", id='" + id + '\'' +
                '}';
    }
}

用户操作接口

public interface UserService {
    public void showUsersInfo(User user);
}

用户操作类(被代理类)

public class UserServiceIpm implements UserService {
    private User user;

    public UserServiceIpm(User user) {
        this.user = user;
    }

    @Override
    public void showUsersInfo(User user) {
        System.out.println(user);
    }

    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }
}

用户操作代理类(代理类)

public class UserServiceProxy implements InvocationHandler{
    private Object target; //被代理对象

    public UserServiceProxy(Object target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("代理");
        target = (UserServiceIpm)target;
        String name = ((UserServiceIpm) target).getUser().name;
        if (name=="管理员"){
            Object o = method.invoke(target,args);
            return o;
        }else{
            System.out.println("没有权限");
            return null;
        }
    }
}

测试类

public class Test {
    public static void main(String[] args) {
        User u1 = new User("游客","2");
    //  User u1 = new User("管理员","2");
        //创建被代理对象target
        UserService target = new UserServiceIpm(u1);
        //获取被代理对象类类型
        Class<? extends UserService> c = target.getClass();
        //获取被代理对象的类加载器
        ClassLoader classLoader = c.getClassLoader();
        //获取被代理对象实现的接口
        Class<?>[] interfaces = c.getInterfaces();
        //创建代理类对象h,传被代理类对象target过去
        InvocationHandler h = new UserServiceProxy(target);
        //被代理类创建代理
        UserService proxy = (UserService) Proxy.newProxyInstance(classLoader, interfaces, h);
        User user = new User("会员","1");
        target.showUsersInfo(user);
        System.out.println("--------");
        proxy.showUsersInfo(user);
    }
}

两者的区别

  • 静态代理
    • 代理单一目标对象
    • 在代理类实现时就指定与被代理类相同的接口(运行前)
    • 优点
      • 降低了系统的耦合度
      • 代理对象作为客户端和目标对象之间的中介,起到了保护目标对象的作用
    • 缺点
      • 增加了代理对象,因此会造成请求的处理速度变慢
      • 增加了系统实现的复杂度
  • 动态代理
    • 代理多个目标对象
    • 不需要显式实现与被代理类相同的接口,而是将这种实现推迟到程序运行时由JVM来实现。(运行时)
    • 优点
      • 只需要1个动态代理类就可以解决创建多个静态代理的问题
      • 灵活性强,在使用时(调用被代理类对象)才会动态创建动态代理类实例,不需要事先实例化
    • 缺点
      • 效率低,需要先通过Java反射机制,间接调用目标对象方法。
      • 只能针对接口创建代理类,不能针对类创建代理类,即只能动态代理 实现了接口的类。
    • 具体应用场景:面向切面编程(AOP),日志记录、性能统计、安全控制、异常处理等
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值