Android 内功心法(1)——设计模式的原则和android中常用的模式

对编程稍稍深入了解一点的工程师来说,设计模式并不陌生。但设计模式的理解和运用每个层次的人有不同深度和广度的理解。
接下来我就来讲述一下我所理解的设计模式。
若有其他理解的工程师,欢迎前来探讨!

若想了解设计模式,那么就要先摸清它的原则和行为模式。
设计模式不针对哪种编程语言,而是针对编程思想。所以我把设计模式归为内功心法之中。

先来说说设计模式的原则(包括标准原则描述和自己理解的描述)。

1,开闭原则(Open Close Principle)

*对扩展开放,对修改关闭。
在程序需要进行拓展的时候,不能去修改原有的代码,实现一个热插拔的效果。
为了使程序的扩展性好,易于维护和升级。想要达到这样的效果,我们需要使用接口和抽象类。*

开,对所有的拓展、细化、优化操作开发。
闭,对原有逻辑的修改关闭。
开闭原则的目的就是保证原有逻辑的正常情况下添加新的逻辑。

举个栗子:一个工厂,开始做肥皂。后来为了拓展行业渠道,尝试做香皂。那么这个工厂就要遵守开闭原则。对新增做香皂的业务开放(新开一条生产链),对修改做肥皂的业务关闭(把肥皂尝试做成香皂)。要不然,香皂做不成,把肥皂也修改的不能正常盈利,岂不是搬石头砸了自己的脚。

2,里氏代换原则(Liskov Substitution Principle)

*它是面向对象设计的基本原则之一。
任何父类或者基类可以出现的地方,子类一定可以出现。
它是继承复用的基石。只有当衍生类可以替换掉基类,软件单位的功能不受到影响时,基类才能真正被复用,而衍生类也能够在基类的基础上增加新的行为。
里氏代换原则是对“开-闭”原则的补充。
实现“开-闭”原则的关键步骤就是抽象化。
而基类与子类的继承关系就是抽象化的具体实现,所以里氏代换原则是对实现抽象化的具体步骤的规范*

里氏代换的原则很简单,就是一个儿子,你如果想去做你父亲做的事情,那么你必须学会你父亲会的所有技能。作为儿子,你可以去编程,会武术,学跳舞。但是前提是你父亲会的喝酒,抽烟,把妹你都要会。这样,作为儿子才能真正的接替父亲的位置。
程序中,任何一个父类或者基类的方法在其子类或者孙子类中都必须全部继承或者全部实现。这样当任何一个需要基类的地方都可以用其子类代替。这就是里氏代换的原则。

3、依赖倒转原则(Dependence Inversion Principle)

这个是开闭原则的基础,具体内容:针对接口编程,依赖于抽象而不依赖于具体。

这个空口说来也说不太清楚,还是举个栗子:一个机器要把很多种类的饮料分类,最笨的办法就是给机器输入命令“碳酸饮料:可乐,雪碧,芬达;牛奶类:蒙牛,光明,伊利。”这样,机器就会去一一对应的找饮料,找到了可乐,就把它丢在碳酸饮料类。这叫让机器依赖“具体”。让它知道什么是什么。
而依赖抽象,则是弄出很多的大盒子,每个盒子上都是标签,比如碳酸饮料,牛奶,咖啡什么的。
机器只需要将每个盒子那来归类。碳酸饮料的盒子就放在碳酸饮料类里面。这样,机器不用知道每种饮料是什么,机器只用知道面前的几个大盒子是什么该放在哪里就ok。盒子就是“抽象”的。盒子可以代表可乐,可以代表雪碧,可以代表芬达。所以,盒子就成了逻辑(机器)和具体(饮料)之间的抽象(盒子)了。
这样看来,的确减少了很多的工作量。

4、接口隔离原则(Interface Segregation Principle)

使用多个隔离的接口,比使用单个接口要好。还是一个降低类之间的耦合度的意思。

标准解释还是不太清楚。我补充一下:接口隔离的意思是:不要一个类放一个他自己需要的接口,然后其他类去调用这个类的时候去使用这个接口。而是把所有的接口统一起来,这个类需要实现某个接口,直接调用接口类中的接口。另一个类需要使用某个接口,则就实例化接口类中的某个接口。
这就是把接口隔离在一个类中统一管理。让类与类之间没有联系,而让他们都去找接口。

现实中有个东西就很好的表明这一思想。活动扳手。扳手的卡口是可以活动的。就像把很多型号的卡口集中于一身。这样,不管是那个螺丝都能来找这个扳手,找到自己想要的卡口型号。这个扳手的卡口就相当于一个“接口”的统一管理类。而螺丝就是很多很多需要某个接口的“使用类”。而扳手则就是某个型号的“实现类”。卡口就成功的成了隔离众多接口的一个“接口统一管理类”

5、迪米特法则(最少知道原则)(Demeter Principle)

