代理模式(Proxy Pattern)

介绍

代理模式(Proxy Pattern)是指为其他对象提供一种代理,以控制对这个对象的访问。 代理对象在客服端和目标对象之间起到中介作用,代理模式属于结构型设计模式。

在生活中,我们经常见到这样的场景,如:租房中介、售票黄牛、婚介、经纪人、快递、 事务代理、非侵入式日志监听等,这些都是代理模式的实际体现。

目的

1、保护目标对象

2、增强目标对象。

分类

1、静态代理

2、动态代理

动态代理与静态代理的区别

1、静态代理只能通过手动完成代理操作,如果被代理类增加新的方法,代理类需要同步 新增,违背开闭原则。

2、动态代理采用在运行时动态生成代码的方式,取消了对被代理类的扩展限制,遵循开 闭原则。

3、若动态代理要对目标类的增强逻辑扩展,结合策略模式,只需要新增策略类便可完成, 无需修改代理类的代码。

优点

1、代理模式能将代理对象与真实被调用的目标对象分离。

2、一定程度上降低了系统的耦合度,扩展性好。

3、可以起到保护目标对象的作用。

4、可以对目标对象的功能增强。

缺点

1、代理模式会造成系统设计中类的数量增加。

2、在客户端和目标对象增加一个代理对象,会造成请求处理速度变慢。

3、增加了系统的复杂度。

使用场景

1、日志监听

2、保护目标对象或则增强目标对象

3、Spring 利用动态代理实现 AOP 有两个非常重要的类,一个是 JdkDynamicAopProxy 类 和 CglibAopProxy 类。

4、有分库场景时,数据库的动态选择---可考虑这种模式去实现。

使用建议

具体实现

静态代理(MVC模式就是一个典型的静态代理)

(静态代理实例一)老子帮儿子相亲:

类图:

代码:

package com.knowledge.system.software_design_pattern.proxy_pattern.course_instance.static_proxy;

public interface Person {
    void findLove();
}
package com.knowledge.system.software_design_pattern.proxy_pattern.course_instance.static_proxy;

/**
 * @program: demo-pom
 * @description:
 * @author: bo.hu
 * @create: 2020-01-23 14:12
 **/
public class Son implements Person{
    @Override
    public void findLove() {
        System.out.println("不傻就行");
    }
}
package com.knowledge.system.software_design_pattern.proxy_pattern.course_instance.static_proxy;

/**
 * @program: demo-pom
 * @description: 代理对象类
 * @author: bo.hu
 * @create: 2020-01-23 14:13
 **/
public class Father {
    private Son son;

    public Father(Son son) {
        this.son = son;
    }
    public void findLove(){
        System.out.println("父母角度出发:选择");
        this.son.findLove();
        System.out.println("双方父母同意交往,确立关系。");
    }

    public static void main(String[] args) {
        Father f=new Father(new Son());
        f.findLove();
    }
}

(静态代理实例二)数据库的动态选择:

类图:

代码:

package com.knowledge.system.software_design_pattern.proxy_pattern.course_instance.static_proxy_2;

import lombok.Data;

/**
 * @program: demo-pom
 * @description: 订单实体类
 * @author: bo.hu
 * @create: 2020-01-23 14:38
 **/
@Data
public class Order {
    private Object orderInfo;
    private Long createTime;
    private String id;
}
package com.knowledge.system.software_design_pattern.proxy_pattern.course_instance.static_proxy_2;

/**
 * @program: demo-pom
 * @description:
 * @author: bo.hu
 * @create: 2020-01-23 14:44
 **/
public class OrderMapper {
    public int insert(Order order){
        System.out.println("OrderMapper 创建 Order 成功");
        return 1;
    }
}
package com.knowledge.system.software_design_pattern.proxy_pattern.course_instance.static_proxy_2;

public interface OrderService {
    int createOrder(Order order);
}
package com.knowledge.system.software_design_pattern.proxy_pattern.course_instance.static_proxy_2;

/**
 * @program: demo-pom
 * @description:
 * @author: bo.hu
 * @create: 2020-01-23 14:47
 **/
public class OrderServiceImpl implements OrderService {
    private OrderMapper orderMapper;

    public OrderServiceImpl(OrderMapper orderMapper) {
        this.orderMapper = orderMapper;
    }

    @Override
    public int createOrder(Order order) {
        System.out.println("OrderService 调用 orderMapper 创建订单");
        return orderMapper.insert(order);
    }
}
package com.knowledge.system.software_design_pattern.proxy_pattern.course_instance.static_proxy_2;

import javax.xml.crypto.Data;

/**
 * @program: demo-pom
 * @description:
 * @author: bo.hu
 * @create: 2020-01-23 15:12
 **/
public class DynamicDataSourceEntry {

    public final static String DEFAULT = null;

    private final static ThreadLocal<String> local = new ThreadLocal<>();

    public DynamicDataSourceEntry() {
    }

    public static void clear() {
        local.remove();
    }

    public static void get() {
        local.get();
    }

    public static void restore() {
        local.set(DEFAULT);
    }

    public static void set(String resource) {
        local.set(resource);
    }

