【设计模式一】七大原则、UML类图、设计模式分类

一、七大原则

1、单一职责原则

Single Responsibility Principle

single [ˈsɪŋɡl] 单一的

responsibility [rɪˌspɑːnsəˈbɪləti] 责任

principle [ˈprɪnsəpl] 原则

对类来说的,即一个类应该只负责一项职责。如类 A负责两个不同职责:职责 1,职责 2。当职责 1需求变更 而改变 A时,可能造成职责 2执行错误,所以需要将类 A的粒度分解为 A1,A2

注意事项和细节

  • 降低类的复杂度,一个类只负责一项职责
  • 提高类的可读性,可维护性
  • 降低变更引起的风险
  • 通常情况下,我们应当遵守单一职责原则,只有逻辑足够简单,才可以在代码级违反单一职责原则;只有类中方法数量足够少,可以在方法级别保持单一职责原则

2、接口隔离原则

Interface Segregation Principle

segregation [ˌseɡrɪˈɡeɪʃn] 隔离

客户端不应该依赖它不需要的接口,即一个类对另一个类的依赖应该建立在最小接口


3、依赖倒置原则

Dependence Inversion Principle

dependence [dɪˈpendəns] 依赖

inversion [ɪnˈvɜːrʒn] 反转、倒转

  • 高层模块不应该依赖低层模块,二者都应该依赖其抽象
  • 抽象不应该依赖细节,细节应该依赖抽象
  • 依赖倒转(倒置)的中心思想是面向接口编程
  • 依赖倒转原则是基于这样的设计理念:相对于细节的多变性,抽象的东西要稳定的多。以抽象为基础搭建的架构比以细节为基础的架构要稳定的多。在 java中,抽象指的是接口或抽象类,细节是具体的实现类
  • 使用接口或抽象类的目的是制定好规范,而不涉及任何具体的操作,把展现细节的任务交给实现类完成
  • 低层模块尽量都要有抽象类或接口,或者两者都有,程序稳定性更好
  • 变量的声明类型尽量是 抽象类 或 接口,这样变量引用和实际对象间,就存在一个缓冲层,利于程序扩展和优化
  • 继承时遵循里氏替换原则

依赖关系传递的三种方式:

  • 接口传递
  • 构造器传递
  • setter 方法传递

4、里氏替换原则

Liskov Substitution Principle

substitution [ˌsʌbstɪ'tuʃ(ə)n] 替代

  • 在使用继承时,应遵循里氏替换原则,尽量不要重写父类已经实现的方法
  • 里氏替换原则告诉我们,继承让两个类的耦合性增加了,在适当情况下,应该用聚合、组合、依赖来解决问题

5、开闭原则

Open Closed Principle

  • 是编程中最基础、最重要的设计原则
  • 一个软件实体,如类,模块和函数应该对扩展开放 (对提供方),对修改关闭(对使用方)。用抽象构建框架,用实现扩展细节
  • 当软件需要变化时,尽量通过扩展软件实体的行为来实现变化,而不是通过修改已有的代码来实现变化
  • 编程中遵循其它原则,以及使用设计模式的目的就是遵循开闭原则

6、迪米特原则

Demeter Principle

又叫最少知道原则

  • 一个对象应该对其他对象保持最少的了解

  • 类与类关系越密切,耦合度越大

  • 又叫最少知道原则,即一个类对自己依赖的类知道的越少越好。也就是说,对于被依赖的类不管多么复杂,都尽量将逻辑封装在类的内部。对外除了提供的 public 方法,不对外泄露任何信息

  • 迪米特法则还有个更简单的定义:只与直接的朋友通信

    直接的朋友:每个对象都会与其他对象有耦合关系,只要两个对象之间有耦合关系,我们就说这两个对象之间是朋友关系。耦合的方式很多,依赖,关联,组合,聚合等。其中,我们称出现成员变量,方法参数,方法返回值中的类为直接的朋友,而出现在局部变量中的类不是直接的朋友。也就是说,陌生的类最好不要以局部变量的形式出现在类的内部

  • 核心是降低类之间的耦合

  • 但是注意:由于每个类都减少了不必要的依赖,因此迪米特法则只是要求降低类间(对象间)耦合关系,并不是要求完全没有依赖关系

7、合成复用原则

Composite Reuse Principle

composite [kəmˈpɑːzət] 合成、组合

reuse [ˌriːˈjuːs , ˌriːˈjuːz] 重复、再用

  • 尽量使用组合/聚合的方式,而不是使用继承

8、核心思想

  • 找出应用中可能需要变化之处,把它们独立出来,不要和那些不需要变化的代码混在一起
  • 针对接口编程,而不是针对实现编程
  • 为了交互对象之间的松耦合设计而努力

二、UML类图

1、基本介绍

UML —— Unified Modeling Language UML (统一建模语言),是一种用于软件系统分析和设计的语言工具,它用于帮助软件开发人员进行思考和记录思路的结果

2、UML图

画UML图与写文章差不多,都是把自己的思想描述给别人看,关键在于思路和条理

UML图分类:

  • 用例图 (use case)
  • 静态结构图:类图、对象图、包图、组件图、部署图
  • 动态行为图:交互图(时序图与协作图)、状态图、活动图

3、UML类图

  • 用于描述系统中的类(对象)本身的组成和类(对象)之间的各种静态关系
  • 类之间的关系:依赖、泛化(继承)、实现、关联、聚合与组合


4、继承和实现

1)继承(Inheritance)

