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

個(gè)人博客: http://zhangsunyucong.top


前言

本篇文章主要講23種設(shè)計(jì)模式中的7種結(jié)構(gòu)型設(shè)計(jì)模式扶歪,包括適配器模式怀挠,裝飾者模式狡孔,代理模式,外觀模式蜓堕,橋接模式抛虏,組合模式,享元模式套才。

適配器模式

適配器模式是將一個(gè)類的方法接口轉(zhuǎn)換成客戶端期望的接口表示迂猴。我們可以約定,把客戶端期望的接口叫做目標(biāo)Targetable背伴,被轉(zhuǎn)換的類叫source沸毁。適配器模式可以分為:類的適配器模式,對(duì)象的適配器傻寂,接口的適配器息尺。

類的適配器模式

已有的被轉(zhuǎn)換的類:

public class SourceClass {

    public void method1() {
        System.out.print("Hi, I am a method in sourceClass");
    }

}

期望的目標(biāo):

public interface Targetable {
    void method1();
    void method2();
}

實(shí)現(xiàn)目標(biāo),進(jìn)行適配

public class AdapterClass extends SourceClass implements Targetable {

    @Override
    public void method2() {
        System.out.print("Hi All, I am a method in adapterClass");
    }
}

這樣子就將SourceClass按照意愿Targetable適配轉(zhuǎn)換成了AdapterClass疾掰,AdapterClass具有了SourceClass的所有的功能搂誉,同時(shí)也達(dá)到了擴(kuò)展SourceClass。由于類的適配器模式是通過繼承實(shí)現(xiàn)的静檬,它具有了繼承的優(yōu)缺點(diǎn)炭懊。關(guān)于缺點(diǎn),比如通過AdapterClass對(duì)象可以調(diào)用屬于SourceClass而在Targetable接口中沒有的方法拂檩。

對(duì)象的適配器模式

對(duì)象的適配器模式侮腹,就是將原來類的對(duì)象轉(zhuǎn)換為目標(biāo)接口的對(duì)象。對(duì)象適配器模式?jīng)]有繼承被轉(zhuǎn)換類稻励,而是持有被轉(zhuǎn)換類的對(duì)象父阻。這可以避免繼承被帶來的副作用。

public class AdapterObjectClass implements Targetable{

    private SourceClass mSourceClass;

    public AdapterObjectClass(SourceClass mSourceClass) {
        this.mSourceClass = mSourceClass;
    }

    @Override
    public void method2() {
        System.out.print("hi all, i am a method in AdapterObjectClass");
    }

    @Override
    public void method1() {
        mSourceClass.method1();
    }
}

接口的適配器模式

當(dāng)一個(gè)接口有很多的抽象方法時(shí)钉迷,當(dāng)我們寫這個(gè)接口的實(shí)現(xiàn)類至非,必須實(shí)現(xiàn)該接口的全部方法。而有時(shí)候接口中并不是所有的抽象方法都是我們必須的糠聪,而我們只需要實(shí)現(xiàn)其中的某一些方法。為了解決這個(gè)問題谐鼎,我們可以使用接口的適配器模式舰蟆,引入一個(gè)抽象類趣惠,這個(gè)抽象類提供了接口所有抽象方法的空實(shí)現(xiàn)。我們可以繼承這個(gè)抽象類身害,并只重寫我們需要的方法即可味悄。

比如,在上面我們只要Targetable的method2方法塌鸯。

public abstract class AdapterInterfaceClass implements Targetable{

    @Override
    public void method1() {

    }

    @Override
    public void method2() {

    }
}
public class AdapterWraper extends AdapterInterfaceClass {

    @Override
    public void method1() {
        System.out.print("hi all, I am a method in AdapterWraper class");
    }
}

裝飾者模式

裝飾者模式的核心思想是侍瑟,裝飾者和被裝飾者實(shí)現(xiàn)同一個(gè)接口,將被裝飾者注入裝飾者中丙猬,可以在裝飾者中擴(kuò)展被裝飾者涨颜。

public interface Person {
    void eat();
}

被裝飾者:

public class Man implements Person {

    @Override
    public void eat() {
        System.out.print("There is a man who is eating");
    }
}

裝飾者:

public class ManDecorator implements Person {

    private Person mPerson;

    public ManDecorator(Person person) {
        mPerson = person;
    }

    @Override
    public void eat() {
        mPerson.eat();
        drinkWater();
        System.out.print("I finish my lunch");
    }

    private void drinkWater() {
        System.out.print("Man is drinking water");
    }
}

使用:

Man man = new Man();
ManDecorator manDecorator = new ManDecorator(man);
manDecorator.eat();

輸出的結(jié)果:

There is a man who is eating
Man is drinking water
I finish my lunch

代理模式

注意區(qū)別代理模式和動(dòng)態(tài)代理。

