https://github.com/icql/icql-java/tree/master/designpattern
如果bug容易修复,修改、添加功能能够轻松完成,那我们就可以主观地认为代码对我们来说易维护。相反,则较难维护
符合编码规范,注释详尽,代码高内聚低耦合
在不修改或少量修改原有代码的情况下,通过扩展的方式添加新功能。符合”开闭原则”:对扩展开放,对修改关闭
代码适用性高,可复用
KISS 原则:”Keep It Simple,Stupid”
减少重复代码的编写,面向对象的继承、多态存在的目的之一,就是为了提高代码的可复用性
比较难写单元测试,说明可测试性不好,代码应边界分离便于测试
面向对象编程,面向过程编程,函数式编程(允许函数参数,返回函数)
OOA(Object Oriented Analysis):做什么
OOD(Object Oriented Design):怎么做
OOP(Object Oriented Programming):将分析和设计翻译成代码
封装也叫作信息隐藏或者数据访问保护 类通过暴露有限的访问接口,授权外部仅能通过类提供的方式(或者叫方法)来访问内部信息或者数据 对提供者来说,保护数据隐藏信息;对调用方来说,不需要了解内部的逻辑,只需要访问公开的接口,提高易用性
让调用着只要关心提供了哪些功能,而不需要知道实现细节 java提供了接口和抽象类语法特性,方法本身也是一种抽象,调用者只需要通过方法名注释文档了解其功能就可以直接使用 基于接口而非实现编程,开闭原则,代码解耦
表示is-a的关系,单继承或多继承,但避免继承层次过深复杂,因此尽量少用或不用
多态是指,子类可以替换父类,在实际的代码运行过程中,调用子类的方法实现。 java实现多态有2种:继承、接口
面向对象编程是一种编程范式或编程风格,它以类或对象作为组织代码的基本单元,并将封装、抽象、继承、多态四个特性,作为代码设计和实现的基石
面向过程编程也是一种编程范式或编程风格,它以过程(可以为理解方法、函数、操作)作为组织代码的基本单元,以数据(可以理解为成员变量、属性)与方法相分离为最主要的特点
面向对象开发中常见的面向过程风格:滥用 getter、setter 方法;Constants 类、Utils 类等静态方法的设计问题;基于贫血模型的开发模式
表示is-a关系,使用抽象类,是对成员变量和方法的抽象,解决代码复用问题
表示has-a关系,使用接口,表示具有某一组行为特性,用于隔离接口和具体实现,解耦代码,提高扩展性
基于接口而非实现编程
多用组合少用继承。若继承层次过深或者关系不稳定优先使用组合,从理论上讲,通过组合、接口、委托三个技术手段,我们完全可以替换掉继承
public interface Flyable {
void fly();
}
public class FlyAbility implements Flyable {
@Override
public void fly() { //... }
}
// 省略 Tweetable/TweetAbility/EggLayable/EggLayAbility
public class Ostrich implements Tweetable, EggLayable {// 鸵鸟
private TweetAbility tweetAbility = new TweetAbility(); // 组合
private EggLayAbility eggLayAbility = new EggLayAbility(); // 组合
//... 省略其他属性和方法...
@Override
public void tweet() {
tweetAbility.tweet(); // 委托
}
@Override
public void layEgg() {
eggLayAbility.layEgg(); // 委托
}
}
没有权限修改一个外部类时,可以使用继承重写原来的方法
基于贫血模型的 MVC 分层架构:M 表示 Model(模型,数据层),V 表示 View(视图,展示层),C 表示 Controller(控制,逻辑层)
基于充血模型的 DDD 分层架构
//1)泛化(Generalization)可以简单理解为继承关系
public class A { ... }
public class B extends A { ... }
//2)实现(Realization)一般是指接口和实现类之间的关系
public interface A {...}
public class B implements A { ... }
//3)聚合(Aggregation)是一种包含关系,A 类对象包含 B 类对象,B 类对象的生命周期可以不依赖 A 类对象的生命周期,
//也就是说可以单独销毁 A 类对象而不影响 B 对象,比如课程与学生之间的关系
public class A {
private B b;
public A(B b) {
this.b = b;
}
}
//4)组合(Composition)也是一种包含关系。A 类对象包含 B 类对象,B 类对象的生命周期跟依赖 A 类对象的生命周期,
//B 类对象不可单独存在,比如鸟与翅膀之间的关系
public class A {
private B b;
public A() {
this.b = new B();
}
}
//5)关联(Association)是一种非常弱的关系,包含聚合、组合两种关系。具体到代码层面,
//如果 B 类对象是 A 类的成员变量,那 B 类和 A 类就是关联关系
//6)依赖(Dependency)是一种比关联关系更加弱的关系,包含关联关系。
//不管是 B 类对象是 A 类对象的成员变量,还是 A 类的方法使用 B 类对象作为参数或者返回值、局部变量,
//只要 B 类对象和 A 类对象有任何使用关系,我们都称它们有依赖关系。
不要设计大而全的类,要合理地设计粒度相对较小、功能单一的模块/类,取舍要有度
对扩展开放、对修改关闭。也就是尽可能的做到,添加一个新的功能应该是,在已有代码基础上扩展代码而非修改原有代码逻辑
子类对象能够替换程序中父类对象出现的任何地方,并且保证原来程序的逻辑行为不变及正确性不被破坏
客户端不应该强迫依赖它不需要的接口
高层模块不依赖低层模块,它们共同依赖同一个抽象。抽象不要依赖具体实现细节,具体实现细节依赖抽象。
控制反转(Inversion Of Control,IOC):设计思想,对程序执行流程的控制由原来的编码人员 “反转” 给了框架
依赖注入(Dependency Injection,DI):编码技巧,不通过 new 在类内部创建依赖的对象,将依赖的对象在类的外部创建好之后,通过构造函数,方法参数等方式 传递/注入 给类来使用
Keep It Simple and Stupid,尽量保持简单
You Ain’t Gonna Need It,你不会需要它。不要去编写当前用不到的代码,不要做过度设计
Don’t Repeat Yourself,不要写重复的代码
Law of Demeter,迪米特法则(最小知识原则),高内聚,低耦合,不该有直接依赖关系的类之间,不要有依赖;有依赖关系的类之间,尽量只依赖必要的接口