什么是裝飾設(shè)計(jì)模式姻政?
裝飾器模式是一種用于代替繼承的技術(shù)呆抑,無需通過繼承增加子類就能擴(kuò)展對象的新功能。使用對象的關(guān)聯(lián)關(guān)系代替繼承關(guān)系汁展,更加靈活鹊碍,同時避免類型體系的快速膨脹。
在不使用的繼承的方式下食绿,采用裝飾設(shè)計(jì)模式可以擴(kuò)展一個對象的功能侈咕,可以使一個對象變得越來越強(qiáng)大。
裝飾模式(Decorator)也叫包裝器模式(Wrapper)
裝飾模式降低系統(tǒng)的耦合度器紧,可以動態(tài)的增加或刪除對象的職責(zé)耀销,并使得需要裝飾的具體構(gòu)建類和具體裝飾類可以獨(dú)立變化,以便增加新的具體構(gòu)建類和具體裝飾類铲汪。
參考文章:
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
以普通手機(jī)和智能手機(jī)為例子來講:
Phone類:
public interface Phone {
void call();
void sms();
}
普通手機(jī)NormalPhone類:
public class NormalPhone implements Phone {
@Override
public void call() {
System.out.println("可以打電話");
}
@Override
public void sms() {
System.out.println("可以發(fā)短信");
}
}
智能手機(jī)SmartPhone類:
public class SmartPhone implements Phone {
private NormalPhone mPhone;
SmartPhone(NormalPhone phone) {
this.mPhone = phone;
}
@Override
public void call() {
mPhone.call();
System.out.println("打電話的同時還可以發(fā)微信熊尉、看視頻、玩游戲等等....");
}
@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();
}
}
控制臺輸出:
可以打電話
-----------------
可以打電話
打電話的同時還可以發(fā)微信掌腰、看視頻狰住、玩游戲等等....
使用裝飾設(shè)計(jì)模式實(shí)現(xiàn)給RecyclerView添加頭部和尾部
首先要知道RecyclerView控件如何使用,可以參考下面這篇文章:
http://www.reibang.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);
//設(shè)置布局管理器
recyclerView.setLayoutManager(layoutManager);
//設(shè)置為垂直布局齿梁,這也是默認(rèn)的
layoutManager.setOrientation(OrientationHelper.VERTICAL);
//設(shè)置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);
//設(shè)置分隔線
//recyclerView.addItemDecoration(new DividerGridItemDecoration(this));
//設(shè)置增加或刪除條目的動畫
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一樣可以直接調(diào)用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);
//設(shè)置布局管理器
recyclerView.setLayoutManager(layoutManager);
//設(shè)置為垂直布局,這也是默認(rèn)的
layoutManager.setOrientation(OrientationHelper.VERTICAL);
//設(shè)置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);
//設(shè)置分隔線
//recyclerView.addItemDecoration(new DividerGridItemDecoration(this));
//設(shè)置增加或刪除條目的動畫
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创南,就是點(diǎn)擊item刪除的時候伦忠,會有復(fù)用bug,如下圖:
后面會再排查扰藕。
END.