相关文章
【合集】Java设计模式
UML图
类的表示方式
+:表示public
-:表示private
#:表示protected
属性的完整表示方式 :可见性 名称 : 类型 [ = 缺省值]
方法的完整表示方式: 可见性 名称(参数列表) [ : 返回类型]
类与类之间关系的表示方式
记忆策略
博主箭头指向记忆策略:A–>B 聚合于、组合于、依赖于、实现于、继承于
聚合是空心,组合是实心,是一种更强烈的聚合关系。
单向关联:实线 + 箭头
自关联:带有箭头且指向自身的实线
双向关联:实线
组合关系:实线 + 实心菱形
聚合关系:实线 + 空心菱形
依赖关系:虚线 + 箭头
继承(泛化)关系:实线 + 空心三角形
实现关系:虚线 + 空心三角形
关联关系
对象之间的一种引用关系,
关联分为单向关联,双向关联,自关联。
单向关联
用一个带箭头的实线表示。
双向关联
用一个不带箭头的直线表示。
双方各自持有对方类型的成员变量,
自关联
用一个带有箭头且指向自身的线表示。
聚合关系
用带空心菱形的实线来表示。
强关联关系,是整体和部分之间的关系。
组合关系
用带实心菱形的实线来表示,菱形指向整体。
表示类之间的整体与部分的关系,但它是一种更强烈的聚合关系。
在组合关系中,整体对象可以控制部分对象的生命周期,一旦整体对象不存在,部分对象也将不存在,部分对象不能脱离整体对象而存在。例如,头和嘴的关系,没有了头,嘴也就不存在了。
依赖关系
使用带箭头的虚线来表示,箭头从使用类指向被依赖的类。
是一种使用关系,它是对象之间耦合度最弱的一种关联方式,是临时性的关联。
在代码中,某个类的方法通过局部变量、方法的参数或者对静态方法的调用来访问另一个类(被依赖类)中的某些方法来完成一些职责。
继承关系
泛化关系在代码实现时用带空心三角箭头的实线来表示,箭头从子类指向父类。使用面向对象的继承机制来实现泛化关系。
对象之间耦合度最大的一种关系,表示一般与特殊的关系,是父类与子类之间的关系,是一种继承关系。
实现关系
使用带空心三角箭头的虚线来表示,箭头从实现类指向接口。
接口与实现类之间的关系。
开闭原则
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
|
/**
* 开闭原则 (OCP):开闭原则由Bertrand Meyer提出,其核心思想是软件实体应该对扩展开放,对修改关闭。
* 这意味着在不修改现有代码的基础上,可以通过添加新的代码来扩展程序的功能。实现开闭原则通常依赖于抽象和多态,通过定义接口或抽象类来创建可扩展的架构。
*/
public class A_开闭原则 {
public static void main(String[] args) {
SouGouInput sougouInput = new SouGouInput();
sougouInput.setAbstractSkin(new HeimaSkin());
sougouInput.display();
}
@Setter
public static class SouGouInput {
private AbstractSkin abstractSkin;
public void display() {
abstractSkin.display();
}
}
abstract static class AbstractSkin {
public abstract void display();
}
public static class DefaultSkin extends AbstractSkin {
@Override
public void display() {
System.out.println("默认皮肤");
}
}
public static class HeimaSkin extends AbstractSkin {
@Override
public void display() {
System.out.println("黑马皮肤");
}
}
}
|
里氏替换原则
原则
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
|
/**
* 里氏替换原则 (LSP):里氏替换原则表述了子类型应当能够替换掉它们的基类型而不影响程序的正确性。
* 该原则主要用于指导继承关系的正确使用,确保子类可以无缝替换父类对象,且替换后程序的行为不会发生变化。
*/
@Slf4j
class 原则 {
public static void main(String[] args) {
Rectangle rectangle = new Rectangle();
rectangle.setLength(20);
rectangle.setWidth(10);
RectangleUtil.resize(rectangle);
RectangleUtil.printLengthAndWidth(rectangle);
System.out.println("============");
Rectangle rectangle1 = new Square();
rectangle1.setLength(10);
// 正方形长宽相等,会死循环
// 因此,Square类和Rectangle类之间的继承关系违反了里氏代换原则,它们之间的继承关系不成立,正方形不是长方形。
RectangleUtil.resize(rectangle1);
RectangleUtil.printLengthAndWidth(rectangle1);
}
// 长方形
@Data
public static class Rectangle {
private double length;
private double width;
}
// 正方形
// 长宽相等,重写父类Rectangle的get/set方法
public static class Square extends Rectangle {
@Override
public void setWidth(double width) {
super.setLength(width);
super.setWidth(width);
}
@Override
public void setLength(double length) {
super.setLength(length);
super.setWidth(length);
}
}
public static class RectangleUtil {
// 扩宽的方法
public static void resize(Rectangle rectangle) {
// 判断宽如果比长小,进行扩宽的操作
while (rectangle.getWidth() <= rectangle.getLength()) {
rectangle.setWidth(rectangle.getWidth() + 1);
}
}
// 打印长方形的长和宽
public static void printLengthAndWidth(Rectangle rectangle) {
System.out.println(rectangle.getLength());
System.out.println(rectangle.getWidth());
}
}
}
|
改进
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
|
/**
* 里氏代换原则改进:抽象出来一个四边形接口(Quadrilateral),让Rectangle类和Square类实现Quadrilateral接口
*/
class 改进 {
public static void main(String[] args) {
Rectangle rectangle = new Rectangle();
rectangle.setLength(20);
rectangle.setWidth(10);
RectangleUtil.resize(rectangle);
RectangleUtil.printLengthAndWidth(rectangle);
}
public static class RectangleUtil {
// 扩宽的方法
public static void resize(Rectangle rectangle) {
// 判断宽如果比长小,进行扩宽的操作
while (rectangle.getWidth() <= rectangle.getLength()) {
rectangle.setWidth(rectangle.getWidth() + 1);
}
}
// 打印长和宽
public static void printLengthAndWidth(Quadrilateral quadrilateral) {
System.out.println(quadrilateral.getLength());
System.out.println(quadrilateral.getWidth());
}
}
public interface Quadrilateral {
double getLength();
double getWidth();
}
@Setter
public static class Rectangle implements Quadrilateral {
private double length;
private double width;
@Override
public double getLength() {
return length;
}
@Override
public double getWidth() {
return width;
}
}
@Setter
public static class Square implements Quadrilateral {
private double side;
@Override
public double getLength() {
return side;
}
@Override
public double getWidth() {
return side;
}
}
}
|
依赖倒置原则
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
|
/**
* 依赖倒置原则 (DIP):依赖倒置原则指出高层模块不应依赖于低层模块,它们都应该依赖于抽象。
* 这一原则鼓励开发者依赖于抽象而非具体实现,从而减少模块间的耦合,提高系统的灵活性和可维护性。
*/
public class C_依赖倒置原则 {
public static void main(String[] args) {
Computer computer = new Computer();
HardDisk hardDisk = new XiJieHardDisk();
Cpu cpu = new IntelCpu();
Memory memory = new KingstonMemory();
computer.setCpu(cpu);
computer.setHardDisk(hardDisk);
computer.setMemory(memory);
computer.run();
}
@Data
public static class Computer {
private HardDisk hardDisk;
private Cpu cpu;
private Memory memory;
public void run() {
System.out.println("从硬盘上获取的数据是:" + hardDisk.get());
cpu.run();
memory.save();
}
}
// 抽象接口
public interface HardDisk {
void save(String data);
String get();
}
public interface Cpu {
void run();
}
public interface Memory {
void save();
}
// 具体对象
public static class XiJieHardDisk implements HardDisk {
public void save(String data) {
System.out.println("使用希捷硬盘存储数据为:" + data);
}
public String get() {
System.out.println("使用希捷希捷硬盘取数据");
return "数据";
}
}
public static class IntelCpu implements Cpu {
public void run() {
System.out.println("使用Intel处理器");
}
}
public static class KingstonMemory implements Memory {
public void save() {
System.out.println("使用金士顿内存条");
}
}
}
|
单一职责原则
单一职责原则 (SRP):单一职责原则强调一个类或模块应该有且仅有一个改变它的原因。
这个原则要求每个类只负责一项任务,从而提高类的内聚性并降低耦合度,使得每个类都更加简单和易于维护。
接口隔离原则
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
|
/**
* 接口隔离原则 (ISP):接口隔离原则建议客户端应当依赖于尽可能小的接口,即接口应细化到只包含对客户端有用的方法。
* 遵循这一原则可以减少客户端对不必要接口的依赖,进一步降低系统的耦合度。
*/
public class E_接口隔离原则 {
public static class HeiMaSafetyDoor implements AntiTheft, Fireproof, Waterproof {
@Override
public void antiTheft() {
System.out.println("防盗");
}
@Override
public void fireproof() {
System.out.println("防火");
}
@Override
public void waterproof() {
System.out.println("防水");
}
}
// 防盗接口
public interface AntiTheft {
void antiTheft();
}
// 防火接口
public interface Fireproof {
void fireproof();
}
// 防水接口
public interface Waterproof {
void waterproof();
}
}
|
迪米特法则
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
|
/**
* 迪米特法则 (LOD):迪米特法则(也称为“最少知识原则”)主张一个类应尽量少地了解其他类的内部实现细节。
* 遵循这一法则可以有效地减少不同类之间的依赖关系,增强模块的独立性和可移植性。
*/
@Slf4j
public class F_迪米特法则 {
@Getter
@AllArgsConstructor
public static class Star {
private String name;
}
@Getter
@AllArgsConstructor
public static class Fans {
private String name;
}
@Getter
@AllArgsConstructor
public static class Company {
private String name;
}
@Setter
public static class Agent {
private Star star;
private Fans fans;
private Company company;
public void meeting() {
System.out.println(fans.getName() + "与明星" + star.getName() + "见面了。");
}
public void business() {
System.out.println(company.getName() + "与明星" + star.getName() + "洽淡业务。");
}
}
}
|
合成复用原则CRP
合成复用原则强调在实现复用时,应优先使用对象的合成/聚合来代替类继承。通过合成复用可以保持系统的灵活性和可扩展性,同时避免因继承带来的不必要的依赖关系。