从android代码中来记忆23种设计模式,一、写在最前:设计模式六大原则

在android中咱们常提起的设计模式大约有23种,利用好设计模式可以帮助咱们很好的构建代码结构,也便于咱们之后的维护。每次看完,看的时候总以为很明白,可是过一段时间之后都会忘记,或只记得一些片断,又或到真正使用起来的时候才会发现一系列的问题。本系列笔记会从头记录这23种设计模式,固然必定会有不正确的地方。java

本系列笔记参考了《设计模式之禅》、《Android源码设计模式解析与实战》以及huachao1001的从Android代码中来记忆23种设计模式一文。android

开始以前

在全部的设计模式以前都会先将面向对象的六大原则,大部分同窗都已经很明白了,因此在这里也想记录一些不同的东西。web

单一职责原则(SRP)

一个类所承担的功能或指责必须是同一类或者相近的,不要让一个类承担过多的职责。换一句话说,一个类的职责应该单一。可是在咱们的使用过程当中,在大部分应用中很难作到真正意义上的指责单一,因此对于单一职责原则我是这么理解的: 设计模式

接口的职责必须单一。

类的设计尽可能作到只有一个缘由引发类的变化,指的是设计类而不是实现类,实现类作到单一职责的话无形中会增长不少类,会使本来简单的事情变得更加复杂。

开闭原则(OCP)

一个软件实体应该对扩展开发,对修改关闭。其含义是说一个软件实体应该经过扩展实现变化,而不是经过修改内部已有的代码来实现变化。svg

软件实体是什么?

- 项目或软件产品中按照必定逻辑划分的模块

- 抽象和类

- 方法编码

开闭原则指导咱们,当软件须要变化时应”尽可能经过”扩展的方式来修改,而不是经过变化已有代码来实现,这里说的是尽可能,并非绝对不能够修改原始类,当咱们嗅到“腐化”气味时应尽可能早重构。而不是经过继承等方式添加新的实现,这会致使类的膨胀及历史代码的遗留。spa

一般咱们能够用接口或抽象类来约束一组可变化的行为。主要包含3个层次:.net

第一:经过接口或抽象类约束扩展,对扩展边界定义,不容许实现类出现接口或抽象类之外的public 方法。

第二:参数类型、引用变量尽可能使用接口或抽象对类,而不是实现类。

第三:抽象层尽可能保持稳定。

固然在实际应用过程当中,每每修改源代码和扩展是同时存在的。设计

里氏替换原则(LSP)

有两种解释方法,有一种特别麻烦、特别绕的就再也不说了。

- 全部引用基类的地方必须能透明地使用其子类对象。 code

依然比较绕,通俗一点解释是这样的:只要任何有父类出现的地方(如形参),均可以替换为子类,并且替换为子类也不会产生异常和错误。对于使用者(方法)自己不须要关心究竟是父类仍是子类。

可是,有子类出现的地方,替换为父类就不必定能够了。

举个例子:

//窗口类

public class Window(){

public void show(View child){

child.draw();

}

}

public abstract class View(){

public abstract void draw();

public void measure(int widht,int height){

//测量视图大小

}

}

public class Button extends View{

public void draw(){

//绘制按钮

}

}

public class TextView extends View{

public void draw(){

//绘制文本

}

}

里氏替换原则为良好的继承定义了一个规范:

- 一、子类必须彻底实现父类的方法。咱们在作系统设计的时候常常定义一个接口或抽象类,而后编码实现,调用类直接传入接口或抽象类,其实这里已经使用了里氏原则。

> 若是子类不能全实现父类的方法,或者父类的某些方法在子类中已经发生畸变,建议断开继承关系,采用依赖、聚合、组合等关系代替。

二、子类有本身的个性。即有子类出现的地方,父类未必能够。

三、覆盖或实子类重载父类的方法时,传入的参数必须比父类更宽松(相同或范围大)。(不然会出现原本虚调用父类方法的地方调用了子类的方法)

四、覆盖或实子类重载父类的方法时,返回的结果必须范围更小(和父类类型相同或是父类返回类型的子类)。

依赖倒置原则(DIP)

依赖倒置主要是实现解耦,使得高层次的模块不依赖于低层次模块的具体实现细节。怎么去理解它呢,咱们须要知道几个关键点:

(1)高层模块不该该依赖底层模块(具体实现),两者都应该依赖其抽象(抽象类或接口)。模块之间的依赖经过抽象产生,实现类之间不发生直接依赖关系,依赖关系经过接口或抽象类产生。

高层模块就是调用端,底层模块就是具体实现类。

(2)抽象不该该依赖细节(废话,抽象类跟接口确定不依赖具体的实现了)

(3)细节应该依赖于抽象(一样废话,具体实现类确定要依赖其继承的抽象类或接口)

在咱们用的Java语言中,抽象就是指接口或者抽象类,两者都是不能直接被实例化;细节就是实现类,实现接口或者继承抽象类而产生的类,就是细节。使用Java语言描述就简单了:就是各个模块之间相互传递的参数声明为抽象类型,而不是声明为具体的实现类;

依赖致使的本质是经过抽象使各个类或者模块的实现彼此独立,不相互影响,实现模块间的松耦合。

