设计模式之代理模式(Proxy)

Proxy是"代理人"的意思,它指的是替代别人进行工作的人。当不一定需要本人亲自进行工作时,就可以寻找代理人去完成工作。但代理人毕竟是代理人,能代替本人做的事情终究时有限的,因此,当代理人遇到无法自己解决的事情时就会去找本人解决该问题。

我们平时在租房子的时候,通常不会直接面对房东,而是会找一个房屋中介(赚差价的那种中间商),中介会带我们去看房,我们会和中介签订合同。在这个例子中,中介就扮演着代理的角色。

如果要编码实现代理模式,有两种方式,一种是静态代理,另一种是动态代理。

类图

1.静态代理

(1)优点:在不修改目标对象的功能前提下,能通过代理对象对目标功能扩展

(2) 缺点:因为代理对象需要与目标对象实现一样的接口,所以会有很多代理类

(3)一旦接口增加方法,目标对象与代理对象都要维护

 
//出租   统一的接口  
public interface Rent {
​
    public void rent();
    
}
​
​
//房东    实现了出租接口
public class Host implements Rent{
​
    @Override
    public void rent() {
        System.out.println("房东要出租房子了!");
    }
​
}
​

 

​
//房屋中介(代理类)   也实现了出租接口
public class HostProxy implements Rent{
​
    private Rent rent;
    
    public HostProxy(Rent rent) {
        this.rent=rent;
    }
    
    @Override
    public void rent() {
        seeHouse();
        //真正使用的是房东的出租方法
        rent.rent();
        fare();
    }
​
    public void seeHouse() {
        System.out.println("中介带看房子!");
    }
​
    public void fare() {
        System.out.println("中介收费");
    }
}
​
​
//使用者  测试类
public class Client {
    
    public static void main(String[] args) {
        
        Host host=new Host();
        
        HostProxy proxy=new HostProxy(host);
        
        proxy.rent();
    }
​
}
​

 

2.动态代理

一个被代理的类就需要一个代理类,那么当有多个类需要被代理的时候,就要生成多个代理类。这会造成代码剧增,显然这种情况我们是不希望看到的。于是就有了动态代理类。动态代理是spring中AOP实现的底层原理,其重要性不言而喻!

(1)代理对象,不需要实现接口,但是目标对象要实现接口,否则不能用动态代理

(2)代理对象的生成,是利用JDK的API,动态的在内存中构建代理对象

(3)动态代理也叫做:JDK代理,接口代理

//出租   统一的接口  
public interface Rent {
​
    public void rent();
    
}
//房东    实现了出租接口
public class Host implements Rent{
​
    @Override
    public void rent() {
        System.out.println("房东要出租房子了!");
    }
​
}
​
//通用的代理类
public class ProxyInvocationHandler implements InvocationHandler{
​
    //被代理的接口
    private Object target;
    
    public void setTarget(Object target) {
        this.target=target;
    }
    
    //生成得到代理类
    public Object getProxy() {
        /**
         * 参数说明
         * 1.ClassLoader loader :指定当前目标对象使用的类加载器,获取加载器的方法固定
         * 2. Class<?>[] interfaces :目标对象实现的接口类型,使用泛型方法确认类型
         * 3.InvocationHandler h :事情处理,执行目标对象的方法时会触发事件处理器方法,
         * 会把当前执行的目标对象方法当成参数传入
         */
        return Proxy.newProxyInstance(this.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
    }
    
    //处理代理实例,并返回结果
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        log(method.getName());
        //动态代理的本质,就是使用动态反射机制实现!
        //反射机制调用目标对象的方法
        Object result=method.invoke(target, args);
        return result;
    }
    
    public void log(String msg){
        System.out.println("执行了"+msg+"方法");
    }
    
}
​
​
//使用者  测试类
public class Client {
    
    public static void main(String[] args) {
        //真实角色
        Host host=new Host();
        
        //代理角色:现在没有
        RentsProxyInvocationHandler pih=new RentsProxyInvocationHandler();
        //通过调用程序处理角色来处理我们要调用的对象接口
        pih.setRent(host);
        //这里的proxy就是动态生成的,我们并没有写
        Rent proxy=(Rent) pih.getProxy();
        proxy.rent();
    }
​
}

3.在proxy模式中有一下登场角色

Subject(主体)

subject角色定义了使proxy角色和realSubject角色之间具有一致性的接口。由于存在subject角色,所以client角色不必在意它所使用的究竟是proxy角色还是realSubject角色。在示例程序中,由Rent接口扮演此角色。

Proxy(代理人)

proxy角色会尽量处理来自Client角色的请求。只有当自己不能处理时,它才会将工作交给RealBoject角色。在实例程序中,由HostProxy类扮演此角色。

RealSubject(实际的主体)

“本人”RealSubject角色会在“代理人”无法胜任工作时出场。它与Proxy角色一样,也实现了在Subject角色中定义的接口(API)。在实例程序中,由Host扮演此角色。

Client(请求者)

使用proxy模式的角色,client角色并不包含在proxy模式中。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值