使用轉接頭(適配器)

  前倆天老媽說從家裏抽屜裏找到個耳機但是用不了,我讓她拍個照片給我看,原來是因爲手機是Type-C接口,耳機是3.5mm頭的。於是我買了個轉接口給她。如下圖:
在這裏插入圖片描述
  本能反應的我,立馬開始聯想了起來…


適配器

情景1 沒有耳機

  mom的手機

public class MomPhone {

    private TypeC earphone;

    public void play(){
        if (earphone == null) {
            System.out.println("loudspeaker play");
        } else {
            System.out.println(earphone.getType() + " earphone play");
        }
    }

    public void connect(TypeC earphone){
        this.earphone = earphone;
    }
}

  播放狀態是揚聲器外放

MomPhone momPhone = new MomPhone();
momPhone.play(); // loudspeaker play
情景2 連接Type-C接口的華爲耳機
public interface TypeC {
    String getType();
}

public class TypeCHW implements TypeC {
    @Override
    public String getType() {
        return "Huawei";
    }
}

  播放狀態是華爲耳機播放

momPhone.connect(new TypeCHW());
momPhone.play(); // Huawei earphone play
情景3 連接3.5mm的JBL耳機
public interface M35 {
    String getType();
}

public class M35JBL implements M35 {
    @Override
    public String getType() {
        return "JBL";
    }
}

  接口不對應是不能使用的,所以需要一個如圖的轉接頭

public class Adapter implements TypeC{

    private M35 m35;

    public Adapter(M35 m35) {
        this.m35 = m35;
    }

    @Override
    public String getType() {
        return m35.getType();
    }
}

  轉接頭需要連接手機,所以必須實現Type-C接口,並且暴露一個3.5mm接口,讓3.5mm的設備連接自己,就是Adapter的構造方法。
  有了轉接口就可以播放了

momPhone.connect(new Adapter(new M35JBL()));
momPhone.play(); // JBL earphone play

適配器模式

  情景3中將3.5mm設備通過轉接口連接上Type-C接口的設備的過程,就是使用了設計模式中適配器模式,那個轉接頭就是適配器。
  適配器模式可以分爲類適配、對象適配、接口適配,上面用的就是對象適配。

類適配
public class M35JBLAdapter extends M35JBL implements TypeC {
    @Override
    public String getType() {
        return super.getType();
    }
}

  要描述上面這個類,可以理解JBL的廠商將原來的JBL耳機升級爲Type-C接口一樣,是專門針對M35JBL這款設備做了適配一樣。

momPhone.connect(new M35JBLAdapter());
momPhone.play(); // JBL earphone play
接口適配

  這種模式在業務代碼中應該很少遇到。大致描述就是說,有一個接口中定義了很多方法,如果想只實現其中部分的話,可以在接口和實現類中增加一層抽象類,抽象類實現接口所有方法,但是都是空實現,自定義類繼承抽象類可以重寫其中部分方法。

public interface A {
    void a();
    void b();
    void c();
    void d();
    void e();
    void f();
    void g();
    void h();
}
public abstract class AbstractA implements A {
    public void a() {}
    public void b() {}
    public void c() {}
    public void d() {}
    public void e() {}
    public void f() {}
    public void g() {}
    public void h() {}
}
public class AImpl extends AbstractA {
    public void b() {
        System.out.println();
    }
    public void e() {
        System.out.println();
    }
}

  其中的AbstractA類就是適配器。

策略模式

  策略模式大多情況用在根據不同角色(或類型)處理不同業務的場景中(比如遊客、VIP、活動送的VIP)。舉個例子:

		if ("tourists".equals(type)) {
            // 業務a
        } else if ("vip".equals(type)) {
            // 業務a
        } else if ("presenterVip".equals(type)) {
            // 業務a
        } else {
            // 業務a
        }

  隨着業務代碼行數比較多的時候,將每個業務代碼提成一個單獨的方法,可讀性很高。直到增加了一個爲 SVIP 的類型,原來的業務方法可能也需要拆分,於是決定將每個方法都獨立成一個類。
在這裏插入圖片描述

public interface Role {
    void run();
}

public class VIP implements Role {
    @Override
    public void run() {
        // vip
    }
}

public class SVIP implements Role {
    @Override
    public void run() {
        // 金主爸爸,什麼權限都開
    }
}

public class Tourists implements Role {
    @Override
    public void run() {
        // 窮b,不需要操作
        return;
    }
}

public class PVIP implements Role{
    @Override
    public void run() {
        // 活動送的vip,只設置頭像掛飾
    }
}

  另外定義一個業務類,將業務方法抽取出來

public class RoleService {

    private Role role;

    public RoleService(Role role){
        this.role = role;
    }

    public void run(){
        role.run();
    }
}

  最初的調用方式變成了下面這樣:

		Role role = null;
        if ("tourists".equals(type)) {
            role = new Tourists();
        } else if ("vip".equals(type)) {
            role = new VIP();
        } else if ("presenterVip".equals(type)) {
            role = new PVIP();
        } else if ("svip".equals(type)){
            role = new SVIP();
        }
        RoleService roleService = new RoleService(role);
        roleService.run(); // 業務a

  如果再次增加一種類型,同樣執行業務a,那麼擴展Role接口的實現類即可(程序設計開閉原則:對擴展開放,對修改關閉),以上改進流程就是運用了策略設計模式。每種角色有單獨的實現類後,其中只包含該角色應該要做的業務,不和其他角色業務混在一起(單一職能原則),降低業務間的耦合。
  但是貌似這麼多if-else還是沒有刪除,還是要修改if-else內容。其實這塊代碼可以抽象成工廠方法,需要根據type獲取對應角色實現類,用在程序其他地方。

簡單工廠模式

public class RoleFactory {
    
    public static Role create(String type) {
        if ("tourists".equals(type)) {
            return new Tourists();
        } else if ("vip".equals(type)) {
            return new VIP();
        } else if ("presenterVip".equals(type)) {
            return new PVIP();
        } else if ("svip".equals(type)){
            return new SVIP();
        } else {
            throw new RuntimeException("Type Error");
        }
    }
}

  使用簡單工廠

        Role role = RoleFactory.create(type);
        RoleService roleService = new RoleService(role);
        roleService.run(); // 業務a

最後

  剛開始寫代碼的時候並不知道設計模式有什麼用,感覺花裏胡哨還把自己繞暈了,直到在多個項目中由於需求的增加,發現自己寫的代碼改起來越來越費勁,慢慢的重構改進後,有一天發現自己原來用了設計模式(第一個是策略模式)。那麼下次遇到這種業務場景,開始就按一種模式設計後,不論是後期優化還是擴展都很方便,而且代碼的可讀性也很好。
  每個人對設計模式態度是不一樣的,站的高度不同,看法也不同。“看山是山,看水是水;看山不是山,看水不是水;看山還是山,看水還是水”。不知道自己何時能修煉到那個境界。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章