Design Principles

Design principles provide high level guidelines to design better software applications. They do not provide implementation guidelines and are not bound to any programming language.

前言

    设计原则为设计更好的软件应用提供更高层次的指导。设计模式原则,其实就是程序员在编写程序时应当遵循的原则,也是各种程序设计模式的基础。在网上收集一些资料,在这里总结一下,以后忘了还可以来这里参考一下。也给大伙一个参考。

单一职责原则(Single Responsibility Principle)

    一个类,只有一个引起它变化的原因。应该只有一个职责。每一个职责都是变化的一个轴线,如果一个类有一个以上的职责,这些职责就耦合在了一起。这会导致脆弱的设计。当一个职责发生变化时,可能会影响其它的职责。另外,多个职责耦合在一起,会影响复用性。例如:要实现逻辑和界面的分离。

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
/**
* @Auther: Arsenal
* @Date: 2020-03-05 21:09
* @Description: 单一职责原则
*/
public class SingleResponsibility {
public static void main(String[] args) {
Vehicle vehicle = new Vehicle();
vehicle.roadRun("汽车");
vehicle.airRun("飞机");
vehicle.waterRun("邮轮");
}
}

class Vehicle {
public void roadRun(String vehicleName) {
System.out.println(vehicleName + "在公路上跑。");
}

public void airRun(String vehicleName) {
System.out.println(vehicleName + "在天空飞行。");
}

public void waterRun(String vehicleName) {
System.out.println(vehicleName + "在水中运行。");
}
}

接口隔离原则(Interface Segregation Principle)

    从一个客户类的角度来讲,一个类对另一个类的依赖性应当是建立在最小的接口上。将接口理解为一个类所提供的所有方法的特征集合,是一种在逻辑上存在的概念。

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
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
/**
* @Auther: Arsenal
* @Date: 2020-03-05 21:57
* @Description: 接口隔离原则
*/
public class Segregation {
public static void main(String[] args) {
A a = new A();
a.dependency1(new B());
a.dependency2(new B());
a.dependency3(new B());
System.out.println("================================");
C c = new C();
c.dependency1(new D());
c.dependency4(new D());
c.dependency5(new D());
}
}

interface interface1 {
void operation1();
}

interface interface2 {

void operation2();

void operation3();

}

interface interface3 {

void operation4();

void operation5();
}

class B implements interface1, interface2 {

@Override
public void operation1() {
System.out.println("B 实现 interface1 的 operation1");
}

@Override
public void operation2() {
System.out.println("B 实现 interface1 的 operation2");
}

@Override
public void operation3() {
System.out.println("B 实现 interface1 的 operation3");
}
}

class D implements interface1, interface3 {

@Override
public void operation1() {
System.out.println("D 实现 interface1 的 operation1");
}

@Override
public void operation4() {
System.out.println("D 实现 interface1 的 operation4");
}

@Override
public void operation5() {
System.out.println("D 实现 interface1 的 operation5");
}
}

class A {
public void dependency1(interface1 interface1) {
interface1.operation1();
}

public void dependency2(interface2 interface2) {
interface2.operation2();
}

public void dependency3(interface2 interface2) {
interface2.operation3();
}
}


class C {
public void dependency1(interface1 interface1) {
interface1.operation1();
}

public void dependency4(interface3 interface3) {
interface3.operation4();
}

public void dependency5(interface3 interface3) {
interface3.operation5();
}
}

依赖倒置原则(Dependence Inversion Principle)

    程序要依赖于抽象接口,不要依赖于具体实现。简单的说就是要求对抽象进行编程,不要对实现进行编程,这样就降低了客户与实现模块间的耦合。

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
35
36
/**
* @Auther: Arsenal
* @Date: 2020-03-06 21:09
* @Description: 依赖倒置原则
*/
public class DependencyInversion {
public static void main(String[] args) {
Person person = new Person();
person.message(new Mail());
person.message(new WeChat());
}
}

interface Ireceive {
void getInfo();
}

class Mail implements Ireceive {
@Override
public void getInfo() {
System.out.println("邮件接收消息");
}
}

class WeChat implements Ireceive {
@Override
public void getInfo() {
System.out.println("微信接收消息");
}
}

class Person {
void message(Ireceive receive) {
receive.getInfo();
}
}

里氏替换原则(Liskov Substitution Principle)

    主张使用“抽象(Abstraction)”和“多态(Polymorphism)”将设计中的静态结构改为动态结构,维持设计的封闭性。“抽象”是语言提供的功能。“多态”由继承语义实现。

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
35
36
37
38
39
40
41
42
43
44
/**
* @Auther: Arsenal
* @Date: 2020-03-06 21:09
* @Description: 里氏替换原则
*/
public class LiskovSubstitution {
public static void main(String[] args) {
AA a = new AA();
System.out.println("11-3=" + a.func1(11, 3));
System.out.println("1-8=" + a.func1(1, 8));
System.out.println("=========");
BB b = new BB();
System.out.println("11+3=" + b.func1(11, 3));
System.out.println("1+8=" + b.func1(1, 8));
System.out.println("11+3+9=" + b.func2(11, 3));
}
}

// 基类
class BaseL {
}

class AA extends BaseL {
int func1(int num1, int num2) {
return num1 - num2;
}
}