为什么叫最少知道原则,就是说:一个实体应当尽量少的与其他实体之间发生相互作用,使得系统功能模块相对独立。

这个比较容易理解。程序中,最少知道原则的最好体现就是众多的utils工具类。某个工具类,你传入一个参数,就可以返回给你一个想要的结果。这就是最少知道原则的最好体现。当然,放在设计模式中比这个要稍微复杂一些,不过意思就是这样。

6、合成复用原则(Composite Reuse Principle)

*原则是尽量使用合成/聚合的方式,而不是使用继承。
组合和聚合都是对象建模中关联(Association)关系的一种.聚合表示整体与部分的关系,表示“含有”,整体由部分组合而成,部分可以脱离整体作为一个独立的个体存在。组合则是一种更强的聚合,部分组成整体,而且不可分割,部分不能脱离整体而单独存在。在合成关系中,部分和整体的生命周期一样,组合的新的对象完全支配其组成部分,包括他们的创建和销毁。一个合成关系中成分对象是不能与另外一个合成关系共享。*

这个理解起来用两个集体来表示最好不过。聚合就相当于一个班级。6年3班由40个同学组成,某个同学走了,6年3班还是6年3班,走的同学还是可以完成作为学生的一切行为。就算走了39个同学,意思还是一样。聚合由个体组成,但个体可以脱离聚合单独使用,聚合失去个体也可以存在。

而组合就相当于一个app软件开发团队。队伍中有销售,有后台,有android,有ios,还有经理。这是一个团队,是个“合成”。这个组合中任何一个成员离开都不能叫团队了,而离开的成员也不能单独完成任务。开发团队就是一个部分组成但不可分割的“合成”。
不管是聚合还是合成,其中的对象都不能和另外的聚合或者合成达成关系。就像,6年3班的同学不可能是6年4班的同学,这个开发团队的成员不可能同时为另一个团队工作。

好了,这就是设计模式的原则。只要深入了解了设计模式的原则, 自己就可以设计出很多优秀的设计模式。现在为止设计模式已经有很多种了,但是最经典的还是人人熟知的那24种。

那么,个人建议每一种都要学习,一一学习的机会就留给大家去完成了。我主要说说,android中经常用到的一些设计模式。

一般来说,常用的有以下八种:单例、工厂、观察者、代理、命令、适配器、合成、访问者。

单例模式:目的是为了让系统中只有一个调用对象,缺点是单例使其他程序过分依赖它,而且不同单例运行在不同进程中,使得维护困难;
这里不得不提到一点,一般的单例,刚刚开始接触设计模式的人会用synchronized来同步不同线程中的进入顺序。
虽然很直观很简单。但是,这种单例在序列化和反射机制的时候依然不能达到单例的效果。也就是说它能满足百分之九十的逻辑处理。只要你的程序不太复杂,那么用这种是完全没问题的。

那么问题来了。还有没有更好的办法?
其实早就不是什么新技巧了。枚举。
由于时间原因,以后会详细讲解。

工厂模式:生产固定的一些东西,如抽象类,缺点是产品修改麻烦;如喜欢动作片和爱情片的人分别向服务器发出同一个请求,就可以得到他们想看的影片集,相当于不同对象进行同一请求,需求均得到满足。
做过类似超市收银的应该都清楚,工厂模式在其中体现的最为贴切。最好是工厂+策略模式,同时使用。

观察者模式:就是多个对象对一个对象进行监控,如缓存;
观察者模式让我想起了一个小小的工具库“EventBus.jar”。
这个工具库就是规定方法名,发送请求后,所有被规定的方法名的方法都会接收到值,就相当于一个比较简化的观察者模式。
我在设计框架的时候经常用这个工具库去发送网络请求的返回值。因为网络请求在任何页面任何时候都要返回。所以观察者模式再适合不过了。

代理模式:自己的事交给别人去做,分别返回结果即可,如异步线程;

命令模式:调用对象与作用对象之间分离,由中间件来协调两者之间的工作,如控制器;

适配器模式:将一个接口变成用户所需要的接口,如baseadapter可以适配listview和spinner,因为它们有相同的接口

合成模式:将一对多的关系转换成一对整体的关系,如listview与适配器;

访问者模式:对不同的对象采取不同的处理,如instanceof。

由于今天时间关系,先把这篇文章的目的写出来。 详解了设计模式的原则和几种android中常用的设计模式。 后续会给出每种设计模式的详细解释。

另外,推荐设计模式的书籍:
1,《大话设计模式》
简单易懂且有意思。(用c语言写的。不过相信接触设计模式的工程师们对于不同语言写的已经不是什么影响了)

2,《Android 源码设计模式解析与实战》
第一本关于android的设计模式。讲解android源码中用到的设计模式。设计模式用到最多的地方当然是源码了。

还有个超链接 http://mobile.51cto.com/android-419145.htm

希望对正在学习和准备进阶的工程师们有所帮助!

