回顧23種設(shè)計(jì)模式(二)——結(jié)構(gòu)型模式

代理甘改,適配器,裝飾器灭抑,享元十艾,組合,門面腾节,橋接

代理模式

(這里只是簡單說下靜態(tài)代理忘嫉,JDK動態(tài)代理和CGLIB動態(tài)代理這里略)
定義:由于某些原因需要給某對象提供一個(gè)代理以控制對該對象的訪問

//主題接口
public interface Subject {
    void request();
}
//真實(shí)主題實(shí)現(xiàn)類
public class RealSubject implements Subject{
    public void request() {
        System.out.println("real subject");
    }
}
//代理類
public class Proxy implements Subject{
    private RealSubject realSubject;
    public void request() {
        if (realSubject == null) {
            realSubject = new RealSubject();
        }
        preRequest();
        realSubject.request();
        postRequest();
    }
    private void postRequest() {
        System.out.println("before subject ...");
    }
    private void preRequest() {
        System.out.println("after subject ...");
    }
}

Main方法及輸出結(jié)果:

    public static void main(String[] args) {
        Proxy proxy = new Proxy();
        proxy.request();
    }
after subject ...
real subject
before subject ...

適配器(Adaptee)模式

定義:將一個(gè)類的接口轉(zhuǎn)換成客戶希望的另外一個(gè)接口,使得原本由于接口不兼容而不能一起工作的那些類能一起工作
優(yōu)點(diǎn)
1.客戶端通過適配器可以透明地調(diào)用目標(biāo)接口案腺。
2.復(fù)用了現(xiàn)存的類庆冕,程序員不需要修改原有代碼而重用現(xiàn)有的適配者類。
3.將目標(biāo)類和適配者類解耦劈榨,解決了目標(biāo)類和適配者類接口不一致的問題愧杯。
缺點(diǎn)
1.對類適配器來說,更換適配器的實(shí)現(xiàn)過程比較復(fù)雜鞋既。
例子:各種adapter都是

對象適配器.gif

//組合方式實(shí)現(xiàn)適配器模式:
//即對象適配器
//三相接口
public interface Three {
     void chargedByThree();
}
//二相充電器
public class Two {
    public void chargedByTwo(){
        System.out.println("使用二相插座供電");
    }
}
//二相充電器轉(zhuǎn)三相
public class Adapter implements Three{
    private Two two;
    public Adapter(Two two) {
        this.two = two;
    }
    @Override
    public void chargedByThree() {
        System.out.println("二相轉(zhuǎn)三相 適配器處理中...");
        two.chargedByTwo();
    }
}
//筆記本主類充電
public class Client {
    private Three three;
    public Client(Three three){
        this.three = three;
    }
    public void charged(){
        three.chargedByThree();
    }
}

Main函數(shù)及輸出結(jié)果:

 public static void main(String[] args) {
        Two two = new Two();
        Three three = new Adapter(two);
        Client client = new Client(three);
        client.charged();
    }
二相轉(zhuǎn)三相 適配器處理中...
使用二項(xiàng)插座供電
類適配器.gif
//繼承方式實(shí)現(xiàn)適配器模式:
//及類適配器
//繼承類并實(shí)現(xiàn)接口
public class AdapterExtends extends Two implements Three{
    @Override
    public void chargedByThree() {
        System.out.println("二相轉(zhuǎn)三相 繼承適配器處理中...");
        this.chargedByTwo();
    }
}

Main函數(shù)及輸出結(jié)果:

public static void main(String[] args) {
        Two two = new Two();
        Three three = new AdapterExtends();
        Client client = new Client(three);
        client.charged();
    }
二相轉(zhuǎn)三相 繼承適配器處理中...
使用二項(xiàng)插座供電

橋接模式

定義:將抽象與實(shí)現(xiàn)分離力九,使它們可以獨(dú)立變化
使用場景:JDBC就是使用的該模式。
mysql的driver和oracle的driver邑闺,都實(shí)現(xiàn)了Driver接口跌前,生成了DriverInfo類,通過DriverManager能獲取對應(yīng)的connection陡舅,springboot默認(rèn)的連接池就是HikariCP 使用threadlocal+CopyOnWriteArrayList抵乓,HikariCP 是一個(gè)“零開銷”的生產(chǎn)就緒 JDBC 連接池“醒埽快速灾炭、簡單、可靠颅眶。大約 130Kb 的庫非常輕巧蜈出。

//基礎(chǔ)接口
public interface Base {
    void operate();
}
//基礎(chǔ)接口實(shí)現(xiàn)
public class BaseImpl implements Base{
    public void operate() {
        System.out.println("Base operate ...");
    }
}
//擴(kuò)展抽象類
public abstract class AbstractExtra {
    protected Base base;
    public AbstractExtra(Base base) {
        this.base = base;
    }
    public abstract void extraOperate();
}
//擴(kuò)展實(shí)現(xiàn)類
public class Extra extends AbstractExtra{
    public Extra(Base base) {
        super(base);
    }
    public void extraOperate(){
        System.out.println("Extra extraOperate ...");
        base.operate();
    }
}

Main方法及測試類

    public static void main(String[] args) {
        Base base = new BaseImpl();
        AbstractExtra extra = new Extra(base);
        extra.extraOperate();
    }
Extra extraOperate ...
Base operate ...

裝飾(decorator)模式

定義:指在不改變現(xiàn)有對象結(jié)構(gòu)的情況下,動態(tài)地給該對象增加一些職責(zé)(即增加其額外功能)
優(yōu)點(diǎn)
1.采用裝飾模式擴(kuò)展對象的功能比采用繼承方式更加靈活涛酗。
2.可以設(shè)計(jì)出多個(gè)不同的具體裝飾類铡原,創(chuàng)造出多個(gè)不同行為的組合。
缺點(diǎn)
1.裝飾模式增加了許多子類商叹,如果過度使用會使程序變得很復(fù)雜

裝飾模式.gif

//component通用接口
public interface Component {
    void operation();
}
//接口的實(shí)現(xiàn)類
public class CurrentComponent implements Component{
    public CurrentComponent() {
        System.out.println("創(chuàng)建組件");
    }
    public void operation() {
        System.out.println("組件的通用操作...");
    }
}
//裝飾模式的抽象類
public abstract class Decorator implements Component{
    private Component component;

    public Decorator(Component component) {
        this.component = component;
    }

    abstract void incrementFunction();

    public void operation() {
        component.operation();
    }
}
//裝飾模式的具體實(shí)現(xiàn)
public class IncrementAComponent extends Decorator{
    public IncrementAComponent(Component component) {
        super(component);
    }

    void incrementFunction() {
        System.out.println("裝飾器A的附加操作...");
    }
}

Main函數(shù)及輸出結(jié)果:

    public static void main(String[] args) {
        Component current = new CurrentComponent();
        current.operation();
        System.out.println("----裝飾過后------");
        Component incrementA = new IncrementAComponent(current);
        incrementA.operation();
        ((IncrementAComponent) incrementA).incrementFunction();
    }
創(chuàng)建組件
組件的通用操作...
----裝飾過后------
組件的通用操作...
裝飾器A的附加操作...

外觀模式

外觀(Facade)模式的結(jié)構(gòu)比較簡單燕刻,主要是定義了一個(gè)高層接口。它包含了對各個(gè)子系統(tǒng)的引用剖笙,客戶端可以通過它訪問各個(gè)子系統(tǒng)的功能÷严矗現(xiàn)在來分析其基本結(jié)構(gòu)和實(shí)現(xiàn)方法。

//外觀類
public class Facade {
    private SubSystem1 system1 = new SubSystem1();
    private SubSystem2 system2 = new SubSystem2();
    public void method(){
        system1.method();
        system2.method();
    }
}
//子系統(tǒng)1
public class SubSystem1 {
    public void method(){
        System.out.println("SubSystem1 method ...");
    }
}
//子系統(tǒng)2
public class SubSystem1 {
    public void method(){
        System.out.println("SubSystem2 method ...");
    }
}

Main方法及輸出結(jié)果:

    public static void main(String[] args) {
        Facade facade = new Facade();
        facade.method();
    }
SubSystem1 method ...
SubSystem2 method ...

享元模式

運(yùn)用共享技術(shù)來有効地支持大量細(xì)粒度對象的復(fù)用弥咪。它通過共享已經(jīng)存在的又橡來大幅度減少需要?jiǎng)?chuàng)建的對象數(shù)量过蹂、避免大量相似類的開銷,從而提高系統(tǒng)資源的利用率酪夷。
字符串常量池
自動裝箱 -128-127

//非享元對象
public class UnFlyweight {
    private String info;
    public UnFlyweight(String info) {
        this.info = info;
    }
    public String getInfo() {
        return info;
    }
    public void setInfo(String info) {
        this.info = info;
    }
}
//享元接口
public interface Flyweight {
    void operation(UnFlyweight unFlyweight);
}
//享元接口的具體實(shí)現(xiàn)
public class ConcreteFlyweight implements Flyweight{
    private String key;
    public ConcreteFlyweight(String key) {
        this.key = key;
        System.out.println("ConcreteFlyweight create " + key);
    }
    @Override
    public void operation(UnFlyweight unFlyweight) {
        System.out.print("ConcreteFlyweight key is "+key);
        System.out.println(". ConcreteFlyweight operation with unFlyweight["+unFlyweight.getInfo()+"]");

    }
}
//享元工廠
public class FlyweightFactory {
    private HashMap<String, Flyweight> flyweights=new HashMap<>();
    public Flyweight getFlyweight(String key) {
        Flyweight flyweight = flyweights.get(key);
        if(flyweight!=null) {
            System.out.println("Flyweight key "+key+" is already exist.");
        } else {
            flyweight=new ConcreteFlyweight(key);
            flyweights.put(key, flyweight);
        }
        return flyweight;
    }
}

Main方法及輸出結(jié)果:

    public static void main(String[] args) {
        FlyweightFactory factory = new FlyweightFactory();
        Flyweight f01=factory.getFlyweight("a");
        Flyweight f02=factory.getFlyweight("a");
        f01.operation(new UnFlyweight("1"));
        f02.operation(new UnFlyweight("2"));
    }
