Android源码中的设计模式

最近看了一些Android的源码,发现设计模式无处不在啊!感觉有点乱,于是决定要把设计模式好好梳理一下,于是有了这篇文章。

面向对象的六大原则

单一职责原则所谓职责是指类变化的原因。如果一个类有多于一个的动机被改变,那么这个类就具有多于一个的职责。而单一职责原则就是指一个类或者模块应该有且只有一个改变的原因。通俗的说,即一个类只负责一项职责,将一组相关性很高的函数、数据封装到一个类中。

开闭原则对于扩展是开放的,这意味着模块的行为是可以扩展的。当应用的需求改变时,我们可以对模块进行扩展,使其具有满足那些改变的新行为。对于修改是关闭的,对模块行为进行扩展时,不必改动模块的源代码。通俗的说,尽量通过扩展的方式实现系统的升级维护和新功能添加,而不是通过修改已有的源代码。

里氏替换原则使用“抽象(Abstraction)”和“多态(Polymorphism)”将设计中的静态结构改为动态结构,维持设计的封闭性。任何基类可以出现的地方,子类一定可以出现。在软件中将一个基类对象替换成它的子类对象,程序将不会产生任何错误和异常,反过来则不成立。在程序中尽量使用基类类型来对对象进行定义,而在运行时再确定其子类类型,用子类对象来替换父类对象。

依赖倒置原则高层次的模块不应该依赖于低层次的模块,他们都应该依赖于抽象。抽象不应该依赖于具体实现,具体实现应该依赖于抽象。程序要依赖于抽象接口,不要依赖于具体实现。简单的说就是要求对抽象进行编程,不要对实现进行编程,这样就降低了客户与实现模块间的耦合(各个模块之间相互传递的参数声明为抽象类型,而不是声明为具体的实现类)。

接口隔离原则一个类对另一个类的依赖应该建立在最小的接口上。其原则是将非常庞大的、臃肿的接口拆分成更小的更具体的接口。

迪米特原则又叫作最少知识原则,就是说一个对象应当对其他对象有尽可能少的了解。通俗地讲,一个类应该对自己需要耦合或调用的类知道得最少,不关心被耦合或调用的类的内部实现,只负责调用你提供的方法。下面开始设计模式学习...

1.Singlton(单例模式)

作用:

保证在Java应用程序中,一个类Class只有一个实例存在。

好处:

由于单例模式在内存中只有一个实例,减少了内存开销。

单例模式可以避免对资源的多重占用,例如一个写文件时,由于只有一个实例存在内存中,避免对同一个资源文件的同时写操作。

单例模式可以再系统设置全局的访问点,优化和共享资源访问。

使用情况:

建立目录数据库连接的单线程操作

某个需要被频繁访问的实例对象

1.1使用方法

第一种形式:

8publicclassSinglton{/*持有私有静态实例,防止被引用,此处赋值为null,目的是实现延迟加载*/privatstaticSingltoninstanc=null;/*私有构造方法,防止被实例化*/privatSinglton(){}/*懒汉式:第一次调用时初始Singlton,以后就不用再生成了静态方法,创建实例*/publicstaticSingltongtInstanc(){if(instanc==null){instanc=nwSinglton();}rturninstanc;}}

但是这有一个问题,不同步啊!在对据库对象进行的频繁读写操作时,不同步问题就大了。

第二种形式:

既然不同步那就给gtInstanc方法加个锁呗!我们知道使用synchronizd关键字可以同步方法和同步代码块,所以:

publicstaticsynchronizdSingltongtInstanc(){if(instanc==null){instanc=nwSinglton();}rturninstanc;}

或是

78publicstaticSingltongtInstanc(){synchronizd(Singlton.class){if(instanc==null){instanc=nwSinglton();}}rturninstanc;}

获取Singlton实例:

1Singlton.gtInstanc().方法()2android中的Singlton

软键盘管理的InputMthodManagr

源码(以下的源码都是5.1的):

