前言

Android开发的设计模式,基本设计思想源于java的设计模式,java的设计模式有N多种,据不完全统计,迄今为止,网络出现最频繁的大概有23种。Java只是一门开发语言,学会并掌握这门语言进行代码编写,这是每个程序员必修的课程,但如何写出高质量、易维护和复用性强的代码,那就体现出程序员的层次和水平了。设计模式的出现就是为了解决这些问题。

开始学习设计模式的时候,我们通常都有种将简单问题复杂化的感觉,明明一个类N行代码就能完成的事情,干嘛非要创建几个类?又抽象又难理解的。后来随着开发经验的增长,重复劳动的频繁,终有一天顿悟,体验到设计模式的妙用,方感慨万千。常言,水滴石穿,做任何事都是这样,经验和时间是最好的试金石,B哥老矣,前车之鉴,后车之师。闲言少叙,话转正题,我们介绍一下常用的设计模式。

工厂模式

什么是工厂模式?官方有很多解释,我这里把我所理解的结合经验,诠释给大家,我不想绞尽脑汁,抽象总结出类似于古文(JAVA编程思想)那样难于理解的文字,也没那个水平言简意赅的、一针见血的总结出众生都能看懂的解释。只能笨鸟先飞、勤能补拙,从实践出真知的角度出发,抛砖引玉,供大家思考。公司有个这样一个需求,在App中要使用到LBS定位来实现某些功能。产品技术一大堆开始了需求、技术确认会,当大家讨论到定位是用百度API来实现,还是用高德来实现。大家争论不休,有人说百度定位不准,有人说高德定位不准,众说纷纭。咋办?最后,B总拍板,两个一起用,哪个好用哪个,领导拍板了,但说了又等于没说,咋办?工厂模式这时候就呼之欲出了,我两个都给你设计,代码设个开关和参数,你说用高德不爽,我改个参数,就换百度,直到领导高兴为止,于是代码就产生了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
public class test {
       public static void main(String[] args) {
              Location position= new LocationFactory().getInstance("xiaomi");
              position.getPosition();
              position.getCityName(1020);
       }
}
  
class LocationFactory{
       public static Location getInstance(String type){
              if("baidu".equals(type)){
                     return new BaiduLocation();
              }else {
                     return new XiaoMiLocation();
              }
       }
}
class BaiduLocation implements Location{
       @Override
       public void getPosition() {
              // TODO Auto-generated method stub
              System.out.println("通过百度定位获取到当前的经纬度是XXXXX");
       }
       @Override
       public void getCityName(long lat, long lng) {
              // TODO Auto-generated method stub
              System.out.println("通过百度定位获取到当前的城市是XXXXX");
       }
}
class XiaoMiLocation implements Location{
       @Override
       public void getPosition() {
              // TODO Auto-generated method stub
              System.out.println("通过小米定位获取到当前的经纬度是XXXXX");
       }
       @Override
       public void getCityName(long lat, long lng) {
              // TODO Auto-generated method stub
              System.out.println("通过小米定位获取到当前的城市是XXXXX");
       }
}
interface Location{
       public void getPosition();
       public void getCityName(long lat,long lng);
}

上面的例子,较好的阐述了工厂模式的概念。LocationFactory是一个工厂类,静态函数getInstance的参数决定了是选用百度还是高德,这样,对于调用者来说,只需要关心你是用百度还是高德即可。Location是一个接口,它抽象出高德和百度常用的函数调用。拿定位来说,基本上常用的就是根据经纬度查询地址,或者定位当前所在位置获取经纬度。当然可能还有更多有用的函数,我这里就不在列举。有了这样一个共性的接口,XiaoMiLocation和BaiduLocation通过实现它的接口就能分别满足调用者的需求。调用者就能够任意通过改变参数,来实现来自不同定位API的需求。当然,如果百度和高德不爽,你完全可以使用谷歌API,只需要构造一个GoogleLocation类并实现Location接口的方法即可。

工厂模式的应用非常广泛,比如android的bitmap中常用的BitmapFactory类,创建Bitmap对象,通常使用静态工厂方法。

单例模式:

