裝飾者模式及其應用
前幾天看了鴻洋大神的 Android 優雅的為RecyclerView新增HeaderView和FooterView,發現裝飾者模式 在某些情況下是設計得如此 優雅,現在總結如下:
本篇部落格主要講解一下幾個問題
- 什麼 是裝飾者模式
- 怎樣實現裝飾者模式
- 裝飾者模式的優缺點
- 裝飾者模式在Android中的應用
什麼是裝飾者模式
應用場景
咖啡店裡咖啡中可以加不同的配料–摩卡、牛奶、糖、奶泡;不同的飲品加上不同的配料有不同的價錢,怎樣實現呢?
可能你的第一印象會想到使用繼承,
1. 首先定義一個咖啡基類
2. 對於加糖的,加牛奶的,加摩卡的 ,加奶泡的,分別寫一個子類繼承
3. 對於加糖,又加奶的寫一個類,對於對於加糖,又摩卡的寫一個類,對於對於加糖、又奶泡的寫一個類,對於加糖,又加奶、摩卡的寫一個類—-
說到這裡,你會發現這裡四種配料就要寫十幾種實現類了,那如果我們的配料是二十幾種或者三十幾種呢,那麼使用繼承這種 方式肯定會使我們的子類爆炸,那要怎樣解決你,答案就是使用裝飾者模式
定義
我覺得裝飾者模式是在已有功能的基礎之上,動態地新增更多 功能的一種方式,這些新加的程式碼裝飾了原有類的 核心職責或主要行為。
類UML圖
效果圖
怎樣實現裝飾者模式呢?
首先我們先來看一下我們的設計類圖
- 1) 首先我們定義一個Coffce基類
/**
* @ explain:這裡Coffee相當於我們的Component,
* 是要裝飾的類
*
* @ author:xujun on 2016/7/10 23:16
* @ email:[email protected]
*/
public abstract class Coffee {
/**
*
* @return 返回價格
*/
public abstract int getPrice();
/**
* 返回名字
* @return
*/
public abstract String getName();
}
- 2) 接著 我們定義一個Decorator類繼承 我們的Coffice基類
/**
* @ explain:
* @ author:xujun on 2016/7/10 23:21
* @ email:[email protected]
*/
public abstract class Decorator extends Coffee{
protected Coffee mCoffee;
/**
* 通過組合的方式把Coffee物件傳遞進來
* @param coffee
*/
public Decorator(Coffee coffee){
mCoffee=coffee;
}
}
- 3)接下來我們來看我們的子類是怎樣實現的
public class MilkDecorator extends Decorator {
/**
* 通過組合的方式把Coffee物件傳遞進來
*
* @param coffee
*/
public MilkDecorator(Coffee coffee) {
super(coffee);
}
@Override
public int getPrice() {
return mCoffee.getPrice()+10;
}
@Override
public String getName() {
return "addMilk";
}
}
其實核心程式碼就下面一行,在原來的價格加上 加牛奶的價格
return mCoffee.getPrice()+10
- 4)接下來不難想象加糖,就奶泡。就摩卡的操作,都是在原來的之上加上配料的價格
return mCoffee.getPrice()+2;
return mCoffee.getPrice()+15;
return mCoffee.getPrice()+20;
總結
以後你想要計算加糖,就牛奶,加奶泡的咖啡的價格,只需要這樣
mCoffee = new SimpleCoffee();
mCoffee = new SugarDecorator(mCoffee);
mCoffee = new MilkDecorator(mCoffee);
mCoffee = new MilkFoamDecorator(mCoffee);
int price1 = mCoffee.getPrice();
System.out.println("price1="+price1);
以後你想要計算加糖,就牛奶咖啡的價格,只需要這樣
mCoffee = new SimpleCoffee();
mCoffee = new SugarDecorator(mCoffee);
mCoffee = new MilkDecorator(mCoffee);
int price1 = mCoffee.getPrice();
System.out.println("price1="+price1);
裝飾者模式的優缺點
優點
- 把類中的裝飾功能從類中搬除,可以簡化原來的類
- 可以把類的 核心職責和裝飾功能區分開來,結構清晰 明瞭並且可以去除相關類的重複的裝飾邏輯。
裝飾者模式在Android中的應用
效果圖
- 下面我們來看一下我們是如何 優雅的為RecyclerView新增HeaderView和FooterView
/**
* 部落格地址:http://blog.csdn.net/gdutxiaoxu
* @author xujun
* @time 2016/7/7 17:29.
*/
public class HeaderAndFooterWrapper<T> extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private static final int BASE_ITEM_TYPE_HEADER = 100000;
private static final int BASE_ITEM_TYPE_FOOTER = 200000;
private SparseArrayCompat<View> mHeaderViews = new SparseArrayCompat<>();
private SparseArrayCompat<View> mFootViews = new SparseArrayCompat<>();
private RecyclerView.Adapter mInnerAdapter;
public HeaderAndFooterWrapper(RecyclerView.Adapter adapter) {
mInnerAdapter = adapter;
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (mHeaderViews.get(viewType) != null) {
ViewHolder holder = ViewHolder.createViewHolder(parent.getContext(), mHeaderViews.get
(viewType));
return holder;
} else if (mFootViews.get(viewType) != null) {
ViewHolder holder = ViewHolder.createViewHolder(parent.getContext(), mFootViews.get
(viewType));
return holder;
}
return mInnerAdapter.onCreateViewHolder(parent, viewType);
}
@Override
public int getItemViewType(int position) {
if (isHeaderViewPos(position)) {
return mHeaderViews.keyAt(position);
} else if (isFooterViewPos(position)) {
return mFootViews.keyAt(position - getHeadersCount() - getRealItemCount());
}
return mInnerAdapter.getItemViewType(position - getHeadersCount());
}
private int getRealItemCount() {
return mInnerAdapter.getItemCount();
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
if (isHeaderViewPos(position)) {
return;
}
if (isFooterViewPos(position)) {
return;
}
mInnerAdapter.onBindViewHolder(holder, position - getHeadersCount());
}
@Override
public int getItemCount() {
return getHeadersCount() + getFootersCount() + getRealItemCount();
}
@Override
public void onAttachedToRecyclerView(RecyclerView recyclerView) {
WrapperUtils.onAttachedToRecyclerView(mInnerAdapter, recyclerView, new WrapperUtils
.SpanSizeCallback() {
@Override
public int getSpanSize(GridLayoutManager layoutManager, GridLayoutManager
.SpanSizeLookup oldLookup, int position) {
int viewType = getItemViewType(position);
if (mHeaderViews.get(viewType) != null) {
return layoutManager.getSpanCount();
} else if (mFootViews.get(viewType) != null) {
return layoutManager.getSpanCount();
}
if (oldLookup != null)
return oldLookup.getSpanSize(position);
return 1;
}
});
}
@Override
public void onViewAttachedToWindow(RecyclerView.ViewHolder holder) {
mInnerAdapter.onViewAttachedToWindow(holder);
int position = holder.getLayoutPosition();
if (isHeaderViewPos(position) || isFooterViewPos(position)) {
WrapperUtils.setFullSpan(holder);
}
}
private boolean isHeaderViewPos(int position) {
return position < getHeadersCount();
}
private boolean isFooterViewPos(int position) {
return position >= getHeadersCount() + getRealItemCount();
}
public void addHeaderView(View view) {
mHeaderViews.put(mHeaderViews.size() + BASE_ITEM_TYPE_HEADER, view);
}
public void addFootView(View view) {
mFootViews.put(mFootViews.size() + BASE_ITEM_TYPE_FOOTER, view);
}
public int getHeadersCount() {
return mHeaderViews.size();
}
public int getFootersCount() {
return mFootViews.size();
}
}
- 接著我們來看一下我們是如何使用它的?
mAdapter = new SinglePersonAdapter(this, mDatas, R.layout.main_chat_from_msg);
mHeaderAndFooterWrapper=new HeaderAndFooterWrapper(mAdapter);
TextView t1 = new TextView(this);
t1.setPadding(10,10,10,10);
t1.setBackgroundColor(Color.GRAY);
t1.setText("Header 1");
TextView t2 = new TextView(this);
t2.setText("Header 2");
t2.setPadding(10,10,10,10);
t2.setBackgroundColor(Color.GRAY);
mHeaderAndFooterWrapper.addHeaderView(t1);
mHeaderAndFooterWrapper.addHeaderView(t2);
mRecyclerView.setAdapter(mHeaderAndFooterWrapper);
是不是很簡單,只需要簡單的幾行程式碼,就能在原有Adapter的基礎之上新增headerView或者Foot而View,具體的程式碼分析請見鴻洋大神的 部落格Android 優雅的為RecyclerView新增HeaderView和FooterView
相關推薦
最後的最後,賣一下廣告,歡迎大家關注我的微信公眾號,掃一掃下方二維碼或搜尋微訊號 stormjun,即可關注。 目前專注於 Android 開發,主要分享 Android開發相關知識和一些相關的優秀文章,包括個人總結,職場經驗等。
相關推薦
裝飾者模式及其應用
前幾天看了鴻洋大神的 Android 優雅的為RecyclerView新增HeaderView和FooterView,發現裝飾者模式 在某些情況下是設計得如此 優雅,現在總結如下: 本篇部落格主要講解一下幾個問題 什麼 是裝飾者模式 怎樣實現裝飾者模式
設計模式:裝飾者模式介紹及程式碼示例 && JDK裡關於裝飾者模式的應用
# 0、背景 來看一個專案需求:咖啡訂購專案。 咖啡種類有很多:美式、摩卡、義大利濃咖啡; 咖啡加料:牛奶、豆漿、可可。 要求是,擴充套件新的咖啡種類的時候,能夠方便維護,不同種類的咖啡需要快速**計算多少錢**,客戶單點咖啡,也可以咖啡+料。 ### 最差方案 直接想,就是一個咖啡基類,然
System.Web.Abstractions中的裝飾者模式,及其在Asp.net Mvc中的應用
Wrapper模式的實現 作為.net framework 3.5 sp1 新新增的一個程式集,System.Web.Abstractions裡所有的類,都是Wrapper/Decorator模式的。(System.Web.Abstractions裡的類可以參見後面的附錄,System.Web.Abstra
結構型:裝飾者模式及相關應用
文章目錄 裝飾者(Decorator) 優缺點 應用場景 Java I/O中的應用 Spring中的應用 MyBatis中的應用 參考資料 裝飾者(Decorator) 在不
PHP進階5 裝飾者模式在Laravel中中介軟體的應用
不積跬步無以至千里不積小流無以成江海 裝飾者模式是在開放-關閉原則下實現動態新增或者減少功能的一種方式,類似於洋蔥,分很多層,每一層都有一定的功能,可以
RecyclerView中裝飾者模式應用
近段時間一直在加班,在趕一個專案,現在專案接近尾聲,那麼需要對過去一段時間工作內容進行復盤,總結下比較好的解決方案,積累一些經驗,我認為的學習方式,是「理論—實踐—總結—分享」,這一種很好的沉澱方式。 在之前專案中,有個需求是這樣的,要顯示書的閱讀足跡列表,具體要求是顯示最近30天閱讀情況,佈局是用列表項佈局
設計模式 | 裝飾者模式及典型應用
前言 本文的主要內容: 介紹裝飾者模式 示例 原始碼分析裝飾者模式的典型應用 Java I/O 中的裝飾者模式 spring session 中的裝飾者模式 Mybatis 快取中的裝飾者模式 總結 裝飾者模式 裝飾者模式(Decorator Patt
javaIO(1):OutputStream和FileOutputStream原始碼分析及“裝飾者模式”在IO中的應用
前言 一,IO體系 從現在起,我們將基於JDK1.8詳細介紹java.io包中的關於輸入輸出有關的類。瞭解過這個包的都知道,裡面的類繼承關係錯綜複雜,光是弄清楚這些類的關係就夠喝一壺的了。說實話,我也沒有什麼好的方法來一下子就能弄清這些類,但是如果你瞭解“裝
設計模式--裝飾者模式(在IO體系中的應用)
上一篇介紹了介面卡模式,它是將一個類的介面,轉化成客戶期望的另一個介面,介面卡讓原本介面不相容的類可以合作無間。裝飾者模式:動態的將責任附加到物件上(因為利用組合而不是繼承來實現,而組合是可以在執行時進行隨機組合的)用來擴充套件功能。若要擴充套件功能,裝飾者提供
裝飾者模式
優先 方式 由於 排列組合 tps 接收 class 巧克力 不同 轉載請註明出處!!。http://blog.csdn.net/zhonghuan1992 全部配套代碼均在github上:https://github.com/ZHONGHuanGit
Java設計模式の裝飾者模式
解決 over 裝飾者模式 pack img 應該 ora 我們 lan 目錄 一、問題引入 二、設計原則 三、用裝飾者模式解決問題 四、裝飾者模式的特點 五、裝飾者模式的定義 六、裝飾者模式的實現 七、java.io包內的裝飾者模式
設計模式之裝飾者模式
一點 ron 測試類 實現類 stub generated class void nbsp 一.裝飾者模式特點:1.裝飾者和被裝飾者對象有相同的超類2.可以用一個或多個裝飾者包裝一個對象3.由於裝飾者和被裝飾者具有相同超類,所以任何需要被包裝對象的場合,可以用裝飾過的對象代
過濾器 & 裝飾者模式
自動 設計模式 加載 null type nbsp list 正文 多個 一.過濾器概述 ------------------------------------------------ 1.1.什麽是過濾器? Servlet技術規範中, 定義了S
觀察者模式實際應用:監聽線程,意外退出線程後自動重啟
lee text 實時 之間 最終 ren tap instance and 摘要: 觀察者模式,定義對象之間的一種一對多的依賴關系,當對象的狀態發生改變時,所有依賴於它的對象都得到通知並且被自動更新。觀察者模式在JDK中有現成的實現,java.util.Obsera
7,裝飾者模式(Decorator Pattern)動態的給一個對象添加一些額外的職責。就增加功能來說,此模式比生成子類更為靈活。繼承關系的一個替換方案。
做到 活性 splay .com 重新 裝飾 run play 情況 裝飾( Decorator )模式又叫做包裝模式。通過一種對客戶端透明的方式來擴展對象的功能,是繼承關系的一個替換方案。 裝飾模式就是把要添加的附加功能分別放在單獨的類中,並讓這個
設計模式(三)裝飾者模式Decorator
不知道 operation 總結 界面 都是 per @override stat override 裝飾者模式針對的問題是:對一個結構已經確定的類,在不改變該類的結構的情況下,動態增加一些功能。 一般來說,都是對一些已經寫好的架構增加自己的功能,或者應對多種情況,
09.設計模式_裝飾者模式
9.png 組件 復雜 2-2 就會 蘋果手機 apple pat 轉載 轉載自 http://www.cnblogs.com/zhili/p/DecoratorPattern.html 一、引言 在軟件開發中,我們經常想要對一類對象添加不同的功能,例如要給手機添加貼膜
【設計模式】裝飾者模式-明月裝飾了你的窗子
return rgs light 刪除 clas pan net public 不改變 裝飾者模式 使用裝飾者模式,可以動態的給一個對象添加一些額外的職責。這適用於,我們只希望給某個對象而不是整個類添加一些功能的場景。通過使用含有某個特定功能的類來“包裹”原始的類,提
裝飾者模式的魅力
app lin err space system override using public sin 1 using System; 2 3 namespace ConsoleApplication2 4 { 5 class Program
headfirst設計模式(3)—裝飾者模式
其中 拖延 穩定 放棄 等等 logs headfirst 自己的 定義 序 好久沒寫設計模式了,自從寫了兩篇之後,就放棄治療了,主要還是工作太忙了啊(借口,都是借口),過完年以後一直填坑,填了好幾個月,總算是穩定下來了,可以打打醬油了。 為什麽又重新開始寫設計模式呢?學習