23種設計模式之代理模式

代理模式:

老師上課講的比較通俗易懂,總結記錄一下。java

  以下圖,好比我須要去買一臺聯想電腦,可是聯想總部在北京,我人在西安,若是聯想公司在西安沒有代理經銷商,那我須要去北京總部購買,耗時耗力。可是若是聯想在你當地有設經銷商,那麼咱們須要購買筆記本這個需求,就變得很是簡單了,只須要去當地門店便可,應該很好理解了。設計模式

   聯想公司它本身能夠生產電腦,也能夠本身銷售電腦,這就比如咱們建立的真是對象有兩個方法同樣,經銷商能夠賣電腦,可是他不能生產電腦,電腦從哪裏來?確定是從聯繫公司進貨,而後在銷售,這就至關於代理對象調用了真實對象生產電腦的方法。數組

  同時代理對象能夠爲用戶提供真是對象完成它不能不了的動能,可能說到這裏,對於代理模式的一些基本認識就應該大體瞭解了,因此使用代理模式,簡而言之能夠加強對象的功能,而Java中所謂的23中設計模式,也就是一些通用的解決固定問題的方式。ide

 

 代理模式的一些基本概念    spa

  真實對象:被代理的對象設計

  代理對象:代替真實對象的對象代理

  代理模式:代理對象代理真實對象,達到加強真實對象功能的目的。   (理論性的東西,知道是什麼意思就好,沒必要糾結)code


代理模式實現方式有兩種對象

  1. 靜態代理:有一個類文件描述代理模式blog

  2. 動態代理:在內存中造成代理類   (動態代理相對靈活一些,使用動態代理比使用靜態代理對一些)

 

實現步驟:

  1. 代理對象和真實對象實現相同的接口
  2. 建立代理對象 = Proxy.newProxyInstance();
  3. 使用代理對象調用方法。
  4. 加強方法

加強方式:

  1. 加強參數列表
  2. 加強返回值類型
  3. 加強方法體執行邏輯

 

簡單Demo

定義接口和方法

public interface SaleComputer {

    public String sale(double money);

    public void show();

}

 

這是你的真實對象

//真實的類   聯想公司
public class Lenovo implements SaleComputer {

    @Override
    public String sale(double money) {
        System.out.println("花了" + money + "買了一臺電腦");
        return "聯想電腦";
    }

    @Override
    public void show() {
        System.out.println("展現電腦 ...");
    }
}

 

這是你的代理對象

public class ProxyTest {
    public static void main(String[] args) {
        //1.建立真實對象
        Lenovo lenovo = new Lenovo();

        //2.傳遞三個參數,
        // 參數一: 類加載器 真實對象.getClass().getClassLoader()
        // 參數二: 接口數組 真實對象.lenovo.getClass().getInterfaces()
        // 參數三: 處理器 new InvocationHandler()

        SaleComputer proxy_lenovo = (SaleComputer) Proxy.newProxyInstance(lenovo.getClass().getClassLoader(), lenovo.getClass().getInterfaces(), new InvocationHandler() {

            /**
             * 代理邏輯編寫的方法:代理對象調用的全部方法都會被執行
             * @param proxy  代理對象
             * @param method 代理對象調用方法,被封裝爲的對象
             * @param args   代理對象調用方式時,傳遞的實際參數
             * @return
             * @throws Throwable
             */
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

               /*
                    System.out.println("該方法被執行了");
                    System.out.println(method.getName());
                    System.out.println(args[0]);
                */

                //加強參數  假設代理對象在真實對象拿貨只要市場價的85%,經銷商也要賺錢.那就須要修改原sale方法裏的參數了.
                if (method.getName().equals("sale")) {
                    double money = (double) args[0]; //args[0]=8000
                    money = money * 0.85;  //加強後參數money變爲6800

                    /*
                        使用真實對象調用該方法, Object obj = method.invoke(lenovo, args);
                        使用代理對象調用該方法, Object obj = method.invoke(lenovo, money);
                    */

                    String obj = (String) method.invoke(lenovo, money); 

                    //還能夠加強方法體的邏輯:免費送貨
                    System.out.println("免費送貨上門");

                    //加強返回值,原方法只是返回一個電腦,如今還給你送點東西,本身理解哈,哈哈。
                    return obj+"_送你個鼠標墊";


                } else {
                    Object obj = method.invoke(lenovo, args);
                    return obj;
                }

            }
        });


        String computer = proxy_lenovo.sale(8000);
        System.out.println(computer);

        /*  proxy_lenovo.show();  沒有被加強,執行的話會原樣調用*/
    }
}

 

敏感詞彙過濾需求實現就用到了動態代理來加強方法

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.List;

@WebFilter("/*")
public class SensitiveWordsFilter implements Filter {

    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
        //1.建立代理對象,加強getParameter方法
        ServletRequest proxy_req = (ServletRequest) Proxy.newProxyInstance(req.getClass().getClassLoader(), req.getClass().getInterfaces(), new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                //加強getParameter方法
                //判斷是不是getParameter方法
                if (method.getName().equals("getParameter")) {
                    //加強返回值
                    //獲取返回值
                    String value = (String) method.invoke(req, args);
                    if (value != null) {
                        for (String str : list) {
                            if (value.contains(str)) {
                                value = value.replaceAll(str, "***");
                            }
                        }
                    }
                    return value;
                }

                //判斷方法名是不是 getParameterMap

                //判斷方法名是不是 getParameterValue

                return method.invoke(req, args);
            }
        });

        //2.放行
        chain.doFilter(proxy_req, resp);
    }

    private List<String> list = new ArrayList<String>();//敏感詞聚集合

    public void init(FilterConfig config) throws ServletException {

        try {
            //1.獲取文件真實路徑
            ServletContext servletContext = config.getServletContext();
            String realPath = servletContext.getRealPath("/WEB-INF/classes/敏感詞彙.txt");
            //2.讀取文件
            BufferedReader br = new BufferedReader(new FileReader(realPath));
            //3.將文件的每一行數據添加到list中
            String line = null;
            while ((line = br.readLine()) != null) {
                list.add(line);
            }

            br.close();

            System.out.println(list);

        } catch (Exception e) {
            e.printStackTrace();
        }

    }
public void destroy() { } }
相關文章
相關標籤/搜索