什么是单例模式?单例模式的精髓主要在这个“单”字上,“单”就是一个,直接进入主题,我们通常使用“new”关键字创建一个对象,一旦“new”了,它就会开辟内存创建一个对象。假设我们经常反复创建的这个对象对我们来说其实都是一回事,那么我们就没必要浪费资源和时间嘛,好比,你去外地出差在某个地方至少1天,第一次你去服务台,服务台给你开了间房,你高高兴兴的拿着钥匙进房睡觉了。睡醒后出去办事。完事后,你是不是直接拿着这个钥匙直接奔你开好的房间?该不会去服务台再去开一间吧?大道至简,其实,细细想来,生活就是一种模式,只要你善于发现,你就会有意外惊喜,原来都是这样简单。

来个例子吧,枯燥的代码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class Room {
       public static Room key;
       public static void main(String[] args) {
              Room room=getKey();
              room.openDoor();
              Room room1=getKey();
              room1.openDoor(); 
       }
       public static Room getKey(){
              if(key==null){
                     key=new Room();
              }
              return key;
       
       public void openDoor(){
              System.out.println("我打开了门......");
       }
}

看看上面这个例子,是不是跟我举得宾馆的例子相似?你不管多少次拿钥匙,你都拿的是同一间房的钥匙,不会重新给你发一把,这样做,既节约了宾馆的时间,也节约了你的时间,多好啊。再引申一点说,android开发中也常常使用到单例模式,比如网络的封装,数据库的访问都用到了单利的设计模式。

观察者模式:

什么是观察者模式?一般提到原告,必然脑子立刻联想到被告,观察者和被观察者就如同原告和被告总是那么成对出现。观察者模式,又被叫做订阅模式,有订阅者和发布者。当下IPHONE6异常火爆,国内粉丝要想购买,那必须得预定,必须到它苹果官方去预定,填一大堆资料,交不交钱我不知道,反正得预定登记。等粉丝等到两眼欲穿、花儿快谢了时候,它粉墨登场了,官方以高姿态从容向预定过的粉丝发售。这苹果就是被观察者,粉丝就是观察者,观察者和被观察者之间需要建立联系,那就是登记。登记过后,被观察者拿捏火候觉得时机成熟的时候,就以权位者姿态向观察者抛出绣球,观察者迫不及待的伸出双手牢牢抓住后,满心欢喜的赞美苹果的伟大和自己的庆幸。睁大眼睛盯着目标看,期待期望结果,这就是观察者模式。

来段代码体验一把

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
import java.util.ArrayList;
import java.util.List;
  
  
public class MyOberver {
        public static void main(String[] args) {
               American american=new American();
               Chinese chinese=new Chinese();
               Iphone iphone=new Iphone();
               System.out.println("一个美国人登记购买");
               iphone.register(american);
               System.out.println("一个中国人登记购买");
               iphone.register(chinese);
               try {
                      System.out.println("经过6个月的漫长等待...");
                     Thread.sleep(2000);
              catch (InterruptedException e) {
                     // TODO Auto-generated catch block
                     e.printStackTrace();
              }
               iphone.notifys();
       }
}
/**观察者*/
class Iphone{
       private List<Fensi> list=new ArrayList<Fensi>();
       public void register(Fensi n){
              list.add(n);
              System.out.println("又一个苹果被预订了,现在总共有:"+list.size()+"个人预订了...");
       }
       public void notifys(){
              System.out.println("IPHONE 6现在高调发售...");
              for (Fensi n:list) {
                            n.receive();
              }
       }
}
class American implements Fensi{
       @Override
       public void receive() {
              // TODO Auto-generated method stub
              System.out.println("美国人喊叫:嗯哼,有点贵....");
       }
}
class  Chinese implements Fensi{
       @Override
       public void receive() {
              // TODO Auto-generated method stub
              System.out.println("中国人:我终于买到了,高兴死了....");
       }
}
interface Fensi{
              public void receive();
}

运行后输出结果:

一个美国人登记购买

又一个苹果被预订了,现在总共有:1个人预订了...

一个中国人登记购买

又一个苹果被预订了,现在总共有:2个人预订了...

经过6个月的漫长等待...

IPHONE 6现在高调发售...

美国人喊叫:嗯哼,有点贵....

中国人:我终于买到了,高兴死了....

这就是观察者模式,Chinese和American都是观察者,它们继承了Fensi接口,具有了接收消息receive的能力,Iphone是被观察者,是被观察的目标,它的一举一动,都会深深的影响Fensi们的热情,观察者需要在被观察者哪里进行登记购买register,登记过后,等到时机成熟了,被观察者会主动放出信号iphone.notifys();这样,凡是登记过购买苹果6的粉丝们,都会纷纷收到取货的信息了。

代理模式:

什么是代理模式?代理模式在各类开发中运用的相当广泛,不论是j2ee,android还是ios,都能看到它的身影,所以说设计模式无处不在。代理模式,字面理解就是自己不方便做或者不能做的事情,需要第三方代替来做,最终通过第三方来达到自己想要的目的或效果。举例了:员工小李在B总公司打工,B总成天让小李加班不给加班费,小李忍受不住了,就想去法院告B总。虽然法律上允许打官司不请律师,允许自辩。但是小李第一不熟悉法律起诉的具体流程,第二嘴比较笨,人一多腿就抖得厉害。因此,小李决定去找律师帮忙打官司。找律师打官司和自己打官司相比,有相同的地方,也有不同的地方。

相同的地方在于:

1、  都需要提交原告的资料,如姓名、年龄、事情缘由、想达到的目的。

2、  都需要经过法院的取证调查,开庭争辩等过程。

3、  最后拿到审判结果。

不同地方在于:

1、  小李省事了,让专业的人做专业的事,不需要自己再去了解法院那一套繁琐复杂的流程。

2、  把握更大了。

通过上面的例子,我们注意到代理模式有几个重点。

1、  被代理的角色(小李)

2、  代理角色(律师)

3、  协议(不管是代理和被代理谁去做,都需要做的事情,抽象出来就是协议)

下面给个例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
public class Proxy {
       public static void main(String[] args) {
              Employer employer=new Employer();
              System.out.println("我受不了了,我要打官司告老板");
              System.out.println("找律师解决一下吧......");
              Protocol lawyerProxy=new LawyerProxy(employer);
              lawyerProxy.register("朵朵花开");
              lawyerProxy.dosomething();
              lawyerProxy.notifys();
       }
}
interface Protocol{
       //登记资料
       public void register(String name);
       //调查案情,打官司
       public void dosomething();
       //官司完成,通知雇主
       public void notifys();
}
//律师类
class LawyerProxy  implements Protocol{
       private Employer employer;
       public LawyerProxy(Employer employer){
              this.employer=employer;
       }
       @Override
       public void register(String name) {
              // TODO Auto-generated method stub
              this.employer.register(name);
       }
  
       public void collectInfo(){
              System.out.println("作为律师,我需要根据雇主提供的资料,整理与调查,给法院写出书面文字,并提供证据。");
       }
       @Override
       public void dosomething() {
              // TODO Auto-generated method stub
              collectInfo();
              this.employer.dosomething();
              finish();
       }
       public void finish(){
              System.out.println("本次官司打完了...............");
  
       }
       @Override
       public void notifys() {
              // TODO Auto-generated method stub
              this.employer.notifys();
       
}
//雇主类
class Employer implements Protocol{
       String name=null;
       @Override
       public void register(String name) {
              // TODO Auto-generated method stub
              this.name=name;
       }
  
       @Override
       public void dosomething() {
              // TODO Auto-generated method stub
              System.out.println("我是'"+this.name+"'要告B总,他每天让我不停的加班,还没有加班费。");
       }
  
       @Override
       public void notifys() {
              // TODO Auto-generated method stub
              System.out.println("法院裁定,官司赢了,B总需要赔偿10万元精神补偿费。");
       }
        
}

运行后,打印如下:

我受不了了,我要打官司告老板

找律师解决一下吧......

作为律师,我需要根据雇主提供的资料,整理与调查,给法院写出书面文字,并提供证据。

我是'朵朵花开'要告B总,他每天让我不停的加班,还没有加班费。

本次官司打完了...............

法院裁定,官司赢了,B总需要赔偿10万元精神补偿费。

代码说明:

Protocol这个类就是上面所说的协议,是被代理者或者代理者共同遵守的约定。也就是说,无论是原告还是代理律师,到法院走程序,都需要做的事情。我们抽象出来,这个就是协议。

Employer这类是雇主类也称被代理者类,它遵从Protocol协议,并实现了Protocol协议的三个方法,并去分别完成了具体事情。

LawyerProxy这类是代理类,它也遵从Protocol协议,与Employer不同的是,定义了一个Employer对象,通过构造函数初始化。在实现的三个方法里,分别去调用被代理类的相同实现。就好比去模拟一个被告者,站在被告的角度上,去法院告状。也就是说LawyerProxy代理类对所有想打官司的人开放,只要有原告进来,我就帮他打官司。值得注意的是collectInfo和finish这两个函数,请律师打官司和不请律师打官司,其实都要做同样的事情(register、dosomething、notifys),但是至于为什么?刚才不是说了吗,请律师的好处是省心并且专业,他在做同样的事情前提下,还会收集对你有利的证据和资料(collectInfo),以及后续事情的处理(finish)。

上面就是最普通的代理模式,引申一点,我们看到,对于被告来说,必须创建一个Employer类,并实例化后传参给LawyerProxy代理类,这样做,是不是暴漏了Employer?如果隐藏一下,对于被告来说,更智能傻瓜一点,该怎么做呢?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
public class Proxy {
       public static void main(String[] args) {
              //Employer employer=new Employer();
              System.out.println("我受不了了,我要打官司告老板");
              System.out.println("找律师解决一下吧......");
              Protocol lawyerProxy=new LawyerProxy("朵朵花开"); 
              lawyerProxy.dosomething();
              lawyerProxy.notifys();
       }
}
interface Protocol{
       //登记资料
       public void register(String name);
       //调查案情,打官司
       public void dosomething();
       //官司完成,通知雇主
       public void notifys();
}
//律师类
class LawyerProxy  implements Protocol{
       private Employer employer;
       public LawyerProxy(String name){
              if(name==null) {
                     System.out.println("谁告状?逗我玩呢吧?");
                     return;
              }
              if(employer==null) employer=new Employer();
              register(name); 
       }
       @Override
       public void register(String name) {
              // TODO Auto-generated method stub
              this.employer.register(name);
       }
  
       public void collectInfo(){
              System.out.println("作为律师,我需要根据雇主提供的资料,整理与调查,给法院写出书面文字,并提供证据。");
       }
       @Override
       public void dosomething() {
              // TODO Auto-generated method stub
              collectInfo();
              this.employer.dosomething();
              finish();
       }
       public void finish(){
              System.out.println("本次官司打完了...............");
  
       }
       @Override
       public void notifys() {
              // TODO Auto-generated method stub
              this.employer.notifys();
       
}
//雇主类
class Employer implements Protocol{
       String name=null;
       @Override
       public void register(String name) {
              // TODO Auto-generated method stub
              this.name=name;
       }
  
       @Override
       public void dosomething() {
              // TODO Auto-generated method stub
              System.out.println("我是'"+this.name+"'要告B总,他每天让我不停的加班,还没有加班费。");
       }
  
       @Override
       public void notifys() {
              // TODO Auto-generated method stub
              System.out.println("法院裁定,官司赢了,B总需要赔偿10万元精神补偿费。");
       }
        
}

看到没new LawyerProxy("朵朵花开"),只需要给代理类传入简单的名字,隐含了Employer类,代理类就会自动去创建一个Employer实例,模拟一个用户继续替你完成打官司的事情。

篇幅有限,设计模式有很多种,以上列举了常用的几种,也是最常用最基础的几种,希望大家能够理解并掌握,如有兴趣,请参考《设计模式之禅》这本书,个人觉得不错。

转载出处:http://my.oschina.net/u/2249934/blog/343441

Android中常见的设计模式的更多相关文章

  1. android中常见的设计模式有哪些?

    建造者模式 建造者模式最明显的标志就是Build类,而在Android中最常用的就是Dialog的构建,Notification的构建也是标准的建造者模式. 建造者模式很好理解,如果一个类的构造需要很 ...

  2. Android开发中常见的设计模式 MD

    Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...

  3. Android中常见的内存泄漏

    为什么会产生内存泄漏? 当一个对象已经不需要再使用了,本该被回收时,而有另外一个正在使用的对象持有它的引用从而导致它不能被回收,这导致本该被回收的对象不能被回收而停留在堆内存中,这就产生了内存泄漏. ...

  4. Android开发中常见的设计模式

    对于开发人员来说,设计模式有时候就是一道坎,但是设计模式又非常有用,过了这道坎,它可以让你水平提高一个档次.而在android开发中,必要的了解一些设计模式又是非常有必要的.对于想系统的学习设计模式的 ...

  5. Android开发中常见的设计模式(二)——Builder模式

    了解了单例模式,接下来介绍另一个常见的模式--Builder模式. 那么什么是Builder模式呢.通过搜索,会发现大部分网上的定义都是 将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建 ...

  6. Android开发中常见的设计模式(三)——观察者模式

    先看下这个模式的定义. 定义对象间的一种一对多的依赖关系,当一个对象的状态发送改变时,所有依赖于它的对象都能得到通知并被自动更新 先来讲几个情景. 情景1:有一种短信服务,比如天气预报服务,一旦你订阅 ...

  7. Android开发中常见的设计模式(一)——单例模式

    首先了解一些单例模式的概念. 确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例. 这样做有以下几个优点 对于那些比较耗内存的类,只实例化一次可以大大提高性能,尤其是在移动开发中. 保持 ...

  8. Android 中常见控件的介绍和使用

    1 TextView文本框 1.1 TextView类的结构 TextView 是用于显示字符串的组件,对于用户来说就是屏幕中一块用于显示文本的区域.TextView类的层次关系如下: java.la ...

  9. Android中常见的MVC模式

    MVC模式的简要介绍 MVC是三个单词的缩写,分别为: 模型(Model),视图(View)和控制Controller). MVC模式的目的就是实现Web系统的职能分工. Model层实现系统中的业务 ...

随机推荐

  1. LoadRunner脚本优化—迭代的组合用法

    Elect next row——选择下一行 Sequential:顺序取行 Random:随机取行 Unique:每一个值只能使用一次 中止:abort Vuser 循环Vuser分配到的列表 只循环 ...

  2. zepto源码分析·event模块

    准备知识 事件的本质就是发布/订阅模式,dom事件也不例外:先简单说明下发布/订阅模式,dom事件api和兼容性 发布/订阅模式 所谓发布/订阅模式,用一个形象的比喻就是买房的人订阅楼房消息,售楼处发 ...

  3. 斯坦福机器学习课程 Exercise 习题三

    Exercise 3: Multivariate Linear Regression 预处理数据 Preprocessing the inputs will significantly increas ...

  4. Java基础(二十六)Java IO(3)字节流(Byte Stream)

    字节流是以字节为单位来处理数据的,由于字节流不会对数据进行任何转换,因此用来处理二进制的数据. 一.InputStream类与OutputStream类 1.InputStream类是所有字节输入流的 ...

  5. Java基础(七)泛型数组列表ArrayList与枚举类Enum

    一.泛型数组列表ArrayList 1.在Java中,ArrayList类可以解决运行时动态更改数组的问题.ArrayList使用起来有点像数组,但是在添加或删除元素时,具有自动调节数组容量的功能,而 ...

  6. java 调用启动远程shell脚本,启动spark

    1 依赖 <!--远程调用shell--> <dependency> <groupId>ch.ethz.ganymed</groupId> <ar ...

  7. Excel的IYQ钓鱼

    0x00 环境准备 1.操作系统:windows7 2.microsoft office版本:office 2010 0x01 了解IYQ的基本概念 可以将IYQ简单的理解成内置在excel中的一种特 ...

  8. Feeling after reading《Jane Eyre》

    Yesterday I read and listened over the book named <Jane Eyre>, the book is very thoughtful, th ...

  9. MVC5异步提交表单疑难杂症

    //此处必须添加,不然不能执行异步回调OnAddPortSuccess方法 <script src="~/scripts/jquery.unobtrusive-ajax.min.js& ...

  10. 和manacher有关的乱写

    当初学kmp hash的时候被教导manacher非常的鸡肋 今天因为一篇神奇的题解我忍不住颓废了两节课把它学了 思路,代码都比较好懂 虽然它不如各种自动机霸气,唯一的功能貌似就是$O(n)$求出所有 ...