每一个类(底层模块)尽可能有接口和抽象类,或者接口抽象类两者皆有。

变量的声明尽可能是抽象或者接口

尽可能不覆盖父类的方法

里氏替换原则

一个例子:

母亲给孩子讲故事,只要给她一本书,她就能够照着书给孩子讲故事了。代码以下:

class Book{

public String getContent(){

return "好久好久之前有一个阿拉伯的故事……";

}

}

class Mother{

public void narrate(Book book){

System.out.println("妈妈开始讲故事");

System.out.println(book.getContent());

}

}

public class Client{

public static void main(String[] args){

Mother mother = new Mother();

mother.narrate(new Book());

}

}

运行结果:妈妈开始讲故事 好久好久之前有一个阿拉伯的故事……

运行良好,假若有一天,需求变成这样:不是给书而是给一份报纸,让这位母亲讲一下报纸上的故事,报纸的代码以下:

class Newspaper{

public String getContent(){

return "林书豪38+7领导尼克斯击败湖人……";

}

}

这位母亲却办不到,由于她竟然不会读报纸上的故事,这太荒唐了,只是将书换成报纸,竟然必需要修改Mother才能读。假如之后需求换成杂志呢?换成网页呢?还要不断地修改Mother,这显然不是好的设计。缘由就是Mother与Book之间的耦合性过高了,必须下降他们之间的耦合度才行。

咱们引入一个抽象的接口IReader。读物,只要是带字的都属于读物:

interface IReader{

public String getContent();

}

Mother类与接口IReader发生依赖关系,而Book和Newspaper都属于读物的范畴,他们各自都去实现IReader接口,这样就符合依赖倒置原则了,代码修改成:

class Newspaper implements IReader {

public String getContent(){

return "林书豪17+9助尼克斯击败老鹰……";

}

}

class Book implements IReader{

public String getContent(){

return "好久好久之前有一个阿拉伯的故事……";

}

}

class Mother{

public void narrate(IReader reader){

System.out.println("妈妈开始讲故事");

System.out.println(reader.getContent());

}

}

public class Client{

public static void main(String[] args){

Mother mother = new Mother();

mother.narrate(new Book());

mother.narrate(new Newspaper());

}

}

这样修改后,不管之后怎样扩展Client类,都不须要再修改Mother类了。这只是一个简单的例子,实际状况中,表明高层模块的Mother类将负责完成主要的业务逻辑,一旦须要对它进行修改,引入错误的风险极大。因此遵循依赖倒置原则能够下降类之间的耦合性,提升系统的稳定性,下降修改程序形成的风险。

依赖倒置原则在Java中的表现就是:模块间经过抽象发生,实现类之间不发生直接依赖关系,其依赖关系是经过接口或者抽象类产生的。若是类与类直接依赖细节,那么就会直接耦合,那么当修改时,就会同时修改依赖者代码,这样限制了可扩展性。

接口隔离原则(ISP)

关于接口有一点要说明:类也是接口

有两种定义方法:一种为类不该该依赖它不须要的接口;另外一种为类之间的依赖关系应该创建在最小的接口上。接口隔离的原则是将很是庞大、臃肿的接口分割成更小更具体的接口。

有的时候会感受单一职责和接口隔离隔离原则很像,单一职责更关注的是功能的单一,是业务层次上的划分。而接口隔离原则更关心的是接口的数量要少。

好比说一个接口有一组10个功能,提供给若干个模块使用,每一个模块按照按照不一样的权限只能使用接口中的一部分功能。按照单一职责原则是容许的,可是按照接口隔离原则是不容许的,接口隔离原则要求:”尽可能使用多个专用接口”,意思为有几个模块就提供几个接口,而不是创建一个庞大的接口供全部模块使用。

接口设计时有限度的,固然也不要分了隔离接口而将所有接口都细化,这样就变为过分设计了

最佳实践:

- 一个接口只服务于一个模块或业务流程

- 压缩接口对外提供的public方法

迪米特原则(LOD)

一个对象应该对一个被调用的类(被耦合)有最少的了解。调用者只须要知道它须要调用的方法便可。类与类之间的关系越密切,当一个类发生改变时,对另外一个类影响也越大。

迪米特原则包含的四层含义:

- 只和朋友交流:每一个类必然会和其余类有耦合关系,两个对象间的耦合就成为朋友关系(聚合、组合、依赖等)。朋友类得定义是这样的:出如今成员变量、方法的输入、输出参数中的称为成员朋友类,而出如今方法体内部的类不属于朋友类。

- 朋友之间也是有距离的:不要对外公布太多的public方法和非静态的public变量,尽可能内敛。

迪米特原则的核心观念是:解耦。即:高内聚、低耦合。

最后

单一职责原则 (SRP)

开闭原则 (OCP)

里氏替换原则 (LSP)

迪米特原则 (LOD)

接口隔离原则 (ISP)

依赖倒置原则 (DIP)

至此设计模式的6大基础原则几经所有介绍完毕,将6大原则的首字母组合起来,就是SOLID(稳定的)。

不是说按照必定的设计模式来设计程序就能应对各类场景,或不对代码结构作任何修改。只是咱们在进行程序设计的时候尽可能遵循这6大原则。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值