小白谈谈代理模式

概念

一个类代表另一个类的功能,就好比我们生活中的中介,我们要把楼卖出去,可是我们不可能天天在大街上问,有没有人愿意买我的楼嘛,中介就是帮我们干这件事,相当于我们的代理,中介跟我们都是有卖楼这同一操作的,但是真正卖楼的具体操作还是我们,中介只是负责找客户。


静态代理

案例:我们都玩过游戏吧,有些游戏只能在国外玩,如果想在国内玩,那肯定得有个代理商才行。今年国外最火的游戏《寸头大作战》想在国内开拓业务,于是找了小明做代理商。

实现代码如下:
首先,游戏最重要的就是赚钱了,所以定义一个游戏的接口:

public interface Game {

    //赚钱
    public void makeMoney();
}

接下来实例化《寸头大作战》的代码:

public class Ctb implements Game {
    @Override
    public void makeMoney() {
        System.out.println("今年盈利:" + new Random().nextInt(100) + "亿");
    }
}

小明做代理,那肯定也得有小明这个类:

public class XiaoMing implements Game {

    private Ctb ctb;

    public XiaoMing() {
        this.ctb = new Ctb();
    }

    @Override
    public void makeMoney() {
        System.out.println("通过小明代理");
        this.ctb.makeMoney();
    }
}

最后就是测试类了:

public class Main {

    public static void main(String[] args) {

        //国内想玩游戏,得找小明代理才行
        XiaoMing xiaoMing = new XiaoMing();

        xiaoMing.makeMoney();
    }
}

实验结果:
在这里插入图片描述
如果此时,小红听到了这个游戏这么赚,她也想当个代理,那么我们来帮她实现吧:

public class XiaoHong implements Game {
    private Ctb ctb;

    public XiaoHong() {
        this.ctb = new Ctb();
    }

    @Override
    public void makeMoney() {
        System.out.println("通过小红代理");
        this.ctb.makeMoney();
    }
}

测试类:

public class Main2 {

    public static void main(String[] args) {

        //国内想玩游戏,得找小明,小红代理才行
        XiaoMing xiaoMing = new XiaoMing();
        XiaoHong xiaoHong = new XiaoHong();


        xiaoMing.makeMoney();
        xiaoHong.makeMoney();
    }
}

实验结果:
在这里插入图片描述
我们可以看出,静态代理实现的时候,我们需要给代理人都实现Game的接口,他们得有共同的方法才行。

JDK方式动态代理

上面的例子中,如果我们要实现的不只是小明,小红,而是其他人,如果按照静态代理的方式,没新建一个代理人,都需要重新建一个类,如果不断变换,那就需要不断更新类,因此引入动态代理的概念。
同样的先定义一个游戏的接口:

public interface Game {

    //赚钱
    void makeMoney();
}

我们这次想定义一个人的类,里面包含名字这一参数

public class Person implements Game {

    private String name;

    public Person(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

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

    @Override
    public void makeMoney() {
        System.out.println("今年盈利:" + new Random().nextInt(100) + "亿");
    }
}

接下来就是我们的代理类了,这个代理类继承InvocationHandler类,其中这个动态代理的类中的参数可以进行任意修改,可以改为任意的Object类

public class DynamicProxyHandler implements InvocationHandler {

    private Person person;

    public DynamicProxyHandler(Person person) {
        this.person = person;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("我们现在找的代理人是:" + person.getName());
        Object o = method.invoke(person,args);
        return o;
    }
}

测试类:

public class Main {

    public static void main(String[] args) {
		
		//实例一个代理对象
        Person person = new Person("花花");
		
		//通过放射技术,进行动态生成
        Game game = (Game) Proxy.newProxyInstance(
	        Person.class.getClassLoader(),
	        new Class[]{Game.class},
	        new DynamicProxyHandler(person));

        game.makeMoney();
    }
}

实验结果:
在这里插入图片描述

Cglib代理

该方法不用定义接口,首先定义的是被代理对象,也就是上文案例中的游戏《寸头大作战》:

public class Ctb {

    public void makeMoney(){
        System.out.println("今年盈利:" + new Random().nextInt(100) + "亿");
    }
}

接下来还需要写的是代理人:

public class Person implements MethodInterceptor {

    private String name;

    public Person(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

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

    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {

        //打印要代理的类
        System.out.println(o.getClass().getSuperclass().getName());

        //打印代理人
        System.out.println("现在的代理人为:" + getName());
        Object result = null;
        result = methodProxy.invokeSuper(o, objects);
        return result;
    }
}

其中这个方法有点特殊,需要进行导包,这里就使用maven进行配置,在pom.xml中进行配置:

	<dependencies>
        <dependency>
            <groupId>cglib</groupId>
            <artifactId>cglib</artifactId>
            <version>3.2.12</version>
        </dependency>
    </dependencies>

测试类:

public class Main {

    public static void main(String[] args) {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(Ctb.class);
        enhancer.setCallback(new Person("花花"));
        Ctb ctb = (Ctb) enhancer.create();
        ctb.makeMoney();
    }
}

测试结果:
在这里插入图片描述

总结:如果被代理对象有定义接口类,就使用JDK方式动态代理,如果没有定义接口类,就使用Cglib代理,静态代理局限性太大,无须考虑。


本文的代码:https://pan.baidu.com/s/1ubFxLFGBosES0Qzq3WhzAg
提取码:vngc

发布了48 篇原创文章 · 获赞 0 · 访问量 649

猜你喜欢

转载自blog.csdn.net/weixin_44943485/article/details/105366482
今日推荐