- Published on
设计模式原则与思考
00丨面向对象
面向对象中的继承、多态能让我们写出可复用的代码;编码规范能让我们写出可读性好的代码;设计原则中的单一职责、DRY、基于接口而非实现、里式替换原则等,可以让我们写出可复用、灵活、可读性好、易扩展、易维护的代码;设 计模式可以让我们写出易扩展的代码;持续重构可以时刻保持代码的可维护性等等。具体这些编程方法论是如何提高代码的可维护性、可读性、可扩展性等等。
01丨设计模式学习导读
设计原则:
- SOLID 原则 -SRP 单一职责原则
- SOLID 原则 -OCP 开闭原则
- SOLID 原则 -LSP 里式替换原则
- SOLID 原则 -ISP 接口隔离原则
- SOLID 原则 -DIP 依赖倒置原则
- DRY 原则、KISS 原则、YAGNI 原则、LOD 法则
设计模式的分类:
创建型 常用的有:单例模式、工厂模式(工厂方法和抽象工厂)、建造者模式。 不常用的有:原型模式。 结构型 常用的有:代理模式、桥接模式、装饰者模式、适配器模式。 不常用的有:门面模式、组合模式、享元模式。 行为型 常用的有:观察者模式、模板模式、策略模式、职责链模式、迭代器模式、状态模式。 不常用的有:访问者模式、备忘录模式、命令模式、解释器模式、中介模式。
代码的重构:
●重构的目的(why)、对象(what)、时机(when)、方法(how); ● 保证重构不出错的技术手段∶单元测试和代码的可测试性; ●两种不同规模的重构∶大重构(大规模高层次)和小重构(小规模低层次)。
二,设计原则与思想:面向对象
02丨理论一:当谈论面向对象的时候,我们到底在谈论什么
- 面向对象编程是一种编程范式或编程风格。它以类或对象作为组织代码的基本单元,并将封装、抽象、继承、多态四个特性,作为代码设计和实现的基石 。
- 面向对象编程语言是支持类或对象的语法机制,并有现成的语法机制,能方便地实现面向对象编程四大特性(封装、抽象、继承、多态)的编程语言。
03丨理论二:封装、抽象、继承、多态分别可以解决哪些编程问题
封装(Encapsulation)
如果我们对类中属性的访问不做限制,那任何代码都可以访问、修改类中的属性,虽然这样看起来更加灵活,但从另一方面来说,过度灵活也意味着不可控,属性可以随意被以各种奇葩的方式修改,而且修改逻辑可能散落在代码中的各个角落,势必影响代码的可读性、可维护性。比如某个同事在不了解业务逻辑的情况下,在某段代码中“偷偷地”重设了 wallet 中的balanceLastModifiedTime 属性,这就会导致balance 和balanceLastModifiedTime 两个数据不一致。 除此之外,类仅仅通过有限的方法暴露必要的操作,也能提高类的易用性。如果我们把类属性都暴露给类的调用者,调用者想要正确地操作这些属性,就势必要对业务细节有足够的了解。而这对于调用者来说也是一种负担。相反,如果我们将属性封装起来,暴露少许的几个必要的方 法给调用者使用,调用者就不需要了解太多背后的业务细节,用错的概率就减少很多。这就好比,如果一个冰箱有很多按钮,你就要研究很长时间,还不一定能操作正确。相反,如果只有几个必要的按钮,比如开、停、调节温度,你一眼就能知道该如何来操作,而且操作出错的概率也会降低很多。
抽象(Abstraction)
实际上,如果上升一个思考层面的话,抽象及其前面讲到的封装都是人类处理复杂性的有效手段。在面对复杂系统的时候,人脑能承受的信息复杂程度是有限的,所以我们必须忽略掉一些非关键性的实现细节。而抽象作为一种只关注功能点不关注实现的设计思路,正好帮我们的大脑过滤掉许多非必要的信息。
除此之外,抽象作为一个非常宽泛的设计思想,在代码设计中,起到非常重要的指导作用。很多设计原则都体现了抽象这种设计思想,比如基于接口而非实现编程、开闭原则(对扩展开放、对修改关闭)、代码解耦(降低代码的耦合性)等。我们在讲到后面的内容的时候, 会具体来解释。
换一个角度来考虑,我们在定义(或者叫命名)类的方法的时候,也要有抽象思维,不要在方法定义中,暴露太多的实现细节,以保证在某个时间点需要改变方法的实现逻辑的时候, 不用去修改其定义。举个简单例子,比如 getAliyunPictureUrl() 就不是一个具有抽象思维的命名,因为某一天如果我们不再把图片存储在阿里云上,而是存储在私有云上,那这个命名也要随之被修改。相反,如果我们定义一个比较抽象的函数,比如叫作 getPictureUrl(),那即便内部存储方式修改了,我们也不需要修改命名。
多态(Polymorphism)
学习完了封装、抽象、继 承之后,我们再来看面向对象编程的最后一个特性,多态。多态是指,子类可以替换父类,在实际的代码运行过程中,调用子类的方法实现。对于多态这种特性,多态特性能提高代码的可扩展性和复用性。
07丨理论四:哪些代码设计看似是面向对象,实际是面向过程的?
- 滥用 getter、setter 方法
- Constants 类、Utils 类的设计问题
- 基于贫血模型的开发模式
08丨理论五:接口vs抽象类的区别?如何用普通的类模拟抽象类和接口?
如何决定该用抽象类还是接口? 实际上,判断的标准很简单。如果我们要表示一种 is-a 的关系,并且是为了解决代码复用的问题,我们就用抽象类;如果我们要表示□一种 has-a 关系,并且是为了解决抽象而非代码复用的问题,那我们就可以使用接口。 从类的继承层次上来看,抽象类是一种自下而上的设计思路,先有子类的代码重复,然后再抽象成上层的父类(也就是抽象类)。而接口正好相反,它是一种自上而下的设计思路。我们在编程的时候,一般都是先设计接口,再去考虑具体的实现。