android中的设计模式

来源:互联网 发布:淘宝上正品篮球店铺 编辑:程序博客网 时间:2024/06/06 04:10

转载自:点击打开链接 

看了一篇博客,有些自己的分析,整体还是转载的别人的博客的内容,自己跟着学习理解。

1)单例模式:各种系统Service,例如ActivityManagerService等

public class Singleton{    private volatile static Singleton instance;    //将默认的构造函数私有化,防止其他类手动new    private Singleton(){};    public static Singleton getInstance(){        if(instance==null){            sychronized(Singleton.class){                if(instance==null)                    instance=new Singleton();            }        }        return instatnce;    }}

关注点:1)私有构造函数,防止手动new出对象 

2)两道if判断,一道判断是否当前线程需要进入锁定代码块,二道判断,是否其他线程已经在本线程之前创建了单例

3)volatile保证了可见性,这个关键字会禁止指令重排序优化。也就是说,在 volatile 变量的赋值操作后面会有一个内存屏障(生成的汇编代码上),读操作不会被重排序到内存屏障之前。

2)建造者模式:Dialog中的Builder等

public class MyData{    private int id;    private String num;     public void Test(){    }     public void setId(int id){        this.id=id;    }    public void setNum(String num){        this.num=num+"id";    }}public class MyBuilder{    private int id;    private String num;    public MyData build(){        MyData d=new MyData();        d.setId(id);        d.setNum(num);        return t;    }    public MyBuilder setId(int id){        this.id=id;        return this;    }    public MyBuilder setNum(String num){        this.num=num;        return this;    }}public class Test{    public static void  main(String[] args){        MyData d=new MyBuilder().setId(10).setNum("hc").build();    }}

使用一个类来设置目标实例,Builer类的setter函数都会返回自身的引用this这主要是用于链式调用,这也是Builder设计模式中的一个很明显的特征。例如 android dialog使用一个静态内部类Builder来设置。

3)原型模型:例如Intent的Clone

原型设计模式非常简单,就是将一个对象进行拷贝。对于类A实例a,要对a进行拷贝,就是创建一个跟a一样的类型A的实例b,然后将a的属性全部复制到b。

4)工厂模式:例如getSystemService()根据字符串查找返回不同的系统Service


public abstract class Product{    public abstract void method();}public class ConcreteProductA extends Prodect{    public void method(){        System.out.println("我是产品A!");    }}public class ConcreteProductB extends Prodect{    public void method(){        System.out.println("我是产品B!");    }}public  abstract class Factory{    public abstract Product createProduct();}public class MyFactory extends Factory{    public Product createProduct(String which){        Prodect result;        switch (which){            case "A":                result = new ConcreteProductA();                break;            case "B":                result =  new ConcreteProductB();                break;        }        return result;    }}

根据不同的请求返回不同的对象结果。


5)抽象工厂模式:例如Service的onBind方法可以看成是一个工厂方法,从framework角度来看Service,可以看成是一个具体的工厂。

抽象工厂先制定好统一的抽象方法,这个时候可以对工厂进行定制,以返回不同的结果

public abstract class AbstractProductA{    public abstract void method();}public abstract class AbstractProdectB{    public abstract void method();}public class ConcreteProductA1 extends AbstractProductA{    public void method(){        System.out.println("具体产品A1的方法!");    }}public class ConcreteProductA2 extends AbstractProductA{    public void method(){        System.out.println("具体产品A2的方法!");    }}public class ConcreteProductB1 extends AbstractProductB{    public void method(){        System.out.println("具体产品B1的方法!");    }}public class ConcreteProductB2 extends AbstractProductB{    public void method(){        System.out.println("具体产品B2的方法!");    }}public abstract class AbstractFactory{    public abstract AbstractProductA createProductA();    public abstract AbstractProductB createProductB();}public  class ConcreteFactory1 extends AbstractFactory{    public  AbstractProductA createProductA(){        return new ConcreteProductA1();    }    public  AbstractProductB createProductB(){        return new ConcreteProductB1();    }}public  class ConcreteFactory2 extends AbstractFactory{    public  AbstractProductA createProductA(){        return new ConcreteProductA2();    }    public  AbstractProductB createProductB(){        return new ConcreteProductB2();    }}

