裝飾模式是幹嗎的呢?它在項目中有哪些用途呢?裝飾模式在Android源碼中有哪些應用呢?本文將和讀者朋友一塊兒分享探討裝飾者模式在Android中的應用和實踐。設計模式
本文原創做者MichaelX。
CSDN博客:https://blog.csdn.net/xiong_it
掘金主頁:https://juejin.im/user/56efe6461ea493005565dafd
知乎專欄:https://zhuanlan.zhihu.com/c_144117654
我的博客:http://blog.michaelx.tech
複製代碼
轉載請註明出處。bash
裝飾者模式:也叫wrapper模式。動態地給一個對象添加一些額外的職責,就增長功能來講,裝飾者模式相比生成子類更加靈活,提供了有別於繼承的另外一種選擇。app
**注意:**在裝飾模式中,必然有一個最基本、最核心、最原始的接口或抽象類充當Component抽象構件。ide
ConcreteComponent 具體構件 ConcreteComponent是最核心、最原始、最基本的接口或抽象類的實現,你要裝飾的就是它。函數
Decorator裝飾角色 通常是一個抽象類,作什麼用呢?實現接口或者抽象方法,它裏面可不必定有抽象的方法呀,在它的屬性裏必然有一個private變量指向Component抽象構件。this
具體裝飾角色 ConcreteDecoratorA和ConcreteDecoratorB是兩個具體的裝飾類,你要把你最核心的、最原始的、最基本的東西裝飾成其餘東西。spa
public abstract class Component {
//抽象的方法
public abstract void operate();
}
複製代碼
public class ConcreteComponent extends Component {
//具體實現
@Override
public void operate() {
System.out.println("do Something");
}
}
複製代碼
public abstract class Decorator extends Component {
private Component component = null;
//經過構造函數傳遞被修飾者
public Decorator(Component _component){
this.component = _component;
}
//委託給被修飾者執行
@Override
public void operate() {
this.component.operate();
}
}
複製代碼
public class ConcreteDecorator1 extends Decorator {
//定義被修飾者
public ConcreteDecorator1(Component _component){
super(_component);
}
//定義本身的修飾方法
private void method1(){
System.out.println("method1 修飾");
}
//重寫父類的Operation方法
public void operate(){
this.method1();
super.operate();
}
}
複製代碼
public class ConcreteDecorator2 extends Decorator {
//定義被修飾者
public ConcreteDecorator2(Component _component){
super(_component);
}
//定義本身的修飾方法
private void method2(){
System.out.println("method2修飾");
}
//重寫父類的Operation方法
public void operate(){
super.operate();
this.method2();
}
}
複製代碼
使用場景類.net
public class Client {
public static void main(String[] args) {
Component component = new ConcreteComponent();
//第一次修飾
component = new ConcreteDecorator1(component);
//第二次修飾
component = new ConcreteDecorator2(component);
//修飾後運行
component.operate();
}
}
複製代碼
Context是Android中一個幾乎無處不在的角色,ContextWrapper/ContextThemeWrapper就在繼承過程當中承擔了ContextImpl的裝飾者角色。 設計
ContextThemeWrapper部分代碼爲例:public class ContextThemeWrapper extends ContextWrapper {
private int mThemeResource;
private Resources.Theme mTheme;
private LayoutInflater mInflater;
private Configuration mOverrideConfiguration;
private Resources mResources;
@Override
public AssetManager getAssets() {
// Ensure we're returning assets with the correct configuration. return getResourcesInternal().getAssets(); } @Override public Resources getResources() { return getResourcesInternal(); } private Resources getResourcesInternal() { if (mResources == null) { if (mOverrideConfiguration == null) { mResources = super.getResources(); } else { final Context resContext = createConfigurationContext(mOverrideConfiguration); mResources = resContext.getResources(); } } return mResources; } @Override public Resources.Theme getTheme() { if (mTheme != null) { return mTheme; } mThemeResource = Resources.selectDefaultTheme(mThemeResource, getApplicationInfo().targetSdkVersion); initializeTheme(); return mTheme; } @Override public Object getSystemService(String name) { if (LAYOUT_INFLATER_SERVICE.equals(name)) { if (mInflater == null) { mInflater = LayoutInflater.from(getBaseContext()).cloneInContext(this); } return mInflater; } return getBaseContext().getSystemService(name); } protected void onApplyThemeResource(Resources.Theme theme, int resId, boolean first) { theme.applyStyle(resId, true); } private void initializeTheme() { final boolean first = mTheme == null; if (first) { mTheme = getResources().newTheme(); final Resources.Theme theme = getBaseContext().getTheme(); if (theme != null) { mTheme.setTo(theme); } } onApplyThemeResource(mTheme, mThemeResource, first); } } 複製代碼
還有一個比較典型的例子是RecyclerView經過RecyclerView.ItemDecorator來擴展樣式。 不過這個是一個變種的裝飾者,這個實踐比較另類的地方在於:咱們一般是在裝飾者的的執行方法中擴展被代理對象的行爲,而RecyclerView+ItemDecorator的實踐則偏偏相反,ItemDecorator反倒成了被代理對象,RecyclerView成了裝飾者。3d
說實話,筆者本身也沒有實踐過裝飾模式,可是有一個場景需求應該是能夠應用裝飾模式的。好比一個直播場景,點擊禮物時須要禮物飛出來,雙擊有一個愛心❤️飄出來,那麼禮物和愛心就能夠當作是直播畫面的裝飾者,類關係以下:
GirlView:主播畫面 GirlDecorator:主播畫面裝飾者 GiftView:禮物效果 LoveView:愛心效果特色:裝飾模式其實就是在代理某個對象過程當中,給特定的代理行爲先後加上不一樣的裝飾行爲,好比文中的ContextThemeWrapper
就在代理ContextImpl
的getSystemService
這個行爲過程當中,加上了返回LayoutInflater這個裝飾行爲。所以,咱們也能夠認爲裝飾模式實際上是一種特殊的代理模式
裝飾模式的優缺點 優勢:
裝飾類和被裝飾類能夠獨立發展,而不會相互耦合。換句話說,Component類無須知道Decorator類,Decorator類是從外部來擴展Component類的功能,而Decorator也不用知道具體的構件。
裝飾模式是繼承關係的一個替代方案。咱們看裝飾類Decorator,無論裝飾多少層,返回的對象仍是Component,實現的仍是is-a的關係。
裝飾模式能夠動態地擴展一個實現類的功能,這不須要多說,裝飾模式的定義就是如此。
缺點:
當某個對象的行爲須要增強,而且可能有多種增強的需求時,那麼裝飾模式有可能就能排上用場了。
好了,今天的《設計模式Android篇:裝飾模式》就到這裏,請繼續關注《Design Patterns in Android》(設計模式Android篇)系列博文,歡迎各位讀者朋友評論區拍磚交流,共同進步。