代理模式(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();
    }
}

 

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