继承也称为 泛化

Inheritance [ɪnˈherɪtəns] 继承

generalization [ˌdʒenrələˈzeɪʃn] 泛化

  • Inheritance表示一个类(接口)继承另一个类(接口)的功能和属性,用于描述父类(接口)和子类(接口)之间的关系
  • 继承描述了"is a kind of "关系,例如:Manger是Employee的一种,Manager继承了Employee的所有功能(例如:刷卡签到、执行工作)和属性(例如:员工姓名、入职时间)。

在UML中,继承使用 实线 空心箭头 表示,空心箭头指向父类(接口)

2)实现(Realization)

Realization [ˌriːələˈzeɪʃn] 实现

Implementation [ˌɪmpləmɛnˈteɪʃən] 实施;执行;

Implementation表示类实现接口的功能。

在UML中,继承使用 虚线 空心箭头 表示,空心箭头指向接口

3)继承和实现的区别

虽然在C#中继承和实现都使用符号:来表示(java中使用extends表示继承,implements表示实现),但二者还是有些区别的。

1. 继承发生在“类和类”或“接口和接口”之间,例如:子类继承父类,子接口继承父接口。

子类继承父类:

public abstract class Animal
{		        
}
        
public class Bird : Animal
{		        

}

子接口继承父接口:

public interface ITransportation
{
    void Move();
}

public interface IVehicle : ITransportation
{
        
}

2. 实现发生在“类和接口”之间,例如:类实现某个接口的方法。

public interface IVehicle : ITransportation
{

}

public class Car : IVehicle
{
    public void Move()
    {
        Console.WriteLine("汽车跑起来...");
    }
}

3. 在C#中,多继承确切地说是多实现。

不像C++语言的语法,C#的类不能同时继承多个类。C#仅能继承一个类,但可以同时实现多个接口。
例如:ASP.NET MVC中的Controller类,继承了ControllerBase类,同时实现了IActionFilter, IAuthenticationFilter…等接口。

区别 继承 实现
符号 实线 空心三角箭头 虚线 空心三角箭头
耦合度
涉及对象 类与类、接口与接口 类与接口
java关键字 extends implements

5、依赖、关联、聚合和组合

1)依赖(Dependency)

[dɪˈpendənsi]

  • 依赖关系是对象之间最基本的关系
  • 当一个对象(调用者)需要调用另外一个对象(被调用者)的方法去完成某些工作时,依赖关系就建立了

在UML中,依赖关系使用 虚线 箭头 表示,箭头指向被依赖的一方。

例如:在Web Service中,Client需要调用Service的操作,这就表示Client依赖于Service。

2)关联(Association)

[əˌsoʊsiˈeɪʃn]

  • Association表示多个对象之间的关联关系
  • 每个对象都有自己的生命周期,对象之间不存在从属关系。