6)策略模式:例如AsynceTask的executeOnExecutor()方法

算法的定制,解决问题的方式的定制,executeOnExecutor中可以使用SERIAL_EXECUTOR也可以是使用THREAD_POOL_EXECUTOR,不同侧策略来执行,前者串行,后者并行。


7)状态模式:例如Wifi模块的开关,两种模式

public interface TvState{    public void nextChannerl();    public void prevChannerl();    public void turnUp();    public void turnDown();}public class PowerOffState implements TvState{    public void nextChannel(){}    public void prevChannel(){}    public void turnUp(){}    public void turnDown(){}}public class PowerOnState implements TvState{    public void nextChannel(){        System.out.println("下一频道");    }    public void prevChannel(){        System.out.println("上一频道");    }    public void turnUp(){        System.out.println("调高音量");    }    public void turnDown(){        System.out.println("调低音量");     }}public interface PowerController{    public void powerOn();    public void powerOff();}public class TvController implements PowerController{    TvState mTvState;    public void setTvState(TvStete tvState){        mTvState=tvState;    }    public void powerOn(){        setTvState(new PowerOnState());        System.out.println("开机啦");    }    public void powerOff(){        setTvState(new PowerOffState());        System.out.println("关机啦");    }    public void nextChannel(){        mTvState.nextChannel();    }    public void prevChannel(){        mTvState.prevChannel();    }    public void turnUp(){        mTvState.turnUp();    }    public void turnDown(){        mTvState.turnDown();    }}public class Client{    public static void main(String[] args){        TvController tvController=new TvController();        tvController.powerOn();        tvController.nextChannel();        tvController.turnUp();        tvController.powerOff();        //调高音量,此时不会生效        tvController.turnUp();    }}

根据开关状态不同装入不同状态对象,改用不同的实际操作。


8)责任链模式:例如事件处理,从一开始的ViewRootImp 各种事件处理stage,到viewGroup和View的事件传递整个都是责任链模式。

使多个对象都有机会处理请求,从而避免请求的发送者和接受者直接的耦合关系,将这些对象连成一条链,并沿这条链传递该请求,直到有对象处理它为止



9)解释器模式:Xml的解析

定义:给定一个语言,定义它的语法,并定义一个解释器,这个解释器用于解析语言。

从定义中看起来比较抽象,其实,很简单,很容易理解!就是相当于自定义一个格式的文件,然后去解析它。不用理解的那么复杂!

我们看看Android中哪里用到了,从我们第一次学Android时就知道,四大组件需要在AndroidManifest.xml中定义,其实AndroidManifest.xml就定义了<Activity><Service>等标签(语句)的属性以及其子标签,规定了具体的使用(语法),通过PackageManagerService(解释器)进行解析。


10)命令模式:

定义:命令模式将每个请求封装成一个对象,从而让用户使用不同的请求把客户端参数化;将请求进行排队或者记录请求日志,以及支持可撤销操作

举个例子来理解:当我们点击“关机”命令,系统会执行一系列操作,比如暂停事件处理、保存系统配置、结束程序进程、调用内核命令关闭计算机等等,这些命令封装从不同的对象,然后放入到队列中一个个去执行,还可以提供撤销操作。

那么Android中哪里用到了命令模式呢?在framework层还真不多。但是在底层却用到了,一个比较典型的例子就是在Android事件机制中,底层逻辑对事件的转发处理。每次的按键事件会被封装成NotifyKeyArgs对象。通过InputDispatcher封装具体的事件操作。


观察者模式:

11) 观察者模式:有时Activity在旋转时回调通知各个Icon旋转动画。

定义:定义了对象之间的一对多的关系,其实就是1对n,当“1”发生变化时,“n”全部得到通知,并更新。

观察者模式一个比较经典的应用就是:订阅——发布系统。很容易理解,发布消息时,将消息发送给每个订阅者。我们常用的微信公众号就是典型,当我们关注某个公众号时,每当公众号推送消息时,我们就会去接收到消息,当然了,每个订阅(关注)公众号的的人都能接收到公众号推送的消息。

那么Android哪里用到了观察者模式呢?我们看看ListView的适配器,有个函数notifyDataSetChanged()函数,这个函数其实就是通知ListView的每个Item,数据源发生了变化,请各位Item重新刷新一下。


