結(jié)構(gòu)性模式(三):代理模式、享元模式

1、代理模式

在不改變?cè)碱?lèi)(或叫被代理類(lèi))的情況下,通過(guò)引入代理類(lèi)來(lái)給原始類(lèi)附加功能。一般情況下,我們讓代理類(lèi)和原始類(lèi)實(shí)現(xiàn)同樣的接口。但是,如果原始類(lèi)并沒(méi)有定義接口,并且原始類(lèi)代碼并不是我們開(kāi)發(fā)維護(hù)的。在這種情況下,我們可以通過(guò)讓代理類(lèi)繼承原始類(lèi)的方法來(lái)實(shí)現(xiàn)代理模式。

1.1、實(shí)例說(shuō)明

在某個(gè)應(yīng)用軟件中,需要記錄業(yè)務(wù)方法的調(diào)用日志,在不修改現(xiàn)有業(yè)務(wù)類(lèi)的基礎(chǔ)上為每一個(gè)類(lèi)提供一個(gè)日志記錄代理類(lèi),如在業(yè)務(wù)方法method()調(diào)用之前輸出“方法method()”被調(diào)用,調(diào)用之后如果沒(méi)有異常,則輸出“方法method()調(diào)用成功”,否則輸出“method()調(diào)用失敗”。在代理類(lèi)中調(diào)用真實(shí)業(yè)務(wù)類(lèi)的業(yè)務(wù)方法,使用代理模式設(shè)計(jì)該日志記錄模塊的結(jié)構(gòu),繪制類(lèi)圖并編程模擬實(shí)現(xiàn)。

1.2、實(shí)例類(lèi)圖
代理模式.jpg
1.3、實(shí)例代碼
package com.ljessie.designpattern.structural.proxy;

public interface AbstractLog {
     void method();
}

public class BusinessClass implements AbstractLog {
    @Override
    public void method() {
        System.out.println("真實(shí)業(yè)務(wù)方法!");
    }
}

public class LoggerProxy implements AbstractLog {

    private BusinessClass businessClass;

    public LoggerProxy(){
        businessClass = new BusinessClass();
    }

    @Override
    public void method() {
        System.out.println("方法method()被調(diào)用!");
        try{
            businessClass.method();
            System.out.println("方法method()調(diào)用成功!");
        }catch (Exception e){
            System.out.println("方法method()調(diào)用異常!");
        }
    }
}

public class Client {
    public static void main(String[] args) {
        AbstractLog al = new LoggerProxy();
        al.method();
    }
}

代理模式在Spring AOP中的應(yīng)用可參考:http://www.itdecent.cn/p/58eb4b0a8a85

2、享元模式

所謂“享元”,顧名思義就是被共享的單元。享元模式的意圖是復(fù)用對(duì)象,節(jié)省內(nèi)存,前提是享元對(duì)象是不可變對(duì)象。具體來(lái)講,當(dāng)一個(gè)系統(tǒng)中存在大量重復(fù)對(duì)象的時(shí)候,我們就可以利用享元模式,將對(duì)象設(shè)計(jì)成享元,在內(nèi)存中只保留一份實(shí)例,供多處代碼引用,這樣可以減少內(nèi)存中對(duì)象的數(shù)量,以起到節(jié)省內(nèi)存的目的。

實(shí)際上,不僅僅相同對(duì)象可以設(shè)計(jì)成享元,對(duì)于相似對(duì)象,我們也可以將這些對(duì)象中相同的部分(字段),提取出來(lái)設(shè)計(jì)成享元,讓這些大量相似對(duì)象引用這些享元。

2.1、實(shí)例說(shuō)明

使用享元模式設(shè)計(jì)一個(gè)圍棋軟件,在系統(tǒng)中只存在一個(gè)白棋對(duì)象和一個(gè)黑棋對(duì)象,但是它們可以在棋盤(pán)的不同位置顯示多次。

2.2、實(shí)例類(lèi)圖
享元模式.jpg
2.3、實(shí)例代碼
public class Coordinates {
    private int x;
    private int y;

    public Coordinates(int x,int y){
        this.x = x;
        this.y = y;
    }

    public int getX() {
        return x;
    }

    public void setX(int x) {
        this.x = x;
    }

    public int getY() {
        return y;
    }

    public void setY(int y) {
        this.y = y;
    }
}

/**
 * 圍棋棋子類(lèi),抽象享元類(lèi)
 */
public abstract class IgoChessman {
    abstract String getColor();
    public void locate(Coordinates coordinates){
        System.out.println("棋子顏色:"+this.getColor()+",棋子位置:"+coordinates.getX()+","+coordinates.getY());
    }
}

/**
 * 具體享元類(lèi)
 */
public class BlackIgoChessman extends IgoChessman {
    @Override
    String getColor() {
        return "黑色";
    }
}

/**
 * 具體享元類(lèi)
 */
public class WhiteIgoChessman extends IgoChessman {
    @Override
    String getColor() {
        return "白色";
    }
}

public class IgoChessmanFactory {
    private static IgoChessmanFactory instance =
            new IgoChessmanFactory();
    private static Hashtable ht;
    private IgoChessmanFactory(){
        ht = new Hashtable();
        IgoChessman black = new BlackIgoChessman();
        IgoChessman white = new WhiteIgoChessman();
        ht.put("b",black);
        ht.put("w",white);
    }

    public static IgoChessmanFactory getInstance(){
        return instance;
    }

    public  IgoChessman getIgoChessman(String color){
        return (IgoChessman) ht.get(color);
    }

}

public class Client {
    public static void main(String[] args) {
        IgoChessman black1,black2,white1,white2;
        IgoChessmanFactory factory = IgoChessmanFactory.getInstance();
        black1 = factory.getIgoChessman("b");
        black2 = factory.getIgoChessman("b");
        white1 = factory.getIgoChessman("w");
        white2 = factory.getIgoChessman("w");
        System.out.println("兩顆黑棋是否相同:"+(black1==black2));
        System.out.println("兩顆白棋是否相同:"+(white1==white2));
        black1.locate(new Coordinates(1,2));
        white1.locate(new Coordinates(2,4));
    }
}

運(yùn)行結(jié)果:

兩顆黑棋是否相同:true
兩顆白棋是否相同:true
棋子顏色:黑色,棋子位置:1,2
棋子顏色:白色,棋子位置:2,4
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀(guān)點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容