logo头像
ICQL

designpattern_设计原则

相关源码

https://gitee.com/icql/icql-java/tree/master/designpattern
https://github.com/icql/icql-java/tree/master/designpattern



代码质量

1)可维护性(maintainability)

如果bug容易修复,修改、添加功能能够轻松完成,那我们就可以主观地认为代码对我们来说易维护。相反,则较难维护

2)可读性(readability)

符合编码规范,注释详尽,代码高内聚低耦合

3)可扩展性(extensibility)

在不修改或少量修改原有代码的情况下,通过扩展的方式添加新功能。符合”开闭原则”:对扩展开放,对修改关闭

4)灵活性(flexibility)

代码适用性高,可复用

5)简洁性(simplicity)

KISS 原则:”Keep It Simple,Stupid”

6)可复用性(reusability)

减少重复代码的编写,面向对象的继承、多态存在的目的之一,就是为了提高代码的可复用性

7)可测试性(testability)

比较难写单元测试,说明可测试性不好,代码应边界分离便于测试



面向对象

面向对象编程,面向过程编程,函数式编程(允许函数参数,返回函数)

1)面向对象分析

OOA(Object Oriented Analysis):做什么

2)面向对象设计

OOD(Object Oriented Design):怎么做

3)面向对象编程

OOP(Object Oriented Programming):将分析和设计翻译成代码

4)四大特性(封装、抽象、继承、多态)

(1)封装(Encapsulation)

封装也叫作信息隐藏或者数据访问保护
类通过暴露有限的访问接口,授权外部仅能通过类提供的方式(或者叫方法)来访问内部信息或者数据
对提供者来说,保护数据隐藏信息;对调用方来说,不需要了解内部的逻辑,只需要访问公开的接口,提高易用性

(2)抽象(Abstraction)

让调用着只要关心提供了哪些功能,而不需要知道实现细节
java提供了接口和抽象类语法特性,方法本身也是一种抽象,调用者只需要通过方法名注释文档了解其功能就可以直接使用
基于接口而非实现编程,开闭原则,代码解耦

(3)继承(Inheritance)

表示is-a的关系,单继承或多继承,但避免继承层次过深复杂,因此尽量少用或不用

(4)多态(Polymorphism)

多态是指,子类可以替换父类,在实际的代码运行过程中,调用子类的方法实现。
java实现多态有2种:继承、接口

5)面向过程和面向对象的区别

面向对象编程是一种编程范式或编程风格,它以类或对象作为组织代码的基本单元,并将封装、抽象、继承、多态四个特性,作为代码设计和实现的基石

面向过程编程也是一种编程范式或编程风格,它以过程(可以为理解方法、函数、操作)作为组织代码的基本单元,以数据(可以理解为成员变量、属性)与方法相分离为最主要的特点

面向对象开发中常见的面向过程风格:滥用 getter、setter 方法;Constants 类、Utils 类等静态方法的设计问题;基于贫血模型的开发模式

6)接口和抽象类

表示is-a关系,使用抽象类,是对成员变量和方法的抽象,解决代码复用问题

表示has-a关系,使用接口,表示具有某一组行为特性,用于隔离接口和具体实现,解耦代码,提高扩展性

基于接口而非实现编程

多用组合少用继承。若继承层次过深或者关系不稳定优先使用组合,从理论上讲,通过组合、接口、委托三个技术手段,我们完全可以替换掉继承

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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(); // 委托
}
}

没有权限修改一个外部类时,可以使用继承重写原来的方法

7)贫血模型和充血模型

基于贫血模型的 MVC 分层架构:M 表示 Model(模型,数据层),V 表示 View(视图,展示层),C 表示 Controller(控制,逻辑层)

基于充血模型的 DDD 分层架构

8)类之间的关系(6种)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
//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 类对象有任何使用关系,我们都称它们有依赖关系。



设计原则

1)SOLID原则

(1)单一职责原则(Single Responsibility Principle,SRP)

不要设计大而全的类,要合理地设计粒度相对较小、功能单一的模块/类,取舍要有度

(2)开闭原则(Open Closed Principle,OCP)

对扩展开放、对修改关闭。也就是尽可能的做到,添加一个新的功能应该是,在已有代码基础上扩展代码而非修改原有代码逻辑

(3)里式替换原则(Liskov Substitution Principle,LSP)

子类对象能够替换程序中父类对象出现的任何地方,并且保证原来程序的逻辑行为不变及正确性不被破坏

(4)接口隔离原则(Interface Segregation Principle,ISP)

客户端不应该强迫依赖它不需要的接口

(5)依赖倒置原则(Dependency Inversion Principle,DIP)

高层模块不依赖低层模块,它们共同依赖同一个抽象。抽象不要依赖具体实现细节,具体实现细节依赖抽象。

控制反转(Inversion Of Control,IOC):设计思想,对程序执行流程的控制由原来的编码人员 “反转” 给了框架

依赖注入(Dependency Injection,DI):编码技巧,不通过 new 在类内部创建依赖的对象,将依赖的对象在类的外部创建好之后,通过构造函数,方法参数等方式 传递/注入 给类来使用

2)KISS原则

Keep It Simple and Stupid,尽量保持简单

3)YAGNI原则

You Ain’t Gonna Need It,你不会需要它。不要去编写当前用不到的代码,不要做过度设计

4)DRY原则

Don’t Repeat Yourself,不要写重复的代码

5)LOD原则

Law of Demeter,迪米特法则(最小知识原则),高内聚,低耦合,不该有直接依赖关系的类之间,不要有依赖;有依赖关系的类之间,尽量只依赖必要的接口

设计模式

总览图

微信打赏

赞赏是不耍流氓的鼓励