天天看點

【設計模式】擴充卡模式:攻敵三分,自留七分,以超獸武裝的例子來談談擴充卡模式

文章目錄

  • ​​1 擴充卡模式​​
  • ​​1.1 定義​​
  • ​​1.2 結構​​
  • ​​1.3 類圖​​
  • ​​1.3.1 類擴充卡模式​​
  • ​​1.3.2 對象擴充卡模式​​
  • ​​2 例子​​
  • ​​2.1 類擴充卡模式​​
  • ​​2.1.1 代碼​​
  • ​​2.1.2 效果圖​​
  • ​​2.2 對象擴充卡模式​​
  • ​​2.2.1 代碼​​
  • ​​2.2.2 效果通​​
  • ​​3 優缺點及适用環境​​
  • ​​3.1 優點​​
  • ​​3.2 缺點​​
  • ​​3.3 适用環境​​

1 擴充卡模式

1.1 定義

将一個類的接口轉換成客戶希望的另外一個接口,使得原本由于接口不相容而不能在一起工作的那些類能一起工作。

擴充卡模式分為類擴充卡模式和對象擴充卡模式,前者類(類擴充卡)之間的耦合度比後者高,而且要求程式員了解現有元件庫中的相關元件的内部結構,是以應用相對少一些。

1.2 結構

  • 目标接口(Target):目前系統業務所期待的接口,它可以是抽象類或者接口。
  • 适配者類(Adaptee):他是被通路和适配的現存元件庫中的元件接口。
  • 擴充卡類(Adapter):它是一個轉換器,通過**繼承(類)或引用(對象)**适配者的對象,把适配者接口轉換成目标接口,讓客戶按目标接口的格式通路适配者。
個人認為:擴充卡的作用就是讓使用者使用A的功能而達到B功能的效果。

1.3 類圖

1.3.1 類擴充卡模式

【設計模式】擴充卡模式:攻敵三分,自留七分,以超獸武裝的例子來談談擴充卡模式

1.3.2 對象擴充卡模式

為什麼要有對象擴充卡模式,因為類擴充卡模式違反了合成/聚合複用原則,也就是優先考慮組合/聚合來實作複用,其次考慮繼承(使用繼承需要嚴格遵循裡氏代換原則,濫用繼承會增加系統建構和維護的難度以及系統的複雜度)
【設計模式】擴充卡模式:攻敵三分,自留七分,以超獸武裝的例子來談談擴充卡模式

2 例子

【設計模式】擴充卡模式:攻敵三分,自留七分,以超獸武裝的例子來談談擴充卡模式
國産卡通片《超獸武裝》中的角色就很符合擴充卡模式。他們可以以普通模式進行戰鬥,也可以通過異能鎖(擴充卡)來召喚超獸武裝進行戰鬥。角色(如龍戬)想要發送技能–寒影決,通過異能鎖,将其變成了威力更為強大的超獸形态寒影決。

普通形态的龍戬

也可以攻擊和使用寒影決
【設計模式】擴充卡模式:攻敵三分,自留七分,以超獸武裝的例子來談談擴充卡模式

異能鎖

借助異能鎖,超獸武裝,将自己的寒影決變成超獸武裝的寒影決,威力更大
【設計模式】擴充卡模式:攻敵三分,自留七分,以超獸武裝的例子來談談擴充卡模式

超獸武裝

可以攻擊、使用超獸狀态下的寒影決
【設計模式】擴充卡模式:攻敵三分,自留七分,以超獸武裝的例子來談談擴充卡模式

2.1 類擴充卡模式

2.1.1 代碼

在此例子中,有四個重要的角色 龍戬(DargonJian)、普通形态(Common)、超獸武裝形态(Mocha)、異能鎖(PowerLock)。使用擴充卡的目的即為龍戬在使用普通形态的技能時底層調用的是超獸武裝形态的技能方法。

至于為什麼是類擴充卡模式而不是對象擴充卡模式,核心就在于在将普通形态接口轉化成超獸武裝形态的過程中,擴充卡類繼承了超獸武裝形态的實作類,而不是建立一個超獸武裝形态類的對象。

Common.interface

/* 普通狀态 */
public interface Common {
    /* 攻擊 */
    void attack();
    /* 大招 */
    void bigMove(String msg);

}      

CommonImpl.java

/* 普通形态類 */
public class CommonImpl implements Common {

    @Override
    public void attack() {
        System.out.println("稀裡嘩啦做了一套廣播體操,對敵人造成了1點傷害");
    }

    @Override
    public void bigMove(String msg) {
        System.out.println("放出了大招"+msg);
    }
}      

Mocha.interface

/* 超獸武裝 */
public interface Mocha {
    /* 攻擊 */
    void attack();
    /* 大招 */
    void bigMove(String msg);
}      

MochaImpl.java

/*
* 超獸武裝
* */
public class MochaImpl implements Mocha {

    @Override
    public void attack() {
        System.out.println("超獸武裝形态下對敵攻擊,造成1W點傷害");
    }