生活中代理的例子茧球。比如如果你要租房子庭瑰,你可能不知道該地區(qū)的房子信息,這時(shí)你可以找一個(gè)熟悉的人來幫忙抢埋,這個(gè)幫你的人就是代理弹灭;又比如,打官司時(shí)揪垄,我們可能并不精通法律知識(shí)穷吮,這時(shí)我們可以找一個(gè)代理律師來幫我們。等等饥努。酒来。對(duì)于,代理的工作可以抽象為一個(gè)接口肪凛。

public interface WorkInterface {
    void rentHouse();
}

一個(gè)房東:

public class LandLady implements WorkInterface {

    @Override
    public void rentHouse() {
        System.out.print("您好堰汉!我是房東。我這里有房子出租伟墙!");
    }
}

代理房東的代理類:

public class Proxy implements WorkInterface {

    private LandLady mLandLady;

    public Proxy() {
        mLandLady = new LandLady();
    }

    @Override
    public void rentHouse() {
        mLandLady.rentHouse();
    }
}

租客去找代理租房子:

WorkInterface proxy = new Proxy();
proxy.rentHouse();

外觀模式

在醫(yī)院里的前臺(tái)接待員就是一個(gè)外觀模式的體現(xiàn)翘鸭。由于病人來到醫(yī)院可能對(duì)醫(yī)院內(nèi)部和流程并不熟悉,那么可以由熟悉這些的接待員來幫病人來完成這些事情戳葵。

部門1

public class ModuleA {

    //提供給外部調(diào)用的方法
    public void a1() {}

    //內(nèi)部完成工作的實(shí)現(xiàn)
    private void a2() {}
    private void a3() {}
}

部門2

public class ModuleB {

    //提供給外部調(diào)用的方法
    public void b1() {}

    //內(nèi)部完成工作的實(shí)現(xiàn)
    private void b2() {}
    private void b3() {}
}

部門3

public class ModuleC {

    //提供給外部調(diào)用的方法
    public void c1() {}

    //內(nèi)部完成工作的實(shí)現(xiàn)
    private void c2() {}
    private void c3() {}
}

外觀類:

public class ModuleFacade {

    private ModuleA mModuleA = new ModuleA();
    private ModuleB mMBModuleB = new ModuleB();
    private ModuleC mMCModuleC = new ModuleC();

    public void a1() {
        mModuleA.a1();
    }

    public void b1() {
        mMBModuleB.b1();
    }

    public void c1() {
        mMCModuleC.c1();
    }

}

當(dāng)我們需要ModuleA就乓,ModuleB, ModuleC的功能時(shí)拱烁,我們并不直接和他們打交道生蚁,也不需要了解部門的功能是如何實(shí)現(xiàn)的,而我們只需要去找外觀類溝通即可戏自。

外觀模式的關(guān)鍵點(diǎn)是整合邦投。

橋接模式

橋接模式,提供一個(gè)解耦或者連接抽象化和實(shí)現(xiàn)化的一個(gè)橋梁擅笔,使得二者可以獨(dú)立變化志衣。

一個(gè)接口作為橋屯援,一個(gè)抽象類持有橋。橋和抽象類兩者可以獨(dú)立變化念脯。

橋:

public interface Qiao {
    void toArea();
}

抽象類:

public abstract class FromArea {
    public Qiao qiao;
    abstract public void fromArea();
}

QiaoC.java

public class QiaoC implements Qiao {

    @Override
    public void toArea() {
        System.out.print("I want to go Area C");
    }
}

QiaoD.java

public class QiaoD implements Qiao {

    @Override
    public void toArea() {
        System.out.print("I want to go Area D");
    }
}

FromAreaA.java

public class FromAreaA extends FromArea {

    @Override
    public void fromArea() {
        System.out.print("I come from area A");
    }
}

FromAreaB.java

public class FromAreaB extends FromArea {

    @Override
    public void fromArea() {
        System.out.print("I come from area B");
    }
}

使用:

FromAreaA fromAreaA = new FromAreaA();
QiaoC qiaoC = new QiaoC();
fromAreaA.qiao = qiaoC;

fromAreaA.fromArea();
fromAreaA.qiao.toArea();

QiaoD qiaoD = new QiaoD();
fromAreaA.qiao = qiaoD;

fromAreaA.fromArea();
fromAreaA.qiao.toArea();

從上面可以看出狞洋,Qiao和FromArea兩者是獨(dú)立變化的,它們的抽象和實(shí)現(xiàn)是分離的绿店。

如果有更多的Qiao和FromArea的實(shí)現(xiàn)吉懊,只要擴(kuò)展它們即可。

組合模式

組合模式假勿,又叫“整體-部分設(shè)計(jì)模式”借嗽。它一般用于實(shí)現(xiàn)樹形結(jié)構(gòu)。

節(jié)點(diǎn)

public class TreeNode {

    private String name;
    private TreeNode parent;
    private Vector<TreeNode> children = new Vector<>();