在UML中,关联关系使用一条 直线 表示。

例如:Student和Teacher之间就属于”Association”,多个Student可以关联到一个Teacher,一个Student也可以关联到多个Teacher。
但是Teacher和Student之间没有“从属”或“包含”关系

3)聚合(Aggregation)

aggregation [ˌæɡrɪˈɡeɪʃn] 聚集

segregation [ˌseɡrɪˈɡeɪʃn] 隔离

  • Aggregation体现的是整体和部分之间的关系,即“has-a”关系
  • 整体和部分是可以分离的,即整体和部分都可以拥有各自的生命周期

在UML中,聚合关系使用 空心菱形箭头 表示,箭头指向整体

例如:一个 Department 拥有多个 Employee,Department 作为整体,Department 中的 Employee 是 Department 的一部分。
Department 和 Employee 都有自己的生命周期,当一个 Department 被撤销时,Employee 可以转到其他 Department 或离职了。
Employee 转到其他 Department 或离职时,Department 仍然是存在的

4)组合(Composition)

[ˌkɑːmpəˈzɪʃn]

  • Composition体现的也是整体和部分之间的关系,即“is-a”关系
  • 组合关系是更为强力的聚合关系,整体和部分是不可以分离的
  • 整体的生命周期结束时,也意味着部分的生命周期结束

在UML中,组合关系使用 实心菱形箭头 表示,箭头指向整体

例如:一套房屋有多个房间,房间是房屋的一部分。房间的生命周期依赖于房屋的生命周期,当房屋被拆掉时,房间也就不存在了

5)依赖、关联、聚合和组合的区别

  • 依赖、关联、聚合和组合都可以泛指为”依赖关系”

  • 当对象之间构成 Association、Aggregation 或 Composition 关系时,也建立了对象之间的依赖关系

  • 它们表现的依赖关系强弱程度不同,这4种关系所表现的强弱程度依次为:

    -[强] Composite > Aggregation > Association > Dependency [弱]

关联、聚合和组合是大家经常容易混淆的3种关系,这种关系最大的区别在于对象的生命周期

  • 关联关系:每个对象都有自己的生命周期,对象之间不存在从属关系
  • 聚合关系:整体和部分是可以分离的,整体和部分都可以拥有各自的生命周期
    • 部分整体 中以注入的方式得到的;构造器注入、setter注入
  • 组合关系:整体和部分是不可以分离的,整体的生命周期结束时,也意味着部分的生命周期结束
    • 部分整体 中以 new 的方式得到的;不可分离

三、设计模式概述

1、设计模式介绍

  • 设计模式是程序员在面对同类软件工程设计问题所总结出来的有用的经验,模式不是代码,而是某类问题的通用解决方案,设计模式(Design Pattern)代表了最佳的实践。这些解决方案是众多软件开发人员经过相当长的一段时间的试验和错误总结出来的

  • 设计模式的本质提高软件的维护性、通用性和扩展性,并降低软件的复杂度

  • 设计模式》是经典的书,作者是 Erich Gamma、Richard Helm、Ralph Johnson和 John Vlissides Design(俗称“四人组 GOF”)

  • 设计模式并不局限于某种语言,java,php,c++都有设计模式

2、设计模式类型

三种类型(共23种)

1)创建型模式(5种)

  • 单例模式 (Singleton Pattern)
  • 工厂模式(Factory Pattern)
    • 简单工厂模式
    • 抽象工厂模式(工厂方法模式)
  • 原型模式(Prototype Pattern)
  • 建造者模式(Builder Pattern)

2)结构型模式(7种)

  • 适配器模式
  • 桥接模式
  • 装饰者模式
  • 组合模式
  • 外观模式
  • 享元模式
  • 代理模式

3)行为型模式(11种)

  • 模版方法模式
  • 命令模式
  • 访问者模式
  • 迭代器模式
  • 观察者模式
  • 中介者模式
  • 备忘录模式
  • 解释器模式(Interpreter模式)
  • 状态模式
  • 策略模式
  • 职责链模式(责任链模式)
posted @ 2021-07-25 11:54  土味儿  阅读(589)  评论(0)    收藏  举报