本页内容版权归属为原作者,如有侵犯您的权益,请通知我们删除。

Java认识 - 2016-05-04 18:05:03

Java 概述 一、java的历史: 1,它是由一个错误来的(在1990年末,Sun公司预料嵌入式系统将在未来家用电器领域大显身手,于是成立了一个由James Gosling领导的“Green计划”,准备为下一代智能家电(如电视机、微波炉、电话)编写一个通用控制系统。),刚开始的名字,叫Oak,但是在最后因为在当时oak这个商标已被别人注册,于是只得将oak更名为Java 。 2, 到1998年12月,Sun发布了Java历史上最重要的JDK版本:     JDK1.2,并将Java分成了J2EE、J2S

Hello,服务端 Swift - 2016-05-04 17:05:00

原文: Hello Server Side Swift 作者: Logan Wright 译者: kmyhy 自从苹果官方发布了一个 Swift 的 Linux 开源版本之后,服务端 Swift 终于迎来了一个令人激动的前景。我的好奇心终于无法克制,是时候尝试一下服务端 Swift 了! 除了用过几个 Baas 以外,我没有任何后端编程经验,但幸运的是开源社区已经提供了现成的框架。我试了一下 Tanner Nelson 推荐的 Vapor 框架。它的使用非常简单,非常适合我当前的任务,在这篇文档中还会使用
一、前言 今天我们开启Android系统篇的文章了,其实一直想弄,只是之前一直没有太多深入的了解,最近又把这块拿出来好好看了一下,所以想从新梳理一下,来看看Android中的这块知识,首先我们今天来看一下:Android中的智能指针的概念,为什么说先看一下智能指针这个知识呢?因为我们在看Android源码的时候,会发现几乎好多地方都用到了这个东东,所以我们在介绍后面的知识点,先来看看这个吧。 二、问题 那么Android中的智能指针是个什么东西呢?我们知道Android用的Java语言开发的,Java语言
C++中不要使用包含中文字符串,否则打包的时候编译错误();虚幻中提供了使用中文的工具:本地化。 1. 启用本地化功能 这样,在菜单“窗口”项就会出现“本地化面板” 2. 使用本地化    a. 添加目标              b.修改Config中 DefaultEngine.ini。    添加下面内容:     [Internationalization]     +LocalizationPaths=/Game/Localization/Game   c.添加收集目录       d.添加新语
/prep最近半年来身边开发的朋友越来越多的提到OkHttp,上谷歌百度一下,确实OkHttp成了时下最火的HTTP框架,于是我也开始放下Volley,转而关注OkHttp,五一期间仔细看了官方WiKi介绍(我喜欢学习官方的文档),现在把自己整理的官方教程分享给大家,希望给初学者带来帮助。 br /       OkHttp官网地址:a target=_blank href=#>        OkHttp perseveres when the network is troublesome: it wi

Activity启动模式学习 - 2016-05-04 17:05:31

最近学习了Activity的启动模式,这里记录下,以便以后回顾 Activity有四种启动模式,分别为: * standard * singleTop * singleTask * singleInstance standard 默认情况下,系统会以standard模式来启动activity,这种模式下系统会创建一个新的activity实例。 singleTop 指定Activity的启动模式为singleTop时,当被启动的Activity B已经存在一个实例,并且位于任务栈的栈顶,这时候系统就不会生成
Current git graph Now we want to create a new branch called  dev  from our master branch. Here is our current state of our git graph before the branching:   Creating a dev branch To create a new branch ( dev ), we need click "Branch" on the top menu.   Hi
1 背景 这篇文章主要说明的是用它来看源码的相关配置(该实例依据官方源码进行配置说明)。在android源码中发现有一个development/tools/idegen目录,查了一下发现是生成IDE的project文件(主要是intellij的project文件,其实也就是Android Studio的),所以说福利工具就这么来了,欲知详情,请看下文。 2 配置使用过程 2-1 基础准备工作 首先你得安装配置了Android Studio,接着你得下载好了源码Code,至于如何下载这里不再说明,比较简单,

AsyncTask获取数据库数据 - 2016-05-04 17:05:10

2016_04_25 —————R 关于 http://blog.csdn.net/u010045971/article/details/50853651 未尽之事 1. 为应用程序添加provider的访问权限。 在manifest标签内,定义上面的提到的 permission permission android:name = "com.example.android.sunshine.app.LICENSE_TO_KILL" android:protectionLevel = "dangerous"
activity 生命周期 完整生命周期   oncreate-- 》 onstart-- 》 onresume-- 》 onpause-- 》 onstop-- 》 ondestory   可视生命周期   onstart-- 》 onresume-- 》 onpause-- 》 onstop   前台生命周期   onresume-- 》 onpause   界面用户仍然可见,但是失去焦点     使用场景: 1. 应用程序退出自动保存数据    ondestory   oncreate 2. 应用程