一、前言
我遇到什么问题要使用装饰者设计模式?
- 看源码的时候:我们发现明明ui有一个功能,但是在这个ui类找不到,后来发现,这个ui被当做一个参数传递到了一个类里面,后来才在这个类里找到了这个功能。突然醍醐灌顶,这不就是装饰者设计模式吗?
- 写代码的时候:如果我们想给一个功能增加新的东西,可以借助装饰者设计模式来装饰,如果不需要则可以把这个方法去掉,非常的简洁和优雅,并且新增的功能放到了另外一个类里面,也不臃肿。
二、装饰者设计模式是什么?
装饰者模式是一种动态扩展对象功能的结构型设计模式。它通过包裹(装饰)原有对象的方式,在不修改其代码的前提下,灵活添加新功能,且支持多层嵌套装饰。 它强调对功能的“增量式”扩展而非继承式的重构。
三、装饰者设计模式解决的问题
● 避免类爆炸:继承会导致大量子类,处理继承带来的问题。 ● 动态扩展:在运行时添加或撤销功能,无需修改原有代码。如果不使用,可能我们是直接在类里面添加功能,删除的时候就比较麻烦,并且臃肿。 ● 符合开闭原则:扩展开放,修改关闭。
四、看具体的例子:给textview添加红色边框
一、我们看一个复杂的场景,给EditText添加红色背景
// 1. 组件接口(View的抽象)
public interface ViewComponent {
void display();
}
// 2. 具体组件:EditText
public class EditTextComponent implements ViewComponent {
private EditText editText;
public EditTextComponent(EditText editText) {
this.editText = editText;
}
@Override
public void display() {
editText.setVisibility(View.VISIBLE);
}
}
// 3. 装饰者基类
public abstract class ViewDecorator implements ViewComponent {
protected ViewComponent component;
public ViewDecorator(ViewComponent component) {
this.component = component;
}
@Override
public void display() {
component.display();
}
}
// 4. 具体装饰者:红色背景
public class RedBackgroundDecorator extends ViewDecorator {
public RedBackgroundDecorator(ViewComponent component) {
super(component);
}
@Override
public void display() {
setRedBackground();
super.display();
}
private void setRedBackground() {
if (component instanceof EditTextComponent) {
EditText editText = ((EditTextComponent) component).getEditText();
editText.setBackgroundColor(Color.RED);
}
}
}
// 5.使用示例
EditText editText = findViewById(R.id.editText);
ViewComponent component = new EditTextComponent(editText);
component = new RedBackgroundDecorator(component); // 动态添加红色背景
component.display();
二、给EditText添加红色背景
如果不需要严格遵循组件接口,可直接操作EditText, 这种方式更简洁,但牺牲了模式的标准结构,适合简单场景。
public class RedBackgroundDecorator {
public static EditText decorate(EditText editText) {
editText.setBackgroundColor(Color.RED);
return editText;
}
}
// 使用
EditText editText = new EditText(context);
RedBackgroundDecorator.decorate(editText);
三、一些源码里面用到装饰者设计模式:对RecyclerView进行装饰
//传递RecyclerView进来进行封装
public static IOverScrollDecor setUpOverScroll(RecyclerView recyclerView, int orientation) {
switch (orientation) {
case 0:
return new VerticalOverScrollBounceEffectDecorator(new RecyclerViewOverScrollDecorAdapter(recyclerView));
case 1:
return new HorizontalOverScrollBounceEffectDecorator(new RecyclerViewOverScrollDecorAdapter(recyclerView));
default:
throw new IllegalArgumentException("orientation");
}
}
public RecyclerViewOverScrollDecorAdapter(RecyclerView recyclerView) {
this.mIsItemTouchInEffect = false;
this.mRecyclerView = recyclerView;
RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager();
if (!(layoutManager instanceof LinearLayoutManager) && !(layoutManager instanceof StaggeredGridLayoutManager)) {
throw new IllegalArgumentException("Recycler views with custom layout managers are not supported by this adapter out of the box.Try implementing and providing an explicit 'impl' parameter to the other c'tors, or otherwise create a custom adapter subclass of your own.");
} else {
int orientation = layoutManager instanceof LinearLayoutManager ? ((LinearLayoutManager)layoutManager).getOrientation() : ((StaggeredGridLayoutManager)layoutManager).getOrientation();
if (orientation == 0) {
this.mImpl = new ImplHorizLayout();
} else {
this.mImpl = new ImplVerticalLayout();
}
}
}