浅析代理模式

为什么使用代理模式?

先举个栗子:

Worker的职责是工作:

public interface Worker {//工人
    void work();//工作
}

而Worker又分很多类型,比如说医生,教师,程序员…

就拿医生来说:

public class Doctor implements Worker {
    @Override
    public void work() {
        cure();//医生工作是治病
    }

    private void cure() {
        Log.e("TAG", "Doctor is working");
    }
}

调度程序:

public class ScheduleHandler {
    public static void startWork() {
       new Doctor().work();
    }
}

Worker开始工作:

   public void main(String[] args) {
        ScheduleHandler.startWork();
    }

Worker的一次工作完成了.

现在要给Doctor增加一个签到功能,我们可以在Doctor中直接增加一个签到功能,但是如果我们要给所有职业的Worker都增加签到的功能,是不是要给所有Worker(如:Teacher,Programmer,Designer…)中都增加相同的代码呢,这样做确实可以达到目的,但是增加了大量重复的代码,这时就可以使用代理模式了.

Worker的代理类:

public class ProxyWorker implements Worker {
    private Worker worker;

    public ProxyWorker(Worker doctor) {
        this.worker = doctor;
    }

    @Override
    public void work() {
        signIn();//签到
        worker.work();
    }

    private void signIn() {
        Log.e("TAG", "Worker signed in");
    }
}

我们的调度程序需要做出改变:

public class ScheduleHandler {
    public static void startWork() {
        new ProxyWorker(new Doctor()).work();
    }
}

Worker开始工作:

   public void main(String[] args) {
        ScheduleHandler.startWork();
    }

这样我们给Doctor增加了签到的功能,而且其他职业的Worker(如:Teacher,Programmer,Designer…)也可以使用ProxyWorker来实现签到的功能,代理模式是不是大大减少了我们的代码量,这就是我们为什么要使用代理模式的原因了.

为什么使用动态代理模式

还是接着上面的例子,现在有Student(与Worker同级)也需要一个签到的功能

public interface Student {
    void study();
}

初中生:

public class Junior implements Student {
    @Override
    public void study() {
        Log.e("TAG", "Junior is stutying");
    }
}

如果按照上面ProxyWorker的思想,我们可以再写一个ProxyStudent来代理所有级别Student(如:小学生,初中生,高中生…),并在ProxyStudent中加入签到的方法,可如果我们还想更省事些怎么办?这时就可以使用动态代理了:

    class ProxyHandler implements InvocationHandler {
        private Object tartget;

        public ProxyHandler(Object doctor) {
            this.tartget = doctor;
        }

        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            if ("work".equals(method.getName())) {
                Log.e("TAG", "worker signed in");
            }
            if ("study".equals(method.getName())) {
                Log.e("TAG", "student signed in");
            }
            return method.invoke(tartget, args);
        }
    }

invoke中,我们根据方法名来区别是Worker还是Student做签到的动作

分别让Student,Worker去签到学习/工作:

public void main(String[] args) {
    Student junior = new Junior();
    InvocationHandler handler1 = new ProxyHandler(junior);
    Student student = (Student) Proxy.newProxyInstance(
    junior.getClass().getClassLoader(), junior.getClass().getInterfaces(), handler1);
    student.study();


    Worker doctor = new Doctor();
    InvocationHandler handler2 = new ProxyHandler(doctor);
    doctor.getClass().getClassLoader(), doctor.getClass().getInterfaces(), handler2);
    worker.work();
}

打印结果:
TAG: student signed in
TAG: Junior is stutying
TAG: worker signed in
TAG: Doctor is working

上例中我们可以发现,通过动态代理我们可以动态的获取到方法名,还有代理类的实例,当然动态代理能获取都的信息不仅仅是这些,通过动态代理的能够动态获取信息的特性,我们就可以完成一些特殊的操作.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值