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)圖

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)圖

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