前言
设计模式伴随着我们写代码的一生,总是看了又忘,忘了又看,然后依次循环。在这里用实例或者工作心得记录下设计模式的使用,23种太多,本篇只记录用过的模式,不作过多扩展,后续会针对各个设计模式详细分析。
设计模式分类
创建型模式
对象的创建会消耗掉系统的很多资源,所以单独对对象的创建进行研究,从而能够高效地创建对象就是创建型模式要探讨的问题。
结构型模式
在解决了对象的创建问题之后,对象的组成以及对象之间的依赖关系就成了开发人员关注的焦点,因为如何设计对象的结构、继承和依赖关系会影响到后续程序的维护性、代码的健壮性、耦合性等,对象结构的设计很容易体现出设计人员水平的高低。
行为型模式
在对象的结构和对象的创建问题都解决了之后,就剩下对象的行为问题了,如果对象的行为设计的好,那么对象的行为就会更清晰,它们之间的协作效率就会提高。
Android源码中设计模式
1.单例
android.app.AppComponentFactory中通过class.newInstance创建,保证一个app只有一个Application实例。
PS:注意class.newInstance()被调用前必须保证类已经被ClassLoader加载,其实本篇不想作这些扩展说明,还是说一下吧。
public class AppComponentFactory {
/**
* Allows application to override the creation of the application object. This can be used to
* perform things such as dependency injection or class loader changes to these
* classes.
* <p>
* This method is only intended to provide a hook for instantiation. It does not provide
* earlier access to the Application object. The returned object will not be initialized
* as a Context yet and should not be used to interact with other android APIs.
*
* @param cl The default classloader to use for instantiation.
* @param className The class to be instantiated.
*/
public @NonNull Application instantiateApplication(@NonNull ClassLoader cl,
@NonNull String className)
throws InstantiationException, IllegalAccessException, ClassNotFoundException {
return (Application) cl.loadClass(className).newInstance();
}
}
2.建造者模式
使用多个简单的对象一步一步构建成一个复杂的对象,它提供了一种创建对象的方式,比如AlertDialog,其中setTitle方法返回this,是建造者典型的特征。
public Builder setTitle(CharSequence title) {
P.mTitle = title;
return this;
}
//弹框
new AlertDialog.Builder(getActivity())
.setTitle("标题")
.setMessage(msg)
.setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
}
})
.setPositiveButton("确定", null)
.setCancelable(false)
.show();
3.原型模式
将一个对象进行拷贝,创建重复的对象,一般都是使用clone()方法,对象深浅拷贝这里暂不探究。Android中Intent中提供了clone()方法,有时候Intent很多参数相同,同时跳转2个或多个页面时,Intent加入相同参数后就可以clone()出另外一个Intent,分别用于差异化参数跳转。
public class Intent implements Parcelable, Cloneable {
@Override
public Object clone() {
return new Intent(this);
}
}
//测试伪代码
private void test() {
Intent intent = new Intent();
intent.putExtra("param_1", "1");
intent.putExtra("param_2", "2");
startActivity(intent);
Intent intent2 = (Intent)intent.clone();
intent2.putExtra("param_3", "3");
startActivity(intent2);
}
4.工厂方法模式
创建对象时不会对调用者暴露创建逻辑,通过一个共同的接口来指向新创建的对象。android中通过getSystemService()方法传入不同参数获取对应xxxManager。
//WindowManager
WindowManager windowManager = (WindowManager) getActivity()
.getSystemService(Service.WINDOW_SERVICE);
//SearchManager
SearchManager searchManager = (SearchManager) getActivity()
.getSystemService(Service.SEARCH_SERVICE);
4.抽象工厂模式
多个接口分别负责创建多个相关对象的工厂,调用时根据名称获取一个工厂,获取某个工厂后,后续操作同工厂方法模式,伪代码如下。
A工厂 = 总厂("A工厂");
A包 = A工厂.("A包");
B工厂 = 总厂("B工厂");
B包 = B工厂.("B包");
5.简单工厂模式
无接口,直接通过静态方法提供功能,android中比如BitmapFactory。
BitmapFactory.decodeFile();
BitmapFactory.decodeResource();
6.适配器模式
两个不兼容的接口之间的桥梁。android中平时用的最多是RecyclerView.Adapter,Adapter是Item布局、列表数据间的桥梁,通过不同的Adapter ,我们能够实现不同的布局。
public abstract static class Adapter<VH extends ViewHolder> {
...
public abstract VH onCreateViewHolder(@NonNull ViewGroup parent, int viewType);
public abstract void onBindViewHolder(@NonNull VH holder, int position);
...
}
7.观察者模式
定义对象间的一种一个对多的依赖关系,当一个对象的状态发送改变时,所以依赖于它的对象都得到通知并被自动更新。android中当RecyclerView列表数据变更时,需要调用Adapter.notifyDataSetChanged()通知列表刷新。
RecyclerView.setAdapterInternal()方法中可以清楚看到registerAdapterDataObserver /?unregisterAdapterDataObserver 方法用来订阅与取消订阅。
//观察者
private final RecyclerViewDataObserver mObserver = new RecyclerViewDataObserver();
//RecyclerViewDataObserver
private class RecyclerViewDataObserver extends AdapterDataObserver {
RecyclerViewDataObserver() {
}
@Override
public void onChanged() {
assertNotInLayoutOrScroll(null);
mState.mStructureChanged = true;
processDataSetCompletelyChanged(true);
if (!mAdapterHelper.hasPendingUpdates()) {
//刷新页面
requestLayout();
}
}
}
//Adapter
public abstract static class Adapter<VH extends ViewHolder> {
//被观察者
private final AdapterDataObservable mObservable = new AdapterDataObservable();
//注册观察者
public void registerAdapterDataObserver(@NonNull AdapterDataObserver observer) {
mObservable.registerObserver(observer);
}
//取消注册观察者
public void unregisterAdapterDataObserver(@NonNull AdapterDataObserver observer) {
mObservable.unregisterObserver(observer);
}
//notifyDataSetChanged
public final void notifyDataSetChanged() {
mObservable.notifyChanged();
}
}
//setAdapterInternal
private void setAdapterInternal(@Nullable Adapter adapter, boolean compatibleWithPrevious,
boolean removeAndRecycleViews) {
//...
final Adapter oldAdapter = mAdapter;
mAdapter = adapter;
if (adapter != null) {
//被观察者注册观察者
adapter.registerAdapterDataObserver(mObserver);
adapter.onAttachedToRecyclerView(this);
}
//...
}
//被观察者对象
static class AdapterDataObservable extends Observable<AdapterDataObserver> {
public boolean hasObservers() {
return !mObservers.isEmpty();
}
public void notifyChanged() {
for (int i = mObservers.size() - 1; i >= 0; i--) {
mObservers.get(i).onChanged();
}
}
}
8.策略模式
一个类的行为或其算法可以在运行时更改,定义一系列的算法,把每一个算法封装起来,并且使它们可相互替换。策略模式模式使得算法可独立于使用它的客户而独立变化。android中如RecyclerView.setLayoutManager(),可以是线性、网格、交错,还有图片缓存策略如磁盘缓存、内存缓存等。
RecyclerView.setLayoutManager(new LinearLayoutManager());
RecyclerView.setLayoutManager(new GridLayoutManager());
RecyclerView.setLayoutManager(new StaggeredGridLayoutManager());
9.装饰模式
动态地给一个对象添加一些额外的职责。就增加功能来说,装饰模式相比生成子类更为灵。android中ContextWrapper 就是具体的装饰角色,Context 类在这里就充当了抽象组件的角色,ContextImpl 类则是具体的组件,通过扩展ContextWrapper 增加不同的功能,就形成了Activity 、Service 等子类。
public class ContextWrapper extends Context {//Context包装类
Context mBase;//Context是一个abstract修饰的抽象类
public ContextWrapper(Context base) {//这里实际上是Context的实现类ContextImpl
mBase = base;
}
@Override
public void startActivity(Intent intent) {
mBase.startActivity(intent);//调用ContextImpl的startActivity()方法
}
//其他代码略
}
10.迭代器模式
顺序访问集合对象的元素,不需要知道集合对象的内部细节。常用的Map、List等都支持迭代器模式遍历,Android中使用数据库查询时返回的Cursor游标对象,也是使用了迭代器模式来实现。
Cursor cursor = database.rawQuery("sql", new String[]{"name"});
if (cursor != null) {
while (cursor.moveToNext()) {
cursor.getInt(0);
cursor.getString(1);
}
}
11.责任链模式
一个行为或者操作沿着一条“链”传递,直到该“链”上的某个处理者处理或者消费它为止。android中最直接的体现就是触摸事件分发机制,比如一个Activity,页面包含一个ViewGroup,ViewGroup中包含一个View,页面中元素无任何点击、触摸事件,分别重写他们的dispatchTouchEvent、onInterceptTouchEvent、onTouchEvent,我们触摸View,日志输出如下,事件一路传递下来,又一路回溯回去,最终事件被Activity的onTouchEvent消费了后续的UP事件。
E/Activity: =====dispatchTouchEvent=====ACTION_DOWN
E/ViewGroup: dispatchTouchEvent: ======ACTION_DOWN
onInterceptTouchEvent: ======ACTION_DOWN
E/View: dispatchTouchEvent: ======ACTION_DOWN
onTouchEvent: ======ACTION_DOWN
E/ViewGroup: onTouchEvent: ======ACTION_DOWN
E/Activity: =====onTouchEvent=====ACTION_DOWN
=====dispatchTouchEvent=====ACTION_UP
=====onTouchEvent=====ACTION_UP
在View的onTouchEvent返回true日志如下:
E/Activity: =====dispatchTouchEvent=====ACTION_DOWN
E/ViewGroup: dispatchTouchEvent: ======ACTION_DOWN
onInterceptTouchEvent: ======ACTION_DOWN
E/View: dispatchTouchEvent: ======ACTION_DOWN
onTouchEvent: ======ACTION_DOWN
E/MainActivity: =====dispatchTouchEvent=====ACTION_UP
E/ViewGroup: dispatchTouchEvent: ======ACTION_UP
onInterceptTouchEvent: ======ACTION_UP
E/View: dispatchTouchEvent: ======ACTION_UP
onTouchEvent: ======ACTION_UP
12.代理模式
为其他对象提供一种代理以控制这个对象的访问。android中的Retrofit2框架就是通过动态代理生成请求对象,动态代理本质上是生成大量样板代码 的过程,相比于静态代理,动态代理可以减少编写代理类(比如XXXImpl)的工作量。
public <T> T create(final Class<T> service) {
Utils.validateServiceInterface(service);
if (validateEagerly) {
eagerlyValidateMethods(service);
}
return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service },
new InvocationHandler() {
private final Platform platform = Platform.get();
private final Object[] emptyArgs = new Object[0];
@Override public @Nullable Object invoke(Object proxy, Method method,
@Nullable Object[] args) throws Throwable {
// If the method is a method from Object then defer to normal invocation.
if (method.getDeclaringClass() == Object.class) {
return method.invoke(this, args);
}
if (platform.isDefaultMethod(method)) {
return platform.invokeDefaultMethod(method, service, proxy, args);
}
return loadServiceMethod(method).invoke(args != null ? args : emptyArgs);
}
});
}
13.外观模式
外观模式隐藏系统的复杂性,并向客户端提供了一个客户端可以访问系统的接口。这
在android中,Context就用了外观模式,Context可以打开Activity,可打开Service,广播等等。
14.享元模式
使用共享对象可有效地支持大量的细粒度的对象,享元模式尝试重用现有的同类对象,如果未找到匹配的对象,则创建新对象。在android中,获取Message,可以通过Message.obtain()去获取Message,源码可以看到先去池中找,有则用池中的Message,无则新创建。
public static Message obtain() {
synchronized (sPoolSync) {
if (sPool != null) {
Message m = sPool;
sPool = m.next;
m.next = null;
m.flags = 0; // clear in-use flag
sPoolSize--;
return m;
}
}
return new Message();
}
15.桥接模式
用一个作为桥接的接口,使得实体类的功能独立于接口实现类。比如一个USB线左边可以插不同的手机,右边可以插不同的电源。
public abstract class Shape {
//实现了一些方法
//桥接方法,子类自行实现画什么内容
public abstract void draw();
}
|