publicfinalclassInputMthodManagr{//.........staticInputMthodManagrsInstanc;//.........publicstaticInputMthodManagrgtInstanc(){synchronizd(InputMthodManagr.class){if(sInstanc==null){IBindrb=SrvicManagr.gtSrvic(Contxt.INPUT_METHOD_SERVICE);IInputMthodManagrsrvic=IInputMthodManagr.Stub.asIntrfac(b);sInstanc=nwInputMthodManagr(srvic,Loopr.gtMainLoopr());}rturnsInstanc;}}

使用的是第二种同步代码块的单例模式(可能涉及到多线程),类似的还有AccssibilityManagr(Viw获得点击、焦点、文字改变等事件的分发管理,对整个系统的调试、问题定位等)

BlutoothOppManagr等。

当然也有同步方法的单例实现,比如:CalndarDatabasHlpr

publicstaticsynchronizdCalndarDatabasHlprgtInstanc(Contxtcontxt){if(sSinglton==null){sSinglton=nwCalndarDatabasHlpr(contxt);}rturnsSinglton;}

注意Application并不算是单例模式

publicclassApplicationxtndsContxtWrapprimplmntsComponntCallbacks{publicApplication(){supr(null);}}

在Application源码中,其构造方法是公有的,意味着可以生出多个Application实例,但为什么Application能实现一个app只存在一个实例呢?请看下面:

在ContxtWrappr源码中:

publicclassContxtWrapprxtndsContxt{ContxtmBas;publicContxtWrappr(Contxtbas){mBas=bas;}protctdvoidattachBasContxt(Contxtbas){if(mBas!=null){thrownwIllgalStatExcption(Bascontxtalradyst);}mBas=bas;}

ContxtWrappr构造函数传入的bas为null,就算有多个Application实例,但是没有通过attach()绑定相关信息,没有上下文环境,三个字。

然并卵

2.Factory(工厂模式)

 定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。对同一个接口的实现类进行管理和实例化创建

假设我们有这样一个需求:

动物Animal,它有行为mov()。有两个实现类cat和dog。为了统一管理和创建我们设计一个工厂模式。

同时两个子类有各自的行为,Cat有atFish(),Dog有atBon().

结构图:

Animal接口:

13intrfacanimal{voidmov();}

Cat类:

publicclassCatimplmntsAnimal{

Ovrridpublicvoidmov(){//TODOAuto-gnratdmthodstubSystm.out.println(我是只肥猫,不爱动);}publicvoidatFish(){Systm.out.println(爱吃鱼);}}

Dog类:

publicclassDogimplmntsAnimal{

Ovrridpublicvoidmov(){//TODOAuto-gnratdmthodstubSystm.out.println(我是狗,跑的快);}publicvoidatBon(){Systm.out.println(爱吃骨头);}}

那么现在就可以建一个工厂类(Factory.java)来对实例类进行管理和创建了.

publicclassFactory{//静态工厂方法//多处调用,不需要实例工厂类publicstaticCatproducCat(){rturnnwCat();}publicstaticDogproducDog(){rturnnwDog();}//当然也可以一个方法,通过传入参数,switch实现}

使用:

Animalcat=Factory.producCat();cat.mov();//-----------------------------Dogdog=Factory.producDog();dog.mov();dog.atBon();

工厂模式在业界运用十分广泛,如果都用nw来生成对象,随着项目的扩展,animal还可以生出许多其他儿子来,当然儿子还有儿子,同时也避免不了对以前代码的修改(比如加入后来生出儿子的实例),怎么管理,想着就是一团糟。

1Animalcat=Factory.producCat();

这里实例化了Animal但不涉及到Animal的具体子类(减少了它们之间的偶合联系性),达到封装效果,也就减少错误修改的机会。

Java面向对象的原则,封装(Encapsulation)和分派(Dlgation)告诉我们:具体事情做得越多,越容易范错误,

一般来说,这样的普通工厂就可以满足基本需求。但是我们如果要新增一个Animal的实现类panda,那么必然要在工厂类里新增了一个生产panda的方法。就违背了闭包的设计原则(对扩展要开放对修改要关闭),于是有了抽象工厂模式。

2.1AbstractFactory(抽象工厂)

抽象工厂模式提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。

啥意思?就是把生产抽象成一个接口,每个实例类都对应一个工厂类(普通工厂只有一个工厂类),同时所有工厂类都继承这个生产接口。

生产接口Providr:

13intrfacProvidr{Animalproduc();}

每个产品都有自己的工厂

CatFactory:

78publicclassCatFactoryimplmntsProvidr{

OvrridpublicAnimalproduc(){//TODOAuto-gnratdmthodstubrturnnwCat();}}

DogFactory:

78publicclassDogFactoryimplmntsProvidr{

OvrridpublicAnimalproduc(){//TODOAuto-gnratdmthodstubrturnnwDog();}}

产品生产:

13Providrprovidr=nwCatFactory();Animalcat=providr.produc();cat.mov();

现在我们要加入panda,直接新建一个pandaFactory就行了,这样我们系统就非常灵活,具备了动态扩展功能。









































白癜风有什么特效药
治疗白癜风有什么方法



转载请注明:http://www.gslnbdf.com/azxt/1303.html

  • 上一篇文章:
  •   
  • 下一篇文章: