Java设计模式——代理模式

定义

给某一个对象提供一个代理或占位符,并由代理对象来控制原对象的访问。

角色

(1)Subject(抽象主题角色)

(2)Proxy(代理主题角色)

(3)RealSubject(真实主题角色)

分类

(1)根据适用范围,代理模式可以分为:远程代理、虚拟代理、保护代理、智能引用等。

远程代理:为一个对象在不同的地址空间提供局部代表,这样系统可以将Server部分的事项隐藏。

虚拟代理:如果要创建一个资源消耗较大的对象,可以先用一个代理对象表示,在真正需要的时候才真正创建。

保护代理:用代理对象控制对一个对象的访问,给不同的用户提供不同的访问权限。

智能引用:在引用原始对象的时候附加额外操作,并对指向原始对象的引用增加引用计数。

(2)从代码的角度来分,代理可以分为两种:一种是静态代理,另一种是动态代理。

静态代理:在程序运行前就已经存在了代理类,并且明确了代理类和委托类之间的关系。

动态代理:代理类是在程序运行的过程中根据反射等机制动态生成的,在程序运行前,没有明确的代理类。代理类和委托类关系是在程序运行时确定的。
 

静态代理

下面我们以TeacherA请假一天,不能来教课,请TeacherB代理TeacherA来教课一天为例,说一下静态代理。在这里,代理类和委托类都已经明确。相当于A委托B

代理类:TeacherB 

委托类:TeacherA

/**
 * 抽象主题类
 */
public interface People {
    void teach();
}

/**
 * 具体主题类(委托类)
 */
public class TeacherA implements People{
    @Override
    public void teach() {
        Log.e("=====","===我是老师A,请假一天,需要B老师代我上一天课==");
    }
}
/**
 * 代理类
 */
public class TeacherB implements People {
    private TeacherA teacherA=new TeacherA();

    @Override
    public void teach() {
        Log.e("=========","====我是老师B=====");
        teacherA.teach();//调用了被代理者的teach()方法,
    }
}

使用:

public class TestStaticProxy {
    public static void main(String[] args) {
        People teacherB=new TeacherB();
        teacherB.teach();
    }
}

动态代理

我们还以TeacherA请假一天,不能来上课为例,来找个代理,代替TeacherA教课一天,不过在这里和静态代理有所区别的是我们事先没有选择哪个类为代理类。

动态代理(Dynamic Proxy)可以让系统在运行时根据实际需要来动态创建代理类。让同一个代理类能够代理多个不同的真实主题类而且可以代理不同的方法。使用Java反射机制自动生成代理类,在运行时绑定原始对象和代理对象,无需手动编写代理类,但原始对象必须实现接口。

Java从JDK1.3开始引入了对动态代理的支持。Java语言实现动态代理需要用到位于java.lang.reflect包中的一些类。

下面我就说一下动态代理的实现方式。

(1)创建一个类,实现InvocationHandler接口,重写invoke方法:

public class MyHandler implements InvocationHandler {
    People people;
    public MyHandler( People people){
        this.people=people;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        return method.invoke(people,args);
    }
}

(2)使用Proxy类的newProxyInstance方法,创建代理类的对象:

public class TestDynamicProxy {
    public static void main(String[] args) {
        People people=new TeacherA();
        MyHandler myHandler=new MyHandler(people);

        People proxy= (People) Proxy.newProxyInstance(people.getClass().getClassLoader(),new Class[]{People.class},myHandler);
        proxy.teach();
    }
}

静态代理和动态代理的比较

静态代理的缺点:

(1)静态代理如果接口新增一个方法,除了所有实现类(真实主题类)需要实现这个方法外,所有代理类也需要实现此方法。增加了代码维护的复杂度。违背了开放封闭原则。

(2)代理对象只服务于一种类型的对象,如果要服务多类型的对象。必须要为每一种对象进行代理,静态代理在程序规模稍大时就无法胜任了。

动态代理的优点:

(1)可以通过一个代理类完成全部的代理功能,接口中声明的方法都被转移到调用处理器一个集中的方法中处理(InvocationHandler.invoke)。当接口方法数量较多时,我们可以进行灵活处理,而不需要像静态代理那样每一个方法进行中转。

(2)动态代理的应用使我们的类职责更加单一,复用性更强。

优点

(1)能够协调调用者和被调用者,在一定程度上降低了耦合度

(2)客户端可以针对抽象主题角色进行编程,增加和更换代理类无须修改源代码,符合开闭原则,系统具有较好的灵活性和可扩展性。

缺点

(1)由于在客户端和真实主题之间加了代理对象,因此有些类型的代理模式可能会造成请求速度的变慢,如保护代理。

(2)实现代理模式需要额外的工作,而且有些代理模式的实现过程比较复杂,例如远程代理。

相关文章:Java 代理模式的基本概念、使用场景、应用示例和实现方法_java代理模式的应用场景_wljslmz的博客-CSDN博客

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值