1. 程式人生 > >淺談proxy代理模式

淺談proxy代理模式

一、前言

代理是代替伺服器去接受請求者的請求的中間人。我們也聽說過代理伺服器,它的作用的幫助客戶端去請求客戶端想要的資源,為什麼要通過代理呢,那是因為客戶端直接訪問伺服器會被拒絕(防火牆遮蔽),而代理伺服器則可以直接訪問伺服器,客戶端通過代理伺服器,將請求的結果交給代理伺服器,代理伺服器對這些內容進行重組換成自己的標識(IP),並且將請求的結果返回給使用者,這樣做的弊端就是訪問的速度大打折扣,但是總比沒有強。

我們的代理模式就是這麼幹的,如果代理能夠處理的東西(比如使用者已經訪問過的,伺服器返回過來的沒有過期的快取),不用請求伺服器了,直接返回給使用者,而只有代理伺服器不能處理的東西才會再次交給伺服器去處理,當然這只是代理的一種策略,為了能夠加快訪問速度,這樣代理伺服器就代替我們去訪問伺服器了。

二、程式碼例項

本人去處理所有事情是非常麻煩的,特別是初始化的時候都非常的耗時,因此使用代理,不到必須自己出馬的時候一直按兵不動,讓代理去完成這些工作,這就是代理模式。

Printable介面:代理的同源性:

package designMode.proxy;

public interface Printable {
    public abstract void setPrinterName(String name);
    public abstract String getPirnterName();
    public abstract void print(String word);
}

Printer類:本人(相當於真正的伺服器)

package designMode.proxy;

public class Printer implements Printable{
    String name;

    public Printer(String name) {
        this.name = name;
        heavyWork();
        System.out.println("生成印表機例項成功...");
    }

    private void heavyWork(){
        System.out.println("本人:"+name);
        try {
            Thread.sleep(5000);
        }catch (InterruptedException e){
            e.printStackTrace();
        }
    }

    @Override
    public void setPrinterName(String name) {
        this.name=name;
    }

    @Override
    public String getPirnterName() {
        return name;
    }

    @Override
    public void print(String word){
        System.out.println("印表機"+name+"正在列印...");
        System.out.println(word);
        System.out.println("列印完成!");
    }
}

ProxyPrinter代理類:

package designMode.proxy;

public class ProxyPrinter implements Printable {
    String name;
    Printer printer = null;

    //代理能做的事情自己去做
    @Override
    public void setPrinterName(String name) {
        if(printer!=null){
            printer.setPrinterName(name);
        }
        this.name = name;
    }

    //代理能做的事情自己去做
    @Override
    public String getPirnterName() {
        return name;
    }

    //代理做不了的事情交給真正能做的(印表機)去做
    @Override
    public void print(String word) {
        check();
        printer.print(word);
    }

    private synchronized void check(){
        if(printer==null){
            printer = new Printer(name);
        }
    }
}

Main類:

package designMode.proxy;

public class Main {
    public static void main(String[] args) {
        Printable proxy = new ProxyPrinter();
        proxy.setPrinterName("江疏影");
        System.out.println("此時代理的名字為:"+proxy.getPirnterName());
        System.out.println("==遇到了代理處理不了的工作,通知伺服器==");
        proxy.print("hello,world!");
        System.out.println("======================");
        proxy.setPrinterName("倪妮");
        System.out.println("此時代理的名字為:"+proxy.getPirnterName());
        proxy.print("hello,my country!");
    }
}

啟動伺服器很耗時(這裡用睡眠5秒錶示),那麼使用代理伺服器可以輕鬆處理一些事務(設定名字,獲取名字),知道代理伺服器無能為力的時候(print列印內容),代理伺服器就會通知伺服器去處理,從本例來看,因為使用了委託機制,將printer物件組合進來,但是printer是不知道代理的,它只是被啟動了而已,這說明了什麼?本人(printer)可以不做任何改動,就可以增加很多的代理去啟動本人,這樣非常有利於擴充套件,其實這裡也使用了懶載入機制,看到只有到不得不使用的時候才生成被代理的例項,那麼可不可以直接在代理模式中使用懶載入機制呢,答案是不利於擴充套件性,沒有這種分而治之的思想好,這樣的好處是很大的,在main中可以隨意切換,同時能夠定義相同的必須的介面。這種透明性是非常有益的,在很多模式中都有體現。

三、總結

代理模式是一種常見的模式,只在必須的時候生成例項,也分為很多種類,主要按照使用去分類的,比如本例的虛擬代理,以及其它的遠端代理,訪問控制代理等,我們主要理解代理的實現本質,代理的意義,以及手機用途。代理模式與裝飾器模式比較類似,都是持有了同類或父類的引用(委託機制),並且在函式之中呼叫了同類的方法來加工與同類同名的本類的響應方法,但是也有區別,代理模式是為了減輕被代理人的工作,在不得已的時候再去打擾被代理人,而裝飾器模式是為了產生新的功能,裝