結構型模式
這篇博文剛開始講述設計模式中另一大分類:結構型模式,共7種適配器模式、裝飾模式、代理模式、外觀模式、橋接模式、組合模式、享元模式。
這其中對象的適配器模式是其他各種結構型模式的起源,他們的衍生關係圖,如下圖:
適配器模式
適配器模式,有時也稱作包裝模式,是指將某一個類的接口適配轉化成用戶所期望的另一接口的情況,
其目的是解決由於接口不匹配所造成的類的兼容性問題。適配器模式又可分爲三種:類的適配器模式,對象的適配器模式,接口的適配器模式。先來了解一下類的適配器模式類的適配器模式
其核心的思想是,現存有一個原始類,擁有一些方法,用戶期望的目標接口除了原始類擁有的原始方法,還需要有新增一些其他方法,這裏通過Adapter類對原始類的方法擴展到目標接口。例如,現存Sms 類,擁有發送短信的方法,用戶期望的適配目標接口除了有發送短信,還有發送延時短信,可以建立一個適配類將Sms 類適配到目標接口,類圖如下:
詳細代碼如下:
Sms 類,擁有發送短信的方法
public class Sms {
public void sendSms() {
System.out.println(String.format("%s.%s called!", this.getClass().getName(), "sendSms()"));
}
}
目標接口,除了有發送短信,還有發送延時短信
public interface Sender {
public void sendSms();
public void sendDelaySms(long delay);
}
適配類將Sms 類適配到目標接口
public class SmsAdapter extends Sms implements Sender {
@Override
public void sendDelaySms(long delay) {
System.out.println(String.format("%s.%s called!", this.getClass().getName(), "sendDelaySms()"));
}
}
測試類代碼:
public class WorkClass {
public void test() {
Sender smsSender= new SmsAdapter();
smsSender.sendSms();
smsSender.sendDelaySms(1000*60*60);
}
}
輸出結果:
I/System.out: com.example.qinghua_liu.myapplication.designpattern.creator.designpattern.struct.adapt.SmsAdapter.sendSms() called!
I/System.out: com.example.qinghua_liu.myapplication.designpattern.creator.designpattern.struct.adapt.SmsAdapter.sendDelaySms() called!
目標接口Sender的實現類具有了原始類Sms的功能方法。
對象的適配器模式
對象的適配器模式的核心思路與類的適配器模式不同,適配類不是繼承原始類,而是持有一個原始類的實例,以達到適配目標接口這一同樣的目的。先看類圖:
新增SmsWrapper類
public class SmsWrapper implements Sender {
private Sms sms;
@Override
public void sendDelaySms(long delay) {
System.out.println(String.format("%s.%s called!", this.getClass().getName(), "sendDelaySms()"));
}
@Override
public void sendSms() {
if (null != sms) {
sms.sendSms();
}
}
public SmsWrapper(Sms smsobj) {
this.sms = smsobj;
}
}
測試類代碼:
public class WorkClass {
public void test() {
Sender smsSender = new SmsWrapper(new Sms());
smsSender.sendSms();
smsSender.sendDelaySms(1000 * 60 * 60);
}
}
輸出結果:
I/System.out: com.example.qinghua_liu.myapplication.designpattern.creator.designpattern.struct.adapt.Sms.sendSms() called!
I/System.out: com.example.qinghua_liu.myapplication.designpattern.creator.designpattern.struct.adapt.SmsWrapper.sendDelaySms() called!
目的輸出與類的適配器一樣,只是實現方式不一樣。
- 第三種適配器模式是接口的適配器模式
接口的適配器模式的應用場景是這樣子的,現存一個接口,它包括一系列等實現的方法,如果我們寫一個類去實現這個接口,就必須全部實現接口的所有方法,可有時這些方法並不是我們全部都想要的,顯然這是一種冗餘。接口的適配器模式正是爲了解決上面所述這種情況,其核心思想是,藉助一個抽象類(abstract class)去實現原始接口,這樣抽象類的子類,就可以不必直接與原始接口打交道而只要重寫抽象類的一些我們想要的方法就可以了。類圖如下:
在實際開發中,我們會遇到某接口中定義了太多的方法,以致於有時我們在一些實現類中並不是都需要用到。
代碼:
Setter 接口:
public interface Setter {
public void setText(String text);
public void setBitmapDrawable(int id);
}
WrapperSetter 抽象類:
public abstract class WrapperSetter implements Setter {
@Override
public void setText(String text) {}
@Override
public void setBitmapDrawable(int id) {}
}
實現子類:
public class TextViewSetter extends WrapperSetter {
@Override
public void setText(String text) {
System.out.println(String.format("%s.%s called!", this.getClass().getName(), "setText()"));
}
}
public class ImageViewSetter extends WrapperSetter {
@Override
public void setBitmapDrawable(int id) {
System.out.println(String.format("%s.%s called!", this.getClass().getName(), "setBitmapDrawable()"));
}
}
測試類代碼:
public class WorkClass {
public void test() {
Setter setterText = new TextViewSetter();
Setter setterImage = new ImageViewSetter();
setterText.setText("");
setterImage.setBitmapDrawable(R.drawable.a500cg_btn);
}
}
輸出結果:
I/System.out: com.example.qinghua_liu.myapplication.designpattern.creator.designpattern.struct.adapt.TextViewSetter.setText() called!
I/System.out: com.example.qinghua_liu.myapplication.designpattern.creator.designpattern.struct.adapt.ImageViewSetter.setBitmapDrawable() called!
- 結語
三種適配器模式分別有各自不同應用場景:
類適配器模式:需求將一個類轉換成實現另一個新接口的類時,可以此模式,創建一個新類,繼承原有的類並實現目標的接口即可。
對象適配器模式:需求將一個對象轉換成滿足另一個新接口的對象時,可以創建一個Wrapper類,持有原類的一個實例,在Wrapper類的實現目標接口的方法中,調用原類實例的方法即可。
接口適配器模式:當不希望實現一個接口中所有的方法時,可以創建一個抽象類Wrapper,實現所有方法,寫子類繼承抽象類的時候,覆寫需要的方法即可。