设计模式之美
2019-12-18 09:44:25 0 举报
AI智能生成
设计模式总结
作者其他创作
大纲/内容
设计原则与思想
面向对象
什么是面向对象
面向对象的特性
封装
封装也叫作信息隐藏或者数据访问保护。
类通过暴露有限的访问接口,授权外部仅能通过类提供的方式(或者叫函数)来访问内部信息或者数据
类通过暴露有限的访问接口,授权外部仅能通过类提供的方式(或者叫函数)来访问内部信息或者数据
主要讲的是如何隐藏信息、保护数据
意义
访问受限,保证数据的一致性
提高类的易用性
将属性封装起来,暴露少许的几个必要的方法给调用者使用,
调用者就不需要了解太多背后的业务细节,用错的概率就减少很多
调用者就不需要了解太多背后的业务细节,用错的概率就减少很多
语法支持
private、protected、public
抽象
讲的是如何隐藏方法的具体实现,让调用者只需要关心方法提供了哪些功能,并不需要知道这些功能是如何实现的
语法支持
接口类、抽象类、函数(方法)
意义
只关注功能点不关注实现的设计思路
根据一些抽象性的设计原则指导设计,开闭、单一等
方法名、类名定义
继承
是用来表示类之间的 is-a 关系
语法支持
extends
意义
代码复用
重用父类的属性和方法
可以通过抽象类,实现多态特性
反应真是从属关系
多态
多态是指,子类可以替换父类,在实际的代码运行过程中,调用子类的方法实现
语法机制
编程语言要支持父类对象可以引用子类对象
编程语言要支持继承
编程语言要支持子类可以重写(override)父类中的方法
实现方法
继承加子类重写
接口类
静态语言-java
有传参限制,而动态类型的没有
利用 duck-typing 语法。
动态语言-python
只要两个类具有相同的方法,就可以实现多态,并不要求两个类之间有任何关系,这就是所谓的 duck-typing
意义
多态特性能提高代码的可扩展性和复用性
只需增加新的实现类并实现接口的方法,不需要修改调用时的方法
接口和抽象类的区别
特性
抽象类
抽象类不允许被实例化,只能被继承
抽象类可以包含属性和方法。方法既可以包含代码实现,
也可以不包含代码实现。不包含代码实现的方法叫作抽象方法
也可以不包含代码实现。不包含代码实现的方法叫作抽象方法
子类继承抽象类,必须实现抽象类中的所有抽象方法
接口类
接口不能包含属性(也就是成员变量)。
类实现接口的时候,必须实现接口中声明的所有方法
接口只能声明方法,方法不能包含代码实现。
解决什么问题
抽象类
子类继承抽象类-代码复用
?继承普通类也可以实现代码复用,使用抽象类的必要性
如果父类没有定义子类的方法,是无法使用多态特性(通过父类调用子类的方法)
如果父类定义了子类的方法,为空或者有具体的实现
如果是为空,影响代码可读性
子类可能忘记重写父类的方法,因为不是强制的,抽象类必须重写
父类可以被实例化,这样就可能会调用父类的方法,而不是子类的,容易出错
接口类
抽象类更多的是为了代码复用,而接口就更侧重于解耦。
接口是对行为的一种抽象,相当于一组协议或者契约
接口是对行为的一种抽象,相当于一组协议或者契约
接口实现了约定和实现相分离,可以降低代码间的耦合性,提高代码的可扩展性
什么使用使用
抽象类
为了解决代码复用的问题,是一种自下而上的设计思想
接口
为了解决抽象而非代码复用的问题,是一种自上而下的设计思想
如何正确使用继承和组合
类之间的结构比较稳定,不轻易改变,继承层次比较浅,
比如最多有两层继承关系,继承关系不复杂
比如最多有两层继承关系,继承关系不复杂
继承改写成组合,意味着定义更多的类和接口,增加维护成本
继承可以通过组合、接口、委托三个技术手段
is-a关系可以通过组合和接口的has-a关系类替代
多态可以利用接口来实现
代码复用可以通过委托来实现
当没有权限父类,只能通过继承重写父类的方法
实战
模型
贫血模型
只包含数据不包含业务逻辑的类
比如MVC模式中用到bo,vo,Entity,po等
贫血模型将数据与操作分离,破坏了面向对象的封装性,是一种典型的面向过程的编程风格
充血模型
数据和对应的业务逻辑被封装到同一个类中
满足面向对象的封装特性,是典型的面向对象编程风格
充血模型主要是针对service层的改变
针对domain的处理封装在领域对象中
service层主要起到连接和组合的作用
service主要与repository交互,可以保持领域模型的独立
service负责跨领域模型的业务聚合、以及一些非功能比如幂等、事物、邮件、消息、日志、调用其他rpc接口等
controller和repository还是使用贫血模型
repository层中entity生命周期有限,一般传递到service就被转换成bo
controller层vo作为数据传输对象,不包含相关业务方法
鉴权实战
面向对象分析
面向对象设计
根据需求描述,把其中涉及的功能点,一个一个罗列出来,功能点尽可能要小,每个功能点只负责一件事情
«然后再去看哪些功能点职责相近,操作同样的属性,可否应该归为同一个类
«然后再去看哪些功能点职责相近,操作同样的属性,可否应该归为同一个类
对负责的系统可以先进行模块划分。再罗列功能点
具体分析方法
根据罗列出的功能点看都和哪个相关,可以作为类
识别需求中的名词作为类的属性
识别名词相关的动词,作为类的方法
对上面筛选出的进行筛选
设计原则
单一职责( Single Responsibility Principle,缩写为 SRP)
定义
一个类或者模块只负责完成一个职责或者功能
意义
目的是实现代码高内聚、低耦合,提高代码的复用性、可读性、可维护性
如何判断类的职责是否单一
类中的代码行数、函数或者属性过多,会影响代码的可读性和可维护性,
就需要考虑对类的职责进行更细致的划分,拆成不同职责的类
就需要考虑对类的职责进行更细致的划分,拆成不同职责的类
类依赖的其他类过多,或者依赖类的其他类过多,不符合高内聚、低耦合的设计思想,也要考虑进行拆分。
依赖其他类过多,耦合性增加
依赖其他类过多,耦合性增加
私有方法过多,就要考虑能否将私有方法独立到新的类中,设置为 public 方法,供更多的类使用,从而提高代码的复用性
比较难给类起一个合适名字,很难用一个业务名词概括,或者只能用一些笼统的 Manager、Context
之类的词语来命名,这就说明类的职责定义得可能不够清晰
之类的词语来命名,这就说明类的职责定义得可能不够清晰
类中大量的方法都是集中操作类中的某几个属性,比如,在 UserInfo 中,
如果一半的方法都是在操作 address 信息,那就可以考虑将这几个属性和对应的方法拆分出来
如果一半的方法都是在操作 address 信息,那就可以考虑将这几个属性和对应的方法拆分出来
注意过渡单一化
单一化的目的是实现代码高内聚、低耦合,提高代码的复用性、可读性、可维护性,应该在此前提下进行合理的职责单一化,
不是为了单一化儿单一化,要结合实际的业务场景
不是为了单一化儿单一化,要结合实际的业务场景
拆分的过细会降低代码的内聚性,也会增加维护成本
开闭原则(Open Closed Principle,简写为 OCP)
定义
对扩展开放、对修改封闭
意义
提高可扩展性
如何做到ocp
考虑未来可能的需求变更,
扩展意识、抽象意识、封装意识
里式替换原则
是用来指导,继承关系中子类该如何设计的一个原则
定义:子类对象(object of subtype/derived class)能够替换程序(program)中父类对象(object of base/parent class)出现的任何地方,并且保证原来程序的逻辑行为(behavior)不变及正确性不被破坏。
父类定义了函数的“约定”(或者叫协议),那子类可以改变函数的内部实现逻辑,
但不能改变函数原有的“约定”。这里的约定包括:函数声明要实现的功能;
对输入、输出、异常的约定;甚至包括注释中所罗列的任何特殊说明
但不能改变函数原有的“约定”。这里的约定包括:函数声明要实现的功能;
对输入、输出、异常的约定;甚至包括注释中所罗列的任何特殊说明
类似于接口和实现类的要求
接口隔离原则
设计模式
0 条评论
下一页