设计模式专栏
1、定义以及UML建模图
装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构。这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装。
2、使用场景
这种模式创建了一个装饰类,用来包装原有的类,并在保持类方法签名完整性的前提下,提供了额外的功能。
我们通过下面的实例来演示装饰器模式的用法。其中,我们将一部手机安装不同的应用软件,从而实现不同的功能,因为我不是厂商,所以出厂的时候不能进行定制,所以,这里以演示给手机装软件,实现不同的功能。
3、核心类
抽象组件,MobilePhone
可以是一个接口或者抽象类,其充当的是被装饰的原始对象,组件具体实现类 ,NewPhone
该类是抽象组件的具体实现,也是我们装饰的具体的对象抽象装饰者,Decorator
其承担的责任就是为了装饰我们的组件对象,其内部一定要有一个指向组件对象的引用,在大多数情况下,该类为抽象类,根据具体的装饰者装饰逻辑实现不同的具体子类,如果是一个,当然可以成具体的被装饰对象。
- 装饰者具体实现类, InstallApkDecorator
只是对抽象装饰者做出具体的实现。
- 手机抽象类
public abstract class MobilePhone {
/**
* 打电话功能
*/
abstract void call();
}
- 出厂手机
public class NewPhone extends MobilePhone{
@Override
void call() {
System.out.println("具有打电话功能!");
}
}
- 应用商店(装饰器抽象类)
public abstract class Decorator extends MobilePhone {
private MobilePhone mobilePhone;
public Decorator(MobilePhone mobilePhone) {
this.mobilePhone = mobilePhone;
}
@Override
void call() {
mobilePhone.call();
}
}
- 具体装饰类(小米应用商店,或者app store)
public class InstallApkDecorator extends Decorator {
public InstallApkDecorator(MobilePhone mobilePhone) {
super(mobilePhone);
}
@Override
void call() {
super.call();
installApk("抖音!");
}
private void installApk(String s) {
System.out.println("具有了抖音APP功能!");
}
}
- 具体使用:
public class Client {
public static void main(String[] args){
MobilePhone mobilePhone=new NewPhone();
mobilePhone.call();
System.out.println("装饰器装饰,让有浏览短视频功能!");
Decorator zsq=new InstallApkDecorator(mobilePhone);
zsq.call();
}
}
4、简单扩展
再来看看再Android中的巧妙的使用,如果你是一个Android开发者,原生的RecycleView的adapter 是不支持直接添加头view,为了在项目中更好的使用,可以使用装饰器模式,将原生的adapter保持不动,增加addHeader(View) 方法,实现类似于listview添加头部的功能,这里展示一个鸿洋大神封装的adapter装饰器,文末有详细原文。
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;
}
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();
}
}
复写核心方法
public class HeaderAndFooterWrapper<T> extends RecyclerView.Adapter<RecyclerView.ViewHolder>
{
@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();
}
}
Adapter来源原文:https://blog.csdn.net/lmj623565791/article/details/51854533