JS技术

《Android源码设计模式解析》读书笔记——Android中你应该知道的设计模式 - 赵凯强 - 博客频道 - CSD

字号+ 作者:H5之家 来源:H5之家 2015-12-14 16:21 我要评论( )

Android代码混淆,如何过滤掉反射的R文件及第三方包?解决方案:在Proguard.cfg方件中添加以下设定:过滤R文件的混淆:-keep class **.R$* { *;}过滤第三方包的

断断续续的,《Android源码设计模式解析》也看了一遍,书中提到了很多的设计模式,但是有部分在开发中见到的几率很小,所以掌握不了也没有太大影响。

我觉得这本书的最大价值有两点,一个是从设计模式的角度去理解Android源码,结合着日常开发中的常用类,对设计模式的理解会更加的深刻;另外一个好处就是了解常用模式,再看其他人写的代码的时候,更容易理解代码思路。下面是我的读书笔记和一些思考,设计模式只整理我认为重要的部分。

建造者模式

建造者模式最明显的标志就是Build类,而在Android中最常用的就是Dialog的构建,Notification的构建也是标准的建造者模式。

建造者模式很好理解,如果一个类的构造需要很多参数,而且这些参数并不都是必须的,那么这种情况下就比较适合Builder。

比如构建一个AlertDialog,标题、内容、取消按钮、确定按钮、中立按钮,你可能只需要单独设置几个属性即可;另外在我的OkHttpPlus项目中,构造一个Http请求也是这样的,有可能你只需要设置URL,有可能需要添加请求参数、Http Header等,这个时候建造者模式也是比较合适的。

单例模式

单例在Android开发中经常用到,但是表现形式可能不太一样。

以ActivityManager等系统服务来说,是通过静态代码块的形式实现单例,在首次加载类文件时,生成单例对象,然后保存在Cache中,之后的使用都是直接从Cache中获取。

{ static { registerService(ACTIVITY_SERVICE, new ServiceFetcher() { public Object createService(ContextImpl ctx) { return new ActivityManager(ctx.getOuterContext(), ctx.mMainThread.getHandler()); }}); } }

当然,还有更加明显的例子,比如AccessibilityManager内部自己也保证了单例,使用getInstance获取单例对象。

public static AccessibilityManager getInstance(Context context) { synchronized (sInstanceSync) { if (sInstance == null) { ...... IBinder iBinder = ServiceManager.getService(Context.ACCESSIBILITY_SERVICE); IAccessibilityManager service = iBinder == null ? null : IAccessibilityManager.Stub.asInterface(iBinder); sInstance = new AccessibilityManager(context, service, userId); } } return sInstance; }

除此之外,还有一些伪单例,比如Application,默认情况下在一个进程中只存在一个实例,但是Application不能算是单例,因为它的构造方法未私有,你可以生成多个Application实例,但是没有用,你没有通过attach()绑定相关信息,没有上下文环境。

public Application() { super(null); }

单例的使用场景也很简单,就是一个App只需要存在一个类实例的情况,或者是类的初始化操作比较耗费资源的情况。在很多开源框架中,我们只需要一个对象即可完成工作,比如各种网络框架和图片加载库。

除此之外,因为单例的实现方式很多,比如懒汉式、饿汉式、静态内部类、双重锁检查、枚举等方式,所以要清楚每种实现方式的主要特点和使用场景。

原型模式

原型模式在开发中使用的并不多,但是在源码中却有所体现。

书中以Intent介绍了原型模式,是通过实现Cloneable接口来做的

, Object clone() { return new Intent(this); } }

其实这样来看的话,原型模式也比较好理解,就是你想更快的获取到一个相同属性的对象,那么就可以使用原型模式,比如这里就获取到了一个Intent对象,Intent里面的属性与被clone的相同,但是两者并无关联,可以单独使用。

除了实现Cloneable接口,你完全可以自己定义一个方法,来获取一个对象。我这里以PhoneLayoutInflater为例子介绍。

PhoneLayoutInflater是LayoutInflater的子类,如果我们在Activity中获取LayoutInflate的话,是通过下面方法

@Override public Object getSystemService(String name) { if (LAYOUT_INFLATER_SERVICE.equals(name)) { if (mInflater == null) { mInflater = LayoutInflater.from(getBaseContext()).cloneInContext(this); } return mInflater; } return getBaseContext().getSystemService(name); }

可以看到,如果为null,就会调用cloneInContext(),这个方法在LayoutInflate是抽象方法,具体实现在PhoneLayoutInflater中

public LayoutInflater cloneInContext(Context newContext) { return new PhoneLayoutInflater(this, newContext); }

可以看到,这也是一个原型模式,所以我们不要太纠结于形式,更重要的是理解这样做的好处。

除了在源码中可以看到原型模式,在开源框架中也可以看到,比如OkHttpClient中就存在着下面的方法

OkHttpClient clone() { return new OkHttpClient(this); }

可以看到,实现和前面的完全相同,也是new了一个对象返回,因为OkHttpClient的构造过程比较复杂,参数众多,所以用这种方式来直接生成新对象,成本很低,而且能保留之前对象的参数设置。

工厂方法模式

书中对于工厂方法模式的一个观点很新奇,就是Activity.onCreate()可以看做是工厂方法模式,来生成不同的View对象填充界面。

但是我对这个说法不太苟同,原因有两点:一是这种形式不太符合工厂方法,没有抽象,没有实现,不符合一般格式,也不是静态方法,不可看做是静态工厂方法;二是没有以生成对象为结果,即不是return view来生成对象,只是通过setContentView()来设置了属性而已。这就像是给一个Activity设置了背景颜色一样。当然,设计模式这东西一个人有一个人的看法。

静态工厂方法在Android中比较明显的例子应该就是BitmapFactory了,通过各种decodeXXX()就可以从不同渠道获得Bitmap对象,这里不再赘述。

策略模式

在书中策略模式讲得非常好,结合动画的插值器用法,我们可以很好的理解策略模式的形式和用法。

在我看来,策略模式就相当于一个影碟机,你往里面插什么碟子,就能放出什么电影。

同样,在OkHttpPlus的封装中,为了对网络返回值进行解析,我使用了策略模式。当然我写代码的时候还不知道策略模式,是写完了之后突然想到,这就是策略模式啊!

 

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

相关文章
  • JavaScript复习笔记--字符串

    JavaScript复习笔记--字符串

    2016-01-27 17:16

  • Swift 2.0学习笔记(Day48)——类型检查与转换 - 关东升 - 博客频道 - CSDN.NET 关东升 iO

    Swift 2.0学习笔记(Day48)——类型检查与转换 - 关东升 - 博客频道

    2015-12-14 18:16

  • 有趣的Ruby-学习笔记1 - 我可以接受失败,但我不能接受放弃。--迈克尔 乔丹 - 博客频道 - CSDN.NET

    有趣的Ruby-学习笔记1 - 我可以接受失败,但我不能接受放弃。--迈克

    2015-12-14 17:17

  • leetcode笔记:Spiral Matrix - liyuefeilong的专栏 - 博客频道 - CSDN.NET

    leetcode笔记:Spiral Matrix - liyuefeilong的专栏 - 博客频道 - CS

    2015-12-13 12:03

网友点评
i