什么是装饰设计模式?
装饰器模式是一种用于代替继承的技术,无需通过继承增加子类就能扩展对象的新功能。使用对象的关联关系代替继承关系,更加灵活,同时避免类型体系的快速膨胀。
在不使用的继承的方式下,采用装饰设计模式可以扩展一个对象的功能,可以使一个对象变得越来越强大。
装饰模式(Decorator)也叫包装器模式(Wrapper)
装饰模式降低系统的耦合度,可以动态的增加或删除对象的职责,并使得需要装饰的具体构建类和具体装饰类可以独立变化,以便增加新的具体构建类和具体装饰类。
参考文章:
https://www.cnblogs.com/zhangtianq/p/6091047.html
https://blog.csdn.net/android_zyf/article/details/68343953
https://www.cnblogs.com/pecool/p/9534568.html
以普通手机和智能手机为例子来讲:
Phone类:
public interface Phone {
void call();
void sms();
}
普通手机NormalPhone类:
public class NormalPhone implements Phone {
@Override
public void call() {
System.out.println("可以打电话");
}
@Override
public void sms() {
System.out.println("可以发短信");
}
}
智能手机SmartPhone类:
public class SmartPhone implements Phone {
private NormalPhone mPhone;
SmartPhone(NormalPhone phone) {
this.mPhone = phone;
}
@Override
public void call() {
mPhone.call();
System.out.println("打电话的同时还可以发微信、看视频、玩游戏等等....");
}
@Override
public void sms() {
mPhone.sms();
}
}
Client类:
public class Client {
public static void main(String[] args) {
NormalPhone normalPhone = new NormalPhone();
normalPhone.call();
System.out.println("-----------------");
SmartPhone smartPhone = new SmartPhone(normalPhone);
smartPhone.call();
}
}
控制台输出:
可以打电话
-----------------
可以打电话
打电话的同时还可以发微信、看视频、玩游戏等等....
使用装饰设计模式实现给RecyclerView添加头部和尾部
首先要知道RecyclerView控件如何使用,可以参考下面这篇文章:
https://www.jianshu.com/p/4f9591291365
MainActivity类:
public class MainActivity extends AppCompatActivity {
private RecyclerView recyclerView;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_recyclerview);
ArrayList<String> datas = new ArrayList<>();
for (int i = 0; i < 50; i++) {
datas.add(" data " + i);
}
recyclerView = findViewById(R.id.recyclerview);
LinearLayoutManager layoutManager = new LinearLayoutManager(this);
//设置布局管理器
recyclerView.setLayoutManager(layoutManager);
//设置为垂直布局,这也是默认的
layoutManager.setOrientation(OrientationHelper.VERTICAL);
//设置Adapter
Adapter recycleAdapter = new Adapter(datas);
WrapperRecyclerAdapter adapter = new WrapperRecyclerAdapter(recycleAdapter);
recyclerView.setAdapter(adapter);
//View headerView = LayoutInflater.from(this).inflate(R.layout.header_view, null);//todo 这样写效果不对
View headerView = LayoutInflater.from(this).inflate(R.layout.header_view, recyclerView, false);
View footerView = LayoutInflater.from(this).inflate(R.layout.footer_view, recyclerView, false);
adapter.addHeaderView(headerView);
adapter.addFooterView(footerView);
//设置分隔线
//recyclerView.addItemDecoration(new DividerGridItemDecoration(this));
//设置增加或删除条目的动画
recyclerView.setItemAnimator(new DefaultItemAnimator());
}
}
Adapter类:
public class Adapter extends RecyclerView.Adapter<Adapter.ViewHolder> {
private List<String> mDatas;
public Adapter(List<String> data) {
this.mDatas = data;
}
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_recycler, parent, false);
return new ViewHolder(v);
}
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, final int position) {
Log.d("TAG", "onBindViewHolder:" + position);
holder.mTextView.setText(mDatas.get(position));
holder.mTextView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.d("TAG", "onClick :" + position);
mDatas.remove(position);
notifyDataSetChanged();
}
});
}
@Override
public int getItemCount() {
return mDatas.size();
}
static class ViewHolder extends RecyclerView.ViewHolder {
TextView mTextView;
public ViewHolder(View v) {
super(v);
mTextView = v.findViewById(R.id.tv_title);
}
}
}
WrapperRecyclerAdapter类:
public class WrapperRecyclerAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private RecyclerView.Adapter mRecyclerAdapter;//原始的Adapter,不具有添加header和footer
ArrayList<View> mHeaderViews;
ArrayList<View> mFooterViews;
public WrapperRecyclerAdapter(RecyclerView.Adapter adapter) {
this.mRecyclerAdapter = adapter;
mHeaderViews = new ArrayList<>();
mFooterViews = new ArrayList<>();
mRecyclerAdapter.registerAdapterDataObserver(new RecyclerView.AdapterDataObserver() {
@Override
public void onChanged() {
notifyDataSetChanged();
}
});
}
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int postion) {
Log.e("TAG", "onCreateViewHolder " + postion);
if (postion < mHeaderViews.size()) {
Log.e("TAG", "add header view");
View headerView = mHeaderViews.get(postion);
return createHeaderView(headerView);
}
int itemCount = mRecyclerAdapter.getItemCount();
int adjPos = postion - mHeaderViews.size();
if (adjPos < itemCount) {
Log.e("TAG", "add item view");
return mRecyclerAdapter.onCreateViewHolder(parent, mRecyclerAdapter.getItemViewType(adjPos));
}
Log.e("TAG", "add footer view");
// footerview
View footerView = mFooterViews.get(postion - itemCount - mHeaderViews.size());
return createHeaderView(footerView);
}
private RecyclerView.ViewHolder createHeaderView(View view) {
return new RecyclerView.ViewHolder(view) {
};
}
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
Log.d("TAG", "Wrapper RecyclerAdapter onBindViewHolder:" + position);
if (position < mHeaderViews.size()) {
return;
}
int adjPos = position - mHeaderViews.size();
if (adjPos < mRecyclerAdapter.getItemCount()) {
mRecyclerAdapter.onBindViewHolder(holder, adjPos);
//mRecyclerAdapter.onBindViewHolder(holder, adjPos);
} else {
Log.d("TAG", "adjPos getItemCount." + adjPos + " " + mRecyclerAdapter.getItemCount());
//fix footer view.
}
}
@Override
public int getItemViewType(int position) {
return position;
}
@Override
public int getItemCount() {
return mRecyclerAdapter.getItemCount() + mHeaderViews.size() + mFooterViews.size();
}
// 添加头部
public void addHeaderView(View v) {
if (!mHeaderViews.contains(v)) {
mHeaderViews.add(v);
notifyDataSetChanged();
}
}
public void removeHeaderView(View v) {
if (mHeaderViews.contains(v)) {
mHeaderViews.remove(v);
notifyDataSetChanged();
}
}
// 添加尾部
public void addFooterView(View v) {
if (!mFooterViews.contains(v)) {
mFooterViews.add(v);
notifyDataSetChanged();
}
}
public void removeFooterView(View v) {
if (mFooterViews.contains(v)) {
mFooterViews.remove(v);
notifyDataSetChanged();
}
}
}
为了像ListView一样可以直接调用addHeaderView,我们继承RecyclerView写一个WrapperRecyclerView:
public class WrapperRecyclerView extends RecyclerView {
private WrapperRecyclerAdapter mWrapperRecyclerAdapter;
public WrapperRecyclerView(Context context) {
super(context);
}
public WrapperRecyclerView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
public WrapperRecyclerView(Context context, @Nullable AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
public void setAdapter(Adapter adapter) {
mWrapperRecyclerAdapter = new WrapperRecyclerAdapter(adapter);
super.setAdapter(mWrapperRecyclerAdapter);
}
public void addHeaderView(View view) {
if (mWrapperRecyclerAdapter != null) {
mWrapperRecyclerAdapter.addHeaderView(view);
}
}
public void removeHeaderView(View view) {
if (mWrapperRecyclerAdapter != null) {
mWrapperRecyclerAdapter.removeHeaderView(view);
}
}
public void addFooterView(View view) {
if (mWrapperRecyclerAdapter != null) {
mWrapperRecyclerAdapter.addFooterView(view);
}
}
public void removeFooterView(View view) {
if (mWrapperRecyclerAdapter != null) {
mWrapperRecyclerAdapter.removeFooterView(view);
}
}
}
MainActivity2类代码:
public class MainActivity2 extends AppCompatActivity {
private WrapperRecyclerView recyclerView;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_recyclerview2);
ArrayList<String> datas = new ArrayList<>();
for (int i = 0; i < 15; i++) {
datas.add(" WrapperRecyclerView data " + i);
}
recyclerView = findViewById(R.id.recyclerview);
LinearLayoutManager layoutManager = new LinearLayoutManager(this);
//设置布局管理器
recyclerView.setLayoutManager(layoutManager);
//设置为垂直布局,这也是默认的
layoutManager.setOrientation(OrientationHelper.VERTICAL);
//设置Adapter
Adapter recycleAdapter = new Adapter(datas);
//WrapperRecyclerAdapter adapter = new WrapperRecyclerAdapter(recycleAdapter);
recyclerView.setAdapter(recycleAdapter);
//View headerView = LayoutInflater.from(this).inflate(R.layout.header_view, null);//todo 这样写效果不对
View headerView = LayoutInflater.from(this).inflate(R.layout.header_view, recyclerView, false);
View footerView = LayoutInflater.from(this).inflate(R.layout.footer_view, recyclerView, false);
recyclerView.addHeaderView(headerView);
recyclerView.addFooterView(footerView);
//设置分隔线
//recyclerView.addItemDecoration(new DividerGridItemDecoration(this));
//设置增加或删除条目的动画
recyclerView.setItemAnimator(new DefaultItemAnimator());
}
}
布局文件:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.ivyzh.designpatterndemo.d1_singleton_pattern.MainActivity">
<com.ivyzh.designpatterndemo.d4_decorator_pattern.simple2.WrapperRecyclerView
android:id="@+id/recyclerview"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</LinearLayout>
说明:上面的例子有个bug,就是点击item删除的时候,会有复用bug,如下图:
删除条目的Bug.png
后面会再排查。
END.