12)备忘录模式:

备忘录模式定义:在不破坏封闭的前提下,捕获一个对象的内部状态,并在对象之外保存这个状态,这样,以后就可将对象恢复到原先保存的状态中。

其实就是相当于一个提前备份,一旦出现啥意外,能够恢复。像我们平时用的word软件,意外关闭了,它能帮我们恢复。其实就是它自动帮我们备份过。

那么Android哪里用到了备忘录模式呢?ActivityonSaveInstanceStateonRestoreInstanceState就是用到了备忘录模式,分别用于保存和恢复。


13)迭代器模式:List中的Iterator

private class Itr implements Iterator<E> {        // The "limit" of this iterator. This is the size of the list at the time the        // iterator was created. Adding & removing elements will invalidate the iteration        // anyway (and cause next() to throw) so saving this value will guarantee that the        // value of hasNext() remains stable and won't flap between true and false when elements        // are added and removed from the list.        protected int limit = ArrayList.this.size;        int cursor;       // index of next element to return        int lastRet = -1; // index of last element returned; -1 if no such        int expectedModCount = modCount;        public boolean hasNext() {            return cursor < limit;        }        @SuppressWarnings("unchecked")        public E next() {            if (modCount != expectedModCount)                throw new ConcurrentModificationException();            int i = cursor;            if (i >= limit)                throw new NoSuchElementException();            Object[] elementData = ArrayList.this.elementData;            if (i >= elementData.length)                throw new ConcurrentModificationException();            cursor = i + 1;            return (E) elementData[lastRet = i];        }        public void remove() {            if (lastRet < 0)                throw new IllegalStateException();            if (modCount != expectedModCount)                throw new ConcurrentModificationException();            try {                ArrayList.this.remove(lastRet);                cursor = lastRet;                lastRet = -1;                expectedModCount = modCount;                limit--;            } catch (IndexOutOfBoundsException ex) {                throw new ConcurrentModificationException();            }        }        @Override        @SuppressWarnings("unchecked")        public void forEachRemaining(Consumer<? super E> consumer) {            Objects.requireNonNull(consumer);            final int size = ArrayList.this.size;            int i = cursor;            if (i >= size) {                return;            }            final Object[] elementData = ArrayList.this.elementData;            if (i >= elementData.length) {                throw new ConcurrentModificationException();            }            while (i != size && modCount == expectedModCount) {                consumer.accept((E) elementData[i++]);            }            // update once at end of iteration to reduce heap write traffic            cursor = i;            lastRet = i - 1;            if (modCount != expectedModCount)                throw new ConcurrentModificationException();        }    }

代码是ArrayList中贴出来的,内类含有外部类得应用,可以使用这个内部类来访问和便利内部类的对象,通常接入Iterator<E> 接口模型。


14)模板模式:Activity的声明周期

定义:定义一个操作中的算法框架,而将一些步骤延迟到子类中,使得子类可以不改变一个算法的结构即可重定义该算法的某些特定的步骤。

15)访问者模式

定义:封装一些作用于某种数据结构中各元素的操作,它可以在不改变这个数据结构的前提下定义作用于这些元素的新的操作。

访问者模式是23种设计模式中最复杂的一个,但他的使用率并不高,大部分情况下,我们不需要使用访问者模式,少数特定的场景才需要。

16 )中介者模式

定义:中介者模式包装了一系列对象相互作用的方式,使得这些对象不必相互明显调用,从而使他们可以轻松耦合。当某些对象之间的作用发生改变时,不会立即影响其他的一些对象之间的作用保证这些作用可以彼此独立的变化,中介者模式将多对多的相互作用转为一对多的相互作用。

android中的bindService的Binder转发机制。


17)代理模式

AIDL生成类中的Proxy类,将BInder作为自己的对象,按照规则使用BInder转发,对参数整理映射等。

18) 组合模式

定义:将对象组成成树形结构,以表示“部分-整体”的层次结构,使得用户对单个对象和组合对象的使用具有一致性。

上面的定义不太好理解,我们直接从Android中用到的组合模式说起。我们知道,Android中View的结构是树形结构,每个ViewGroup包含一系列的View,而ViewGroup本身又是View。这是Android中非常典型的组合模式。

