深刻理解设计模式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 我们将第一时间删除。

相关素材