深刻理解设计模式1:7原则
发布于 2022-06-04 14:28
7原则概述
1) 单一职责原则
2) 接口隔离原则
3) 依赖倒转原则
4) 里氏替换原则
5) 开闭原则 ocp
6) 迪米特法则
7) 合成复用原则
依 里 接 单 开 合 笛
1. 单一职责 汽车在地上跑
类区分
new RoadVehicle().run("汽车");new AirVehicle().run("飞机");class RoadVehicle { public void run(String vehicle) {
System.out.println(vehicle + "公路运行");
}
}class AirVehicle { public void run(String vehicle) {
System.out.println(vehicle + "天空运行");
}
}
方法区分
过于简单,方法区分
Vehicle2 vehicle2 = new Vehicle2();
vehicle2.run("汽车");
vehicle2.runAir("飞机"); public void run(String vehicle) { //处理
System.out.println(vehicle + " 在公路上运行....");
} public void runAir(String vehicle) {
System.out.println(vehicle + " 在天空上运行....");
}
2. 接口隔离 要什么功能实现什么接口
接口 已经最小化,不会有 冗余的实现
接口最小化
// 接口1interface Interface1 { void operation1();
}// 接口2interface Interface2 { void operation2(); void operation3();
}// 接口3interface Interface3 { void operation4(); void operation5();
}
实现需要的
class B implements Interface1, Interface2 { public void operation1() {
System.out.println("B 实现了 operation1");
} public void operation2() {
System.out.println("B 实现了 operation2");
} public void operation3() {
System.out.println("B 实现了 operation3");
}
}
使用和测试
A用到B的 1 2 3 方法,B就只有 123方法
class A { public void depend1(Interface1 i) {
i.operation1();
} public void depend2(Interface2 i) {
i.operation2();
} public void depend3(Interface2 i) {
i.operation3();
}
}
A a = new A();
a.depend1(new B());
a.depend2(new B());
a.depend3(new B());
3. 依赖倒转 对接口的依赖
* 同开闭,加功能使用方不变
//定义接口interface IReceiver { public String getInfo();
}class Email implements IReceiver { public String getInfo() { return "电子邮件信息: hello,world";
}
}//在增加一个 WX//方式2class Person { //这里我们是对接口的依赖
public void receive(IReceiver receiver ) {
System.out.println(receiver.getInfo());
}
}
依赖关系传递 3种方式
依赖关系传递的三种方式和应用案例
1) 接口传递(形参)。叫做 :依赖关系。
2) 构造方法传递。大概也叫做:依赖。
3) setter方式传递。叫做:聚合关系。
解释1:接口作为形参 和 构造的形参,都是方法传递。在UML中都叫做依赖。
解释2:
这三种都是依赖,为什么UML,单独把 setter叫做聚合?
难道因为:setter传递,耦合性比较 弱?
对于 组合而言,聚合的 耦合比较弱。
组合就是:X 对象里,new A();
PS:UML 6种 关系为,依赖,关联,继承(泛化),实现,聚合,组合。
接口传递(形参)
开关的功能 被电视 依赖
//方式1:通过接口传递实现依赖//开关的接口interface IOpenAndClose { public void open(ITV tv); //抽象方法,接收接口}interface ITV { //ITV接口
public void play();
}
实现开关的接口
// 实现接口class OpenAndClose implements IOpenAndClose { public void open(ITV tv) {
tv.play();
}
}
实现电视的接口
class ChangHong implements ITV { @Override
public void play() {
System.out.println("长虹电视机,打开");
}
} //创建 长虹电视
ChangHong changHong = new ChangHong(); //使用顶层开关的接口
OpenAndClose openAndClose = new OpenAndClose(); //参数为:电视接口,我们直接 传递给它一个 电视的实现
openAndClose.open(changHong);
构造传递
// 方式2: 通过构造方法依赖传递interface IOpenAndClose { public void open(); //抽象方法}interface ITV { //ITV接口
public void play();
}class OpenAndClose implements IOpenAndClose { public ITV tv; //成员
public OpenAndClose(ITV tv) { //构造器
this.tv = tv;
} public void open() { this.tv.play();
}
}
ChangHong changHong = new ChangHong(); //通过构造器进行依赖传递
OpenAndClose openAndClose = new OpenAndClose(changHong);
openAndClose.open();
set方法传递
interface IOpenAndClose { public void open(); // 抽象方法
public void setTv(ITV tv);
}interface ITV { // ITV接口
public void play();
}class OpenAndClose implements IOpenAndClose { private ITV tv; public void setTv(ITV tv) { this.tv = tv;
} public void open() { this.tv.play();
}
}
OpenAndClose openAndClose = new OpenAndClose();
openAndClose.setTv(changHong);
openAndClose.open();
4. 里式替换 提取父类,使用组合关系
//创建一个更加基础的基类class Base { //把更加基础的方法和成员写到Base类}// A类class A extends Base { // 返回两个数的差
public int func1(int num1, int num2) { return num1 - num2;
}
}// B类继承了A// 增加了一个新功能:完成两个数相加,然后和9求和class B extends Base { //如果B需要使用A类的方法,使用组合关系
private A a = new A(); //这里,重写了A类的方法, 可能是无意识
public int func1(int a, int b) { return a + b;
} public int func2(int a, int b) { return func1(a, b) + 9;
} //我们仍然想使用A的方法
public int func3(int a, int b) { return this.a.func1(a, b);
}
}
5. 开闭原则 核心。新增图形 继承父类
* 使用方,无需改变。同依赖倒转
//这是一个用于绘图的类 [使用方],扩展的时候,无需修改class GraphicEditor { //接收Shape对象,调用draw方法
public void drawShape(Shape s) {
s.draw();
}
}
接口和实现
//Shape类,基类abstract class Shape { int m_type; public abstract void draw();//抽象方法}//可新增class Rectangle extends Shape {
Rectangle() { super.m_type = 1;
} @Override
public void draw() { // TODO Auto-generated method stub
System.out.println(" 绘制矩形 ");
}
}
GraphicEditor g = new GraphicEditor(); //依赖的接口,使用时 传递实现
g.drawShape(new Rectangle());
6. 迪米特法则
最少知道原则
直接朋友
我们称出现
成员变量,
方法参数,
方法返回值中的类为直接的朋友,
而出现在局部变量中的类不是直接的朋友。
陌生的类最好不要以局部变量的形式出现在类的内部。
总部员工 和 学院员工
//学校总部员工类class Employee { private String id;
}//学院的员工类class CollegeEmployee { private String id; //get set}
学院员工管理
//管理学院员工的管理类class CollegeManager { //返回学院的所有员工
public List<CollegeEmployee> getAllEmployee() {
... return list;
}
}
总部员工管理,打印总部 和 学院信息
不遵守法则
class SchoolManager { //返回学校总部的员工
public List<Employee> getAllEmployee() {
... return list;
} //该方法完成输出学校总部和学院员工信息(id)
void printAllEmployee(CollegeManager sub) { //1. 这里的 CollegeEmployee 不是 SchoolManager的直接朋友
//2. CollegeEmployee 是以局部变量方式出现在 SchoolManager
//3. 违反了 迪米特法则
//获取到学院员工
List<CollegeEmployee> list1 = sub.getAllEmployee();
System.out.println("------------学院员工------------"); for (CollegeEmployee e : list1) {
System.out.println(e.getId());
} //打印
System.out.println(this.getAllEmployee());
}
}
使用法则改进
学院类 提供打印的方法
不要把自己的实现方法,写到别人的类里
//输出学院员工的信息
public void printEmployee() {
System.out.println(getAllEmployee());
}
学校总部类,打印时,调用方法
void printAllEmployee(CollegeManager sub) { //1. 将输出学院的员工方法,封装到CollegeManager
sub.printEmployee();
....
}
7. 合成复用原则
(Composite Reuse Principle)
原则是尽量使用合成/聚合的方式,而不是使用继承
设计原则核心思想
1) 找出应用中可能需要变化之处,把它们独立出来,不要和那些不需要变化的代
码混在一起。
2) 针对接口编程,而不是针对实现编程。
3) 为了交互对象之间的松耦合设计而努力
UML类图 元素6个关系
使用了 > ▷+ 虚线 实线。
实线 + ◇♦
6种组合
但:最普通的箭头 —>,表示组合,不合适。顾去掉了箭头,用 — 标识。
继承为不好的强依赖。用实线:—▷
实现是比较好的弱依赖,用虚线:—-▷
依赖,聚合,组合,实质是一个东西。依赖已经用图形表示过。
聚合是 与组合 相比,耦合性弱:所以是 空心的菱形。
组合:耦合性 特别强。所以 实心的菱形。
注意:聚合 组合 都是实线。
聚合,组合用 菱形表示
1. 依赖、-----> 虚线
Dependency
方法的参数 (a:A),构造也是吧
2. 关联、_______ 实线 或 ————>
association
一对一,一对n
3. 继承(泛化)、————▷ 实线 ___▷
Generalization
略
4. 实现、------▷ 虚线
implementation 和 realization
略
5. 聚合、——————◇ 实线 ____◇
Aggregation
定义属性 a:A,使用 setA(a:A) 方法赋值
当前类X,聚合了 A类
6. 组合、——————♦ 实线 ____♦
composite
x类里,new A(); 耦合性 比聚合强。
本文来自网络或网友投稿,如有侵犯您的权益,请发邮件至:aisoutu@outlook.com 我们将第一时间删除。
相关素材