设计模式之代理模式

一、什么是设计模式

设计模式(Design pattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性。 毫无疑问,设计模式于己于他人于系统都是多赢的,设计模式使代码编制真正工程化,设计模式是软件工程的基石,如同大厦的一块块砖石一样。项目中合理的运用设计模式可以完美的解决很多问题,每种模式在现在中都有相应的原理来与之对应,每一个模式描述了一个在我们周围不断重复发生的问题,以及该问题的核心解决方案,这也是它能被广泛应用的原因。简单说:

模式:在某些场景下,针对某类问题的某种通用的解决方案。

场景:项目所在的环境

问题:约束条件,项目目标等

解决方案:通用、可复用的设计,解决约束达到目标。

二、设计模式的三个分类

创建型模式:对象实例化的模式,创建型模式用于解耦对象的实例化过程。

结构型模式:把类或对象结合在一起形成一个更大的结构。

行为型模式:类和对象如何交互,及划分责任和算法。

如下图所示:
在这里插入图片描述
创建型:
单例模式:https://blog.csdn.net/Platinum_stars/article/details/108284748
结构型:
代理模式:https://blog.csdn.net/Platinum_stars/article/details/108284483
行为型:
模板模式:https://blog.csdn.net/Platinum_stars/article/details/108284889

代理模式

代理模式:为其他对象提供一个代理以便控制这个对象的访问。

代理模式就是给一个对象提供一个代理,并由代理对象控制对原对象的引用。它使得客户不能直接与真正的目标对象通信。代理对象是目标对象的代表,其他需要与这个目标对象打交道的操作都是和这个代理对象在交涉。

代理对象可以在客户端和目标对象之间起到中介的作用,这样起到了的作用和保护了目标对象的,同时也在一定程度上面减少了系统的耦合度。
在这里插入图片描述
代理模式包含如下角色:

  • Subject: 抽象主题角色
  • Proxy: 代理主题角色
  • RealSubject: 真实主题角色

静态代理

/**
 * 静态代理举例
 * <p>
 * 特点:代理类和被代理类在编译期间,就确定下来了。
 *
 * @author Ankang Huang
 * @date 2020/8/27 17:21
 */
public class StaticProxyTest {

    public static void main(String[] args) {
        // 创建被代理类的对象
        NikeClothFactory nikeClothFactory = new NikeClothFactory();
        // 创建代理类的对象
        ProxyClothFactory proxyClothFactory = new ProxyClothFactory(nikeClothFactory);
        proxyClothFactory.produceCloth();
    }
}

interface ClothFactory {
    void produceCloth();
}

class ProxyClothFactory implements ClothFactory {
    private ClothFactory factory;// 用被代理类对象进行实例化

    public ProxyClothFactory(ClothFactory factory) {
        this.factory = factory;
    }

    @Override
    public void produceCloth() {
        System.out.println("代理类准备工作");
        factory.produceCloth();
        System.out.println("代理类处理收尾");
    }
}

class NikeClothFactory implements ClothFactory {

    @Override
    public void produceCloth() {
        System.out.println("Nike工产生产一批鞋子");
    }
}

动态代理

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * 动态代理
 *
 * @author Ankang Huang
 * @date 2020/8/27 17:28
 */
public class ProxyTest {

    public static void main(String[] args) {

        SuperMan man = new SuperMan();
        //proxyInstance:代理类的对象
        Human human = (Human) ProxyFactory.getProxyInstance(man);
        //当通过代理类对象调用方法时,会自动的调用被代理类中同名的方法
        String belief = human.getBelief();
        System.out.println(belief);
        human.eat("饭");

        System.out.println("************");

        NikeClothFactory nikeClothFactory = new NikeClothFactory();

        ClothFactory proxyClothFactory = (ClothFactory) ProxyFactory.getProxyInstance(nikeClothFactory);

        proxyClothFactory.produceCloth();
    }
}

interface Human {

    String getBelief();

    void eat(String food);
}

/**
 * 被代理类
 */
class SuperMan implements Human {

    @Override
    public String getBelief() {
        return "I believe I can fly!";
    }

    @Override
    public void eat(String food) {
        System.out.println("我喜欢吃" + food);
    }
}

class HuManUtil {

    public void method1() {
        System.out.println("------通用一------");
    }

    public void method2() {
        System.out.println("------通用二------");
    }
}

/**
 * 要想实现动态代理,需要解决的问题?
 * 问题一:如何根据加载到内存中的被代理类,动态的创建一个代理类及其对象。
 * 问题二:当通过代理类的对象调用方法a时,如何动态的去调用被代理类中的同名方法a。
 */
class ProxyFactory {

    // 调用此方法,返回一个代理类的对象。解决问题一
    public static Object getProxyInstance(Object object) {// object 被代理对象
        MyInvocationHandler handler = new MyInvocationHandler();
        handler.bind(object);
        return Proxy.newProxyInstance(object.getClass().getClassLoader(), object.getClass().getInterfaces(), handler);
    }

}

class MyInvocationHandler implements InvocationHandler {

    private Object object;// 需要使用被代理类的对象进行赋值

    public void bind(Object object) {
        this.object = object;
    }

    // 当我们通过代理类的对象,调用方法a时,就会自动的调用如下的方法:invoke()
    // 将被代理类要执行的方法a的功能就声明在invoke()中
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        HuManUtil util = new HuManUtil();
        util.method1();
        // method:即为代理类对象调用的方法,此方法也就作为了被代理类对象要调用的方法
        // obj:被代理类的对象
        Object invoke = method.invoke(object, args);
        util.method2();
        // 上述方法的返回值就作为当前类中的invoke()的返回值。
        return invoke;
    }
}

本文链接: https://blog.csdn.net/Platinum_stars/article/details/108284483

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值