设计模式学习笔记 - 装饰设计模式

318 阅读2分钟

装饰设计模式,不是用继承的方式,来扩展一个对象的功能。最典型的例子是java的输入输出流,和listView的添加头部和尾部的功能。

例子 PrintA仅有一个print方法,而且是能单一的输出str,那么要扩展PrintA类。

public class PrintA {
    private String str = "-----------";

    public String getStr() {
        return str;
    }

    void print() {
        System.out.println(str);
    }

}
public class PrintB {
    private PrintA mA;

    public PrintB(PrintA mA) {
        this.mA = mA;
    }

    void print() {
        mA.print();
    }

    void printMore() {

        String s = mA.getStr() + "*******";

        System.out.println(s);

    }
}

PrintA a = new PrintA();
PrintB b = new PrintB(a);
//a.print();
b.printMore();

源码中的装饰设计模式

listView控件,默认是有addHeaderView 和 addfooterview的功能的。其实是对ListAdapter进行了额外的扩展。

HeaderViewListAdapter是对listAdapter的扩展类。

public class HeaderViewListAdapter implements WrapperListAdapter, Filterable {
    private final ListAdapter mAdapter; // 最原始的Adapter
    ArrayList<ListView.FixedViewInfo> mHeaderViewInfos; // 添加头部和尾部的view
    ArrayList<ListView.FixedViewInfo> mFooterViewInfos;

    static final ArrayList<ListView.FixedViewInfo> EMPTY_INFO_LIST = new ArrayList<ListView.FixedViewInfo>();
    boolean mAreAllFixedViewsSelectable;
    private final boolean mIsFilterable;
    // 构造方法中进行初始化,装饰设计模式,只接受在构造中传递来需要扩展的对象。
    public HeaderViewListAdapter(ArrayList<ListView.FixedViewInfo> headerViewInfos,
                                 ArrayList<ListView.FixedViewInfo> footerViewInfos,
                                 ListAdapter adapter) {
        mAdapter = adapter;
        mIsFilterable = adapter instanceof Filterable;

        if (headerViewInfos == null) {
            mHeaderViewInfos = EMPTY_INFO_LIST;
        } else {
            mHeaderViewInfos = headerViewInfos;
        }

        if (footerViewInfos == null) {
            mFooterViewInfos = EMPTY_INFO_LIST;
        } else {
            mFooterViewInfos = footerViewInfos;
        }

        mAreAllFixedViewsSelectable = areAllListInfosSelectable(mHeaderViewInfos) && areAllListInfosSelectable(mFooterViewInfos);
    }
// 返回对应的头部个数。
    public int getHeadersCount() {
        return mHeaderViewInfos.size();
    }

    public int getFootersCount() {
        return mFooterViewInfos.size();
    }
 
// 删除头部view
    public boolean removeHeader(View v) {
        for (int i = 0; i < mHeaderViewInfos.size(); i++) {
            ListView.FixedViewInfo info = mHeaderViewInfos.get(i);
            if (info.view == v) {
                mHeaderViewInfos.remove(i);

                mAreAllFixedViewsSelectable =
                        areAllListInfosSelectable(mHeaderViewInfos)
                        && areAllListInfosSelectable(mFooterViewInfos);

                return true;
            }
        }

        return false;
    }

    public boolean removeFooter(View v) {
        for (int i = 0; i < mFooterViewInfos.size(); i++) {
            ListView.FixedViewInfo info = mFooterViewInfos.get(i);
            if (info.view == v) {
                mFooterViewInfos.remove(i);

                mAreAllFixedViewsSelectable =
                        areAllListInfosSelectable(mHeaderViewInfos)
                        && areAllListInfosSelectable(mFooterViewInfos);

                return true;
            }
        }

        return false;
    }
// 返回总个数,footerview + headerview + content个数
    public int getCount() {
        if (mAdapter != null) {
            return getFootersCount() + getHeadersCount() + mAdapter.getCount();
        } else {
            return getFootersCount() + getHeadersCount();
        }
    }
// 根据当前的position 判断是否小于header的个数,如果是则返回header中的view

// 如果 大于 headerview的个数,小于内容item的个数则调用原始的adapter的getView方法,返回view

// 否则返回 尾部的view
    public View getView(int position, View convertView, ViewGroup parent) {
        int numHeaders = getHeadersCount();
        if (position < numHeaders) {
            return mHeaderViewInfos.get(position).view;
        }

        final int adjPosition = position - numHeaders;
        int adapterCount = 0;
        if (mAdapter != null) {
            adapterCount = mAdapter.getCount();
            if (adjPosition < adapterCount) {
                return mAdapter.getView(adjPosition, convertView, parent);
            }
        }

        // Footer (off-limits positions will throw an IndexOutOfBoundsException)
        return mFooterViewInfos.get(adjPosition - adapterCount).view;
    }
}