    public static void set(int year) {
        local.set("DB_" + year);
    }

}
package com.knowledge.system.software_design_pattern.proxy_pattern.course_instance.static_proxy_2;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * @program: demo-pom
 * @description: 创建订单静态代理类
 * @author: bo.hu
 * @create: 2020-01-23 15:22
 **/
public class CreateOrderProxy implements OrderService{
    private SimpleDateFormat yearFormat = new SimpleDateFormat("yyyy");
    private OrderService orderService;

    public CreateOrderProxy(OrderService orderService) {
        this.orderService = orderService;
    }

    public int createOrder(Order order){
        before();
        Long time = order.getCreateTime();
        Integer dbRouter = Integer.valueOf(yearFormat.format(new Date(time)));
        System.out.println("静态代理类自动分配到【DB_" + dbRouter + "】数据源处理数据。");
        DynamicDataSourceEntry.set(dbRouter);
        orderService.createOrder(order);
        after();
        return 0;
    }

    private void before() {
        System.out.println("Proxy before method.");
    }

    private void after() {
        System.out.println("Proxy after method.");
    }

    public static void main(String[] args) {
        Order order=new Order();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
        Date date = null;
        try {
            date = sdf.parse("2017/02/01");
        } catch (ParseException e) {
            e.printStackTrace();
        }
        order.setCreateTime(date.getTime());
        OrderService orderService = new CreateOrderProxy(new OrderServiceImpl(new OrderMapper()));
        orderService.createOrder(order);
    }

}

动态代理

JDK自带的动态代理

类图:

代码:

package com.knowledge.system.software_design_pattern.proxy_pattern.course_instance.static_proxy;

public interface Person {
    void findLove();
}
package com.knowledge.system.software_design_pattern.proxy_pattern.course_instance.dynamic_proxy_jdk;

import com.knowledge.system.software_design_pattern.proxy_pattern.course_instance.static_proxy.Person;

/**
 * @program: demo-pom
 * @description: 顾客
 * @author: bo.hu
 * @create: 2020-01-23 16:19
 **/
public class Customer  implements Person {

    @Override
    public void findLove() {
        System.out.println("不傻就行");
    }
}
package com.knowledge.system.software_design_pattern.proxy_pattern.course_instance.dynamic_proxy_jdk;

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


/**
 * @program: demo-pom
 * @description: 动态代理类java实现方式
 * @author: bo.hu
 * @create: 2020-01-23 16:09
 **/
public class JDKMeipo implements InvocationHandler {

    private Object target;

    public Object getIntence(Object object){
        this.target=object;
        Class<?>clazz=target.getClass();
        return Proxy.newProxyInstance(clazz.getClassLoader(),clazz.getInterfaces(),this);
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        before();
        Object obj=method.invoke(this.target,args);
        after();
        return obj;
    }

    private void before() {
        System.out.println("开始  物色人选");
    }

    private void after() {
        System.out.println("结束  物色人选");
    }

}
package com.knowledge.system.software_design_pattern.proxy_pattern.course_instance.dynamic_proxy_jdk;


import com.knowledge.system.software_design_pattern.proxy_pattern.course_instance.static_proxy.Person;

/**
 * @program: demo-pom
 * @description:
 * @author: bo.hu
 * @create: 2020-01-23 16:20
 **/
public class Test {
    public static void main(String[] args) {
//        动态代理类和被代理类必须继承同一个接口。
//        动态代理只能对接口中声明的方法进行代理。
//        每一个动态代理实例都有一个关联的InvocationHandler。
//        通过代理实例调用方法,方法调用请求会被转发给InvocationHandler的invoke方法。
//        只能代理声明在接口中的方法。
        Person obj=(Person)new JDKMeipo().getIntence(new Customer());
        obj.findLove();
    }
}

CGLIB实现的动态代理(Spring中同时使用了JDK与CGLIB这两种代理)

类图:

代码:

package com.knowledge.system.software_design_pattern.proxy_pattern.course_instance.static_proxy;

public interface Person {
    void findLove();
}
package com.knowledge.system.software_design_pattern.proxy_pattern.course_instance.dynamic_proxy_cglib;

import com.knowledge.system.software_design_pattern.proxy_pattern.course_instance.static_proxy.Person;

public class Customer implements Person {
    @Override
    public void findLove() {
        System.out.println("cglib   findLove()");
    }
}
package com.knowledge.system.software_design_pattern.proxy_pattern.course_instance.dynamic_proxy_cglib;

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

import java.lang.reflect.Method;

public class CgLibMeipo implements MethodInterceptor {

    public Object getInstence(Class<?> clazz){
        Enhancer enhancer =new Enhancer();
        enhancer.setSuperclass(clazz);
        enhancer.setCallback(this);
        return enhancer.create();
    }

    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        before();
        Object obj=methodProxy.invokeSuper(o,objects);
        after();
        return obj;
    }

    private void after() {
        System.out.println("代理类前置处理");
    }

    private void before() {
        System.out.println("代理类后置处理");
    }

}
package com.knowledge.system.software_design_pattern.proxy_pattern.course_instance.dynamic_proxy_cglib;

public class Test {
    public static void main(String[] args) {
        Customer customer=(Customer)new CgLibMeipo().getInstence(Customer.class);
        customer.findLove();
    }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章