class BB extends BaseL {

AA a = new AA();

int func1(int num1, int num2) {
return num1 + num2;
}

int func2(int num1, int num2) {
return func1(num1, num2) + 9;
}

int func3(int num1, int num2) {
return a.func1(num1, num2);
}
}

开闭原则(Open Closed Principle)

    开闭原则规定“软件中的对象(类,模块,函数等等)应该对于扩展是开放的,但是对于修改是封闭的”,这意味着一个实体是允许在不改变它的源代码的前提下变更它的行为。该特性在产品化的环境中是特别有价值的,在这种环境中,改变源代码需要代码审查,单元测试以及诸如此类的用以确保产品使用质量的过程。遵循这种原则的代码在扩展时并不发生改变,因此无需上述的过程。

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
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
/**
* @Auther: Arsenal
* @Date: 2020-03-06 21:09
* @Description: 开闭原则
*/
public class OpenClosePrinciple {
public static void main(String[] args) {
GraphicEditor graphicEditor = new GraphicEditor();
graphicEditor.drawShape(new Rectangle());
graphicEditor.drawShape(new Circle());
graphicEditor.drawShape(new Triangle());
}
}

class GraphicEditor {
void drawShape(Shape shape) {
shape.draw();
}
}

abstract class Shape {
int m_type;

abstract void draw();
}

class Rectangle extends Shape {
Rectangle() {
super.m_type = 1;
}

@Override
void draw() {
System.out.println("画矩形");
}
}

class Circle extends Shape {
Circle() {
super.m_type = 2;
}

@Override
void draw() {
System.out.println("画三角形");
}
}

class Triangle extends Shape {
Triangle() {
super.m_type = 3;
}

@Override
void draw() {
System.out.println("画圆形");
}
}

迪米特法则(Law of Demeter)

    迪米特法则(Law of Demeter)又叫作最少知识原则(Least Knowledge Principle 简写LKP),一个类对于其他类知道的越少越好,就是说一个对象应当对其他对象有尽可能少的了解,只和朋友通信,不和陌生人说话。

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
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
/**
* @Auther: Arsenal
* @Date: 2020-03-06 21:09
* @Description: 迪米特法则
*/
public class Demeter {

public static void main(String[] args) {
System.out.println("~~~使用迪米特法则的改进~~~");
// 创建了一个 SchoolManager 对象
SchoolManager schoolManager = new SchoolManager();
// 输出学院的员工id 和 学校总部的员工信息
schoolManager.printAllEmployee(new CollegeManager());
}
}

// 学校总部员工类
class Employee {
private String id;

public void setId(String id) {
this.id = id;
}

public String getId() {
return id;
}
}

// 学院的员工类
class CollegeEmployee {
private String id;

public void setId(String id) {
this.id = id;
}

public String getId() {
return id;
}
}

// 管理学院员工的管理类
class CollegeManager {
// 返回学院的所有员工
public List<CollegeEmployee> getAllEmployee() {
List<CollegeEmployee> list = new ArrayList<CollegeEmployee>();
for (int i = 0; i < 10; i++) { // 这里我们增加了10个员工到 list
CollegeEmployee emp = new CollegeEmployee();
emp.setId("学院员工id= " + i);
list.add(emp);
}
return list;
}

// 输出学院员工的信息
public void printEmployee() {
// 获取到学院员工
List<CollegeEmployee> list1 = getAllEmployee();
System.out.println("------------学院员工------------");
for (CollegeEmployee e : list1) {
System.out.println(e.getId());
}
}
}

// 学校管理类

// 分析 SchoolManager 类的直接朋友类有哪些 Employee、CollegeManager
// CollegeEmployee 不是 直接朋友 而是一个陌生类,这样违背了 迪米特法则
class SchoolManager {
// 返回学校总部的员工
public List<Employee> getAllEmployee() {
List<Employee> list = new ArrayList<Employee>();

for (int i = 0; i < 5; i++) { // 这里我们增加了5个员工到 list
Employee emp = new Employee();
emp.setId("学校总部员工id= " + i);
list.add(emp);
}
return list;
}

// 该方法完成输出学校总部和学院员工信息(id)
void printAllEmployee(CollegeManager sub) {

// 分析问题
// 1. 将输出学院的员工方法,封装到CollegeManager
sub.printEmployee();

// 获取到学校总部员工
List<Employee> list2 = this.getAllEmployee();
System.out.println("------------学校总部员工------------");
for (Employee e : list2) {
System.out.println(e.getId());
}
}
}

合成复用原则 (Composite Reuse Principle)

    软件复用时,要尽量先使用组合或者聚合等关联关系来实现,其次才考虑使用继承关系来实现

延伸

    Java七大设计原则
    Java设计六大原则
    尚硅谷Java设计模式,韩顺平图解java设计模式

Content
  1. 1. 前言
  2. 2. 单一职责原则(Single Responsibility Principle)
  3. 3. 接口隔离原则(Interface Segregation Principle)
  4. 4. 依赖倒置原则(Dependence Inversion Principle)
  5. 5. 里氏替换原则(Liskov Substitution Principle)
  6. 6. 开闭原则(Open Closed Principle)
  7. 7. 迪米特法则(Law of Demeter)
  8. 8. 合成复用原则 (Composite Reuse Principle)
  9. 9. 延伸