19 适配器模式

定义:把一个类的接口变换成客户端所期待的另一个接口,从而使原本因接口不匹配而无法在一起工作的两个类能够在一起工作。

其实适配器模式很容易理解,我们在Android开发时也经常用到。比较典型的有ListView和RecyclerView。为什么ListView需要使用适配器呢?主要是,ListView只关心它的每个ItemView,而不关心这个ItemView具体显示的是什么。而我们的数据源存放的是要显示的内容,它保存了每一个ItemView要显示的内容。ListView和数据源之间没有任何关系,这时候,需要通过适配器,适配器提供getView方法给ListView使用,每次ListView只需提供位置信息给getView函数,然后getView函数根据位置信息向数据源获取对应的数据,根据数据返回不同的View。

20)装饰模式

定义:动态的给一个对象添加额外的智者,就增加功能来说,装饰模式比子类继承的方式更灵活。 

那么在Android哪里出现了装饰模式呢?我们平时经常用到Context类,但是其实Context类只是个抽象类,具体实现是ContextImpl,那么谁是ContextImpl的装饰类呢?我们知道Activity是个Context,但是Activity 并不是继承于Context,而是继承于ContextThremeWrapper.而ContextThremeWrapper继承于ContextWrapper,ContextWrapper继承Context.说了这么多,跟装饰模式有啥关系?主要是引入ContextWrapper这个类。ContextWrapper内部有个Context引用mContext,并且ContextWrapper中对Context的每个方法都有实现,在实现中调用的就是mContext相同的方法。

StartService等操作都是使用ContextImp来实现的。

21)享元模式

定义:使用享元对象有效地支持大量的细粒度对象。

享元模式我们平时接触真的很多,比如Java中的常量池,线程池等。主要是为了重用对象。

在Android哪里用到了享元模式呢?线程通信中的Message,每次我们获取Message时调用Message.obtain()其实就是从消息池中取出可重复使用的消息,避免产生大量的Message对象。

22)外观模式

定义:要求一个子系统的外部与其内部的通信必须通过一个统一的对象进行。

怎么理解呢,举个例子,我们在启动计算机时,只需按一下开关键,无需关系里面的磁盘、内存、cpu、电源等等这些如何工作,我们只关心他们帮我启动好了就行。实际上,由于里面的线路太复杂,我们也没办法去具体了解内部电路如何工作。主机提供唯一一个接口“开关键”给用户就好。

那么Android哪里使用到了外观模式呢?依然回到Context,Android内部有很多复杂的功能比如startActivty、sendBroadcast、bindService等等,这些功能内部的实现非常复杂,如果你看了源码你就能感受得到,但是我们无需关心它内部实现了什么,我们只关心它帮我们启动Activity,帮我们发送了一条广播,绑定了Activity等等就够了。还有各种保存和查找Binder转发。还真是这样。

23) 桥接模式

定义:将抽象部分与实现部分分离,使他们独立地进行变化。 
其实就是,一个类存在两个维度的变化,且这两个维度都需要进行扩展。

在Android中桥接模式用的很多,举个例子,对于一个View来说,它有两个维度的变化,一个是它的描述比如Button、TextView等等他们是View的描述维度上的变化,另一个维度就是将View真正绘制到屏幕上,这跟Display、HardwareLayer和Canvas有关。这两个维度可以看成是桥接模式的应用。

 MVC、MVP、MVVP模式

MVC:
全称为Model-View-Controller,也就是模型-视图-控制器。MVC结构如下图所




在Android中对MVC的应用很经典,我们的布局文件如main.xml就是对应View层,本地的数据库数据或者是网络下载的数据就是对应Model层,而Activity对应Controller层。


MVP:

MVP全称为Model View Presenter,目前MVP在Android应用开发中越来越重要了,它的结构图如下:


它降低了View与Model之间的耦合。彻底将View与Model分离。MVP不是一种标准化的模式,它由很多种实现。


MVVM:

全称是Mode View ViewModel,它的结构如下所示


我们在使用ListView时,会自定义一个ViewHolder,在RecyclerView中是必须使用ViewHolder,这主要是提高性能,因为不需要每次去调用findViewById来获取View。其实ViewHolder就是个ViewModel。


原创粉丝点击