    @Override
    public void bigMove(String msg) {
        System.out.println("超獸武裝形态下放出了大招"+msg);
    }
}      

PowerLock.java

/*
* 異能鎖:擴充卡
* */
public class PowerLock extends MochaImpl implements Common {

    @Override
    public void attack() {

        super.attack();
    }

    @Override
    public void bigMove(String msg) {
        super.bigMove(msg);
    }
}      

DargonJian.java

public class DragonJian {
    /* 龍戬攻擊 */
    public void attack(Common common)
    {
        if(common == null)
        {
            throw new NullPointerException("沒有普通形态");
        }
        common.attack();
    }
    /* 寒影決 */
    public void bigMove(Common common,String msg)
    {
        if(common == null)
        {
            throw new NullPointerException("沒有普通形态");
        }
        common.bigMove(msg);
    }
}      

Client.java

public class Client {
    public static void main(String[] args) {
        /* 龍戬 */
        DragonJian dragonJian = new DragonJian();
        /* 普通攻擊*/
        dragonJian.attack(new CommonImpl());
        dragonJian.bigMove(new CommonImpl(),"寒影決");
        System.out.println("=====借助異能鎖,超獸武裝=====");
        dragonJian.attack(new PowerLock());
        dragonJian.bigMove(new PowerLock(),"寒影決");
    }


}      

2.1.2 效果圖

【設計模式】擴充卡模式:攻敵三分,自留七分,以超獸武裝的例子來談談擴充卡模式

2.2 對象擴充卡模式

這裡為了符合合成/聚合複用原則,将原有的繼承改成了組合/聚合的形式

2.2.1 代碼

Client.java

public class Client {
    public static void main(String[] args) {
        /* 龍戬 */
        DragonJian dragonJian = new DragonJian();
        /* 普通攻擊*/
        dragonJian.attack(new CommonImpl());
        dragonJian.bigMove(new CommonImpl(),"寒影決");
        System.out.println("=====借助異能鎖,超獸武裝=====");
        PowerLock powerLock = new PowerLock(new MochaImpl());
        dragonJian.attack(powerLock);
        dragonJian.bigMove(powerLock,"寒影決");
    }


}      

Common.java

/* 普通狀态 */
public interface Common {
    /* 攻擊 */
    void attack();
    /* 大招 */
    void bigMove(String msg);

}      

CommonImpl.java

/* 普通形态類 */
public class CommonImpl implements Common {

    @Override
    public void attack() {
        System.out.println("稀裡嘩啦做了一套廣播體操,對敵人造成了1點傷害");
    }

    @Override
    public void bigMove(String msg) {
        System.out.println("放出了大招"+msg);
    }
}      

DragonJian.java

public class DragonJian {
    /* 龍戬攻擊 */
    public void attack(Common common)
    {
        if(common == null)
        {
            throw new NullPointerException("沒有普通形态");
        }
        common.attack();
    }
    /* 寒影決 */
    public void bigMove(Common common, String msg)
    {
        if(common == null)
        {
            throw new NullPointerException("沒有普通形态");
        }
        common.bigMove(msg);
    }
}      

Mocha.java

/* 超獸武裝 */
public interface Mocha {
    /* 攻擊 */
    void attack();
    /* 大招 */
    void bigMove(String msg);
}      

MochaImpl.java

/*
* 超獸武裝
* */
public class MochaImpl implements Mocha {

    @Override
    public void attack() {
        System.out.println("超獸武裝形态下對敵攻擊,造成1W點傷害");
    }

    @Override
    public void bigMove(String msg) {
        System.out.println("超獸武裝形态下放出了大招"+msg);
    }
}      

PowerLock.java

/*
* 異能鎖:擴充卡
* */
public class PowerLock implements Common {

    MochaImpl mocha = new MochaImpl();

    public PowerLock(MochaImpl mocha) {
        this.mocha = mocha;
    }

    @Override
    public void attack() {

        mocha.attack();
    }

    @Override
    public void bigMove(String msg) {
        mocha.bigMove(msg);
    }
}      

2.2.2 效果通

3 優缺點及适用環境

3.1 優點

  • 一個對象擴充卡可以把多個不同的擴充卡适配到同一個目标
  • 可以适配一個适配者的子類,由于擴充卡和适配者之間是關聯關系,根據"裡氏代換原則",适配者的子類也可以通過該擴充卡進行适配。
  • 将目标類和适配者類解耦,通過引入一個擴充卡類來重用現有的适配者類,而無需修改原有的代碼。增加了類的透明性和複用性,将具體的實作封裝在适配者類中,對于用戶端類來說是透明的,而且提高了适配者的複用性。

3.2 缺點

  • 對于Java、C#等不支援多重類繼承的語言,一次最多隻能适配一個适配者類,不能同時适配多個适配者。
  • 在Java、C#等語言中,類适配者模式中的目标抽象類隻能為接口,不能為類,其使用有一定的局限性。

3.3 适用環境