Java代理模式

Java 代理模式

代理的作用

​ 想象一个场景。我们一个项目已经开发完成,并且部署了很长一段时间。但是突然需要功能更新,那必然涉及到代码的修改。但是我们也知道稍微不注意的修改,出错了,整个项目就很爆炸了。

​ 所以为了不破坏已经完善封装的代码。我们又想要给我们的某些功能做一些增强。我们就可以使用代理,建立一个代理类。

静态代理

静态代理的基本模式
  1. 定义一个接口

    interface Animal{
        public void eat();
    }
    
  2. 写一个类实现接口

    class Dog implements Animal{
        @Override
        public void eat() {
            System.out.println("狗在吃骨头");
        }
    }
    
  3. 写一个代理类代理

    class DogProxy implements Animal{
        private Dog dog=new Dog();
    
        @Override
        public void eat() {
            System.out.println("静态代理类前置内容");//在这可以做一些逻辑
            dog.eat();
            System.out.println("静态代理类后置内容");
        }
    }
    
  4. 使用

    public class StaticProxyDemo {
        public static void main(String[] args) {
            Animal dog=new DogProxy();
            dog.eat();
        }
    }
    
静态代理的用法

​ 假设一个场景,我们开发了一系列手机的通话功能,然后我们发布出去了。没过两天,用户提问题了,怎么我输错号码都不带提示的啊。不行了,产品经理跑来让我们改需求了。我们加班一晚上,给每个手机的通话功能加上电话号码验证的逻辑。于是有了以下结果。

//原来代码的样子
interface Phone{
    public void callPhone(String phoneNum);
}
class ApplePhone implements Phone{
    @Override
    public void callPhone(String phoneNum) {
        System.out.println("ApplePhone calling");
    }
}
class MIPhone implements Phone{
    @Override
    public void callPhone(String phoneNum) {
        System.out.println("MIPhone calling");
    }
}
class HuaWeiPhone implements Phone{
    @Override
    public void callPhone(String phoneNum) {
        System.out.println("HuaWeiPhone calling");
    }
}
//更改后
interface Phone{
    public void callPhone(String phoneNum);
}
class ApplePhone implements Phone{
    @Override
    public void callPhone(String phoneNum) {
        /*
        * 因为需求加的验证电话号码的逻辑
        * */
        System.out.println("ApplePhone calling");
    }
}
class MIPhone implements Phone{
    @Override
    public void callPhone(String phoneNum) {
        /*
         * 因为需求加的验证电话号码的逻辑
         * */
        System.out.println("MIPhone calling");
    }
}
class HuaWeiPhone implements Phone{
    @Override
    public void callPhone(String phoneNum) {
        /*
         * 因为需求加的验证电话号码的逻辑
         * */
        System.out.println("HuaWeiPhone calling");
    }
}

​ 我们先不讨论这些逻辑可以抽出来单独写一个方法,这不是重点。重要的是,我们在原来写好的代码里面加了代码,已经不能保证一定不会破坏整个环境。而且不保证会不会更大的更改。

​ 比如之前是void callPhone。没准修改以后是Boolean callPhone(根据这个方法的运行逻辑处理以后项目的运行逻辑)。这样如果项目足够紧凑,那么可能就是一次重构。

​ 而有了代理以后,我们可以这样做。

class PhoneProxy implements Phone {
    private Phone phoneObject;

    PhoneProxy(Phone phone) {
        this.phone = phone;
    }

    @Override
    public void callPhone(String phoneNum) {
        judgePhoneNum(phoneNum);//新增逻辑
        phone.callPhone(phoneNum);
    }
}

动态代理

​ 这里说的是Cglib的动态代理,需要相应的jar包,而cglib以来asm。所以两个包都要导。

package prox;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

class BookFacadeImpl{//没有接口,因为cglib就是对普通类进行增强
    public void addBook(){
        System.out.println("增加图书的方法。。。");
    }
}
//使用Cglib代理
class BookFacadeCglib implements MethodInterceptor{
    private Object target;

    /**
     * 创建代理对象
     * @param target
     * @return
     */
    public Object getInstance(Object target){
        this.target=target;
        Enhancer enhancer=new Enhancer();
        enhancer.setSuperclass(this.target.getClass());
        enhancer.setCallback(this);
        return enhancer.create();
    }

    @Override
    public Object intercept(Object o, Method method, Object[] objects,MethodProxy proxy) throws Throwable {
        System.out.println("方法执行前逻辑");
        proxy.invokeSuper(o,objects);
        System.out.println("方法执行后逻辑");
        return null;
    }
}
public class DynamicProxyDemo {
    public static void main(String[] args) {
        BookFacadeCglib cglib=new BookFacadeCglib();
        BookFacadeImpl bookCglib=(BookFacadeImpl)cglib.getInstance(new BookFacadeImpl());
        bookCglib.addBook();
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java代理模式是一种结构型设计模式,其目的是为其他对象提供一种代理以控制对这个对象的访问。代理对象可以在客户端和目标对象之间充当中介,以便于客户端访问目标对象时,可以在不改变目标对象的情况下添加一些额外的功能,比如安全性、远程访问、缓存等。 在Java中,代理模式可以通过两种方式实现:静态代理和动态代理。静态代理需要手动编写代理类,而动态代理可以在运行时通过反射机制动态生成代理类,更加灵活。 举个例子,假设我们有一个接口`Subject`,其中定义了一些方法。我们希望在调用这些方法时,增加一些额外的日志记录功能。我们可以编写一个代理类`SubjectProxy`,在代理类中实现接口方法并调用目标对象的方法,同时在方法前后添加日志记录的代码。客户端则通过代理类访问目标对象。 静态代理示例代码如下: ```java public interface Subject { void doSomething(); } public class RealSubject implements Subject { @Override public void doSomething() { System.out.println("RealSubject do something."); } } public class SubjectProxy implements Subject { private Subject realSubject; public SubjectProxy(Subject realSubject) { this.realSubject = realSubject; } @Override public void doSomething() { System.out.println("Before do something."); realSubject.doSomething(); System.out.println("After do something."); } } public class Client { public static void main(String[] args) { Subject realSubject = new RealSubject(); Subject subjectProxy = new SubjectProxy(realSubject); subjectProxy.doSomething(); } } ``` 动态代理示例代码如下: ```java public class SubjectHandler implements InvocationHandler { private Object target; public SubjectHandler(Object target) { this.target = target; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("Before " + method.getName()); Object result = method.invoke(target, args); System.out.println("After " + method.getName()); return result; } } public class Client { public static void main(String[] args) { Subject realSubject = new RealSubject(); InvocationHandler handler = new SubjectHandler(realSubject); Subject subjectProxy = (Subject) Proxy.newProxyInstance(realSubject.getClass().getClassLoader(), realSubject.getClass().getInterfaces(), handler); subjectProxy.doSomething(); } } ``` 无论是静态代理还是动态代理代理模式都可以在不改变目标对象的情况下,为其添加额外的功能,提高代码的可复用性和灵活性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值