ConcreteFlyweight create a
Flyweight key a is already exist.
ConcreteFlyweight key is a. ConcreteFlyweight operation with unFlyweight[1]
ConcreteFlyweight key is a. ConcreteFlyweight operation with unFlyweight[2]

組合模式

有時(shí)又叫作部分-整體模式榴啸,它是一種將對象組合成樹狀的層次結(jié)構(gòu)的模式,用來表示“部分-整體”的關(guān)系晚岭,使用戶對單個(gè)對象和組合對象具有一致的訪問性鸥印。

//組件接口
public interface MyComponent {
    void add(MyComponent c);
    void remove(MyComponent c);
    MyComponent getChild(int i);
    void operation();
}
//葉子實(shí)現(xiàn)接口
public class Leaf implements MyComponent{
    private String name;
    public Leaf(String name)
    {
        this.name=name;
    }
    public void add(MyComponent c){ }
    public void remove(MyComponent c){ }
    public MyComponent getChild(int i) {
        return null;
    }
    public void operation() {
        System.out.println("Leaf "+name+" is here");
    }
}
//樹枝實(shí)現(xiàn)接口
public class Composite implements MyComponent{
    private ArrayList<MyComponent> children=new ArrayList<MyComponent>();
    public void add(MyComponent c){
        children.add(c);
    }
    public void remove(MyComponent c){
        children.remove(c);
    }
    public MyComponent getChild(int i) {
        return children.get(i);
    }
    public void operation() {
        for (MyComponent c : children) {
            c.operation();
        }
    }
}

Main方法及輸出結(jié)果:

    public static void main(String[] args) {
        MyComponent c0=new Composite();
        MyComponent c1=new Composite();
        MyComponent leaf1=new Leaf("1");
        MyComponent leaf2=new Leaf("2");
        MyComponent leaf3=new Leaf("3");
        c0.add(leaf1);
        c0.add(c1);
        c1.add(leaf2);
        c1.add(leaf3);
        c0.operation();
    }
Leaf 1 is here
Leaf 2 is here
Leaf 3 is here
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市坦报,隨后出現(xiàn)的幾起案子库说,更是在濱河造成了極大的恐慌,老刑警劉巖片择,帶你破解...
    沈念sama閱讀 217,542評論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件潜的,死亡現(xiàn)場離奇詭異,居然都是意外死亡字管,警方通過查閱死者的電腦和手機(jī)啰挪,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,822評論 3 394
  • 文/潘曉璐 我一進(jìn)店門绪励,熙熙樓的掌柜王于貴愁眉苦臉地迎上來飒焦,“玉大人,你說我怎么就攤上這事±哟裕” “怎么了倍谜?”我有些...
    開封第一講書人閱讀 163,912評論 0 354
  • 文/不壞的土叔 我叫張陵小压,是天一觀的道長玉工。 經(jīng)常有香客問我,道長汁胆,這世上最難降的妖魔是什么梭姓? 我笑而不...
    開封第一講書人閱讀 58,449評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮嫩码,結(jié)果婚禮上誉尖,老公的妹妹穿的比我還像新娘。我一直安慰自己谢谦,他們只是感情好释牺,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,500評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著回挽,像睡著了一般没咙。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上千劈,一...
    開封第一講書人閱讀 51,370評論 1 302
  • 那天祭刚,我揣著相機(jī)與錄音,去河邊找鬼墙牌。 笑死涡驮,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的喜滨。 我是一名探鬼主播捉捅,決...
    沈念sama閱讀 40,193評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼虽风!你這毒婦竟也來了棒口?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,074評論 0 276
  • 序言:老撾萬榮一對情侶失蹤辜膝,失蹤者是張志新(化名)和其女友劉穎无牵,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體厂抖,經(jīng)...
    沈念sama閱讀 45,505評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡茎毁,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,722評論 3 335
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了忱辅。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片七蜘。...
    茶點(diǎn)故事閱讀 39,841評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡谭溉,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出橡卤,到底是詐尸還是另有隱情夜只,我是刑警寧澤,帶...
    沈念sama閱讀 35,569評論 5 345
  • 正文 年R本政府宣布蒜魄,位于F島的核電站,受9級特大地震影響场躯,放射性物質(zhì)發(fā)生泄漏谈为。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,168評論 3 328
  • 文/蒙蒙 一踢关、第九天 我趴在偏房一處隱蔽的房頂上張望伞鲫。 院中可真熱鬧,春花似錦签舞、人聲如沸秕脓。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,783評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽吠架。三九已至,卻和暖如春搂鲫,著一層夾襖步出監(jiān)牢的瞬間傍药,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,918評論 1 269
  • 我被黑心中介騙來泰國打工魂仍, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留拐辽,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,962評論 2 370
  • 正文 我出身青樓擦酌,卻偏偏與公主長得像俱诸,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子赊舶,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,781評論 2 354

推薦閱讀更多精彩內(nèi)容