    public TreeNode(String name) {
        this.name = name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setParent(TreeNode parent) {
        this.parent = parent;
    }

    public TreeNode getParent() {
        return parent;
    }

    public void addChild(TreeNode child) {
        children.add(child);
    }

    public boolean removeChild(TreeNode child) {
        return children.remove(child);
    }

    public Enumeration<TreeNode> getChildren() {
        return children.elements();
    }

}

整體废登,建立一棵樹:

public class Tree {
    TreeNode root = null;

    public Tree(String name) {
        root = new TreeNode(name);
    }

    public static void main(String[] args) {
        Tree tree = new Tree("A");
        TreeNode nodeB = new TreeNode("B");
        TreeNode nodeC = new TreeNode("C");

        nodeB.addChild(nodeC);
        tree.root.addChild(nodeB);
        System.out.println("build the tree finished!");
    }
}

享元模式

享元模式主要是實(shí)現(xiàn)對(duì)象的共享淹魄。聯(lián)想數(shù)據(jù)庫的連接池。

public class ConnectionPool {  
      
    private Vector<Connection> pool;  
      
    /*公有屬性*/  
    private String url = "jdbc:mysql://localhost:3306/test";  
    private String username = "root";  
    private String password = "root";  
    private String driverClassName = "com.mysql.jdbc.Driver";  
  
    private int poolSize = 100;  
    private static ConnectionPool instance = null;  
    Connection conn = null;  
  
    /*構(gòu)造方法堡距,做一些初始化工作*/  
    private ConnectionPool() {  
        pool = new Vector<Connection>(poolSize);  
  
        for (int i = 0; i < poolSize; i++) {  
            try {  
                Class.forName(driverClassName);  
                conn = DriverManager.getConnection(url, username, password);  
                pool.add(conn);  
            } catch (ClassNotFoundException e) {  
                e.printStackTrace();  
            } catch (SQLException e) {  
                e.printStackTrace();  
            }  
        }  
    }  
  
    /* 返回連接到連接池 */  
    public synchronized void release() {  
        pool.add(conn);  
    }  
  
    /* 返回連接池中的一個(gè)數(shù)據(jù)庫連接 */  
    public synchronized Connection getConnection() {  
        if (pool.size() > 0) {  
            Connection conn = pool.get(0);  
            pool.remove(conn);  
            return conn;  
        } else {  
            return null;  
        }  
    }  
}  
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末甲锡,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子羽戒,更是在濱河造成了極大的恐慌缤沦,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,348評(píng)論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件易稠,死亡現(xiàn)場(chǎng)離奇詭異缸废,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)驶社,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,122評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門企量,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人亡电,你說我怎么就攤上這事届巩。” “怎么了份乒?”我有些...
    開封第一講書人閱讀 156,936評(píng)論 0 347
  • 文/不壞的土叔 我叫張陵恕汇,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我或辖,道長(zhǎng)瘾英,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,427評(píng)論 1 283
  • 正文 為了忘掉前任颂暇,我火速辦了婚禮缺谴,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘蟀架。我一直安慰自己瓣赂,他們只是感情好榆骚,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,467評(píng)論 6 385
  • 文/花漫 我一把揭開白布片拍。 她就那樣靜靜地躺著煌集,像睡著了一般。 火紅的嫁衣襯著肌膚如雪捌省。 梳的紋絲不亂的頭發(fā)上苫纤,一...
    開封第一講書人閱讀 49,785評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音纲缓,去河邊找鬼卷拘。 笑死,一個(gè)胖子當(dāng)著我的面吹牛祝高,可吹牛的內(nèi)容都是我干的栗弟。 我是一名探鬼主播,決...
    沈念sama閱讀 38,931評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼工闺,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼乍赫!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起陆蟆,我...
    開封第一講書人閱讀 37,696評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤雷厂,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后叠殷,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體改鲫,經(jīng)...
    沈念sama閱讀 44,141評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,483評(píng)論 2 327
  • 正文 我和宋清朗相戀三年林束,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了像棘。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,625評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡壶冒,死狀恐怖缕题,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情依痊,我是刑警寧澤避除,帶...
    沈念sama閱讀 34,291評(píng)論 4 329
  • 正文 年R本政府宣布,位于F島的核電站胸嘁,受9級(jí)特大地震影響瓶摆,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜性宏,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,892評(píng)論 3 312
  • 文/蒙蒙 一群井、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧毫胜,春花似錦书斜、人聲如沸诬辈。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,741評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽焙糟。三九已至,卻和暖如春样屠,著一層夾襖步出監(jiān)牢的瞬間穿撮,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評(píng)論 1 265
  • 我被黑心中介騙來泰國(guó)打工痪欲, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留悦穿,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,324評(píng)論 2 360
  • 正文 我出身青樓业踢,卻偏偏與公主長(zhǎng)得像栗柒,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子知举,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,492評(píng)論 2 348

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