图说设计模式链接
对象关系
下面两个关系好理解
泛化关系(generalization) 继承
- 继承关系 is-a
- 泛化<>实现
- 泛化关系用一条带空心箭头的直接表示;如下图表示(A继承自B);

实现关系(realize) 实现抽象类的接口类
- 继承自抽象类

下面四个关系耦合度递增
依赖关系(dependency) 访问不到私有变量
- 某类作为别的类的局域变量、方法的形参,或者对静态方法的调用
- 描述一个对象在运行期间会用到另一个对象的关系;
- 是一种临时性的关系,通常在运行期间产生,并且随着运行时的变化; 依赖关系也可能发生变化;

PS: 关联、聚合、组合只能配合语义,结合上下文才能够判断出来,而只给出一段代码让我们判断是无法判断的
关联关系(association) 同层次的类 可访问到私有变量
- 类常作为成员变量
- 关联关系是用一条直线表示的
- 关联关系是一种“强关联”的关系,静态的,运行无关的!

- 关联关系默认不强调方向,表示对象间相互知道;如果特别强调方向, A − − > B A-->B A−−>B,表示A知道B,但 B不知道A;
聚合关系(aggregation) 整体部分类间的关联关系
- 类常作为成员变量
- has a
- 无强依赖关系的整体由部分组成的语义
- 学生聚合到班级上

- 整体和部分不是强依赖的,即使整体不存在了,部分仍然存在;例如, 部门撤销了,人员不会消失,他们依然存在。
组合关系(composition) 两类生命周期一样 整体类可以控制部分类的实例化和析构
- 类常作为初始化方法的参数
- contains-a
- 有强依赖关系的整体由部分组成的语义

UML图/时序图
- UML(Unified Modeling Language)统一建模语言

- 时序图(Sequence Diagram)是显示对象之间交互的图,这些对象是按时间顺序排列的。时序图中显示的是参与交互的对象及其对象之间消息交互的顺序。
- 时序图包括的建模元素主要有:对象(Actor)、生命线(Lifeline)、控制焦点(Focus of control)、消息(Message)等等。
设计理念
单一职责原则 SRP
- 就一个类而言,应该仅有一个引起它变化的原因
- 如果一个类承担职责过多,这些职责的耦合性太高,会导致设计十分脆弱!
- 软件设计,发现职责并分离职责!
开发-封闭原则 The Open-Closed Principle OCP
- 开闭原则:针对软件实体(类/模块/函数) ① Open for Extension ② Closed for modification
- 设计类的时候要尽可能考虑完善,新需求来的时候可以通过只增加一些类而不需要修改原类
- 但当变化发生的时候创建抽象类来隔离同类的变化
- 面对需求是通过增加代码而非更改代码实现!
- 但也避免刻意频繁的抽象
- 提高程序的可维护性,可扩展,可复用和灵活性!
依赖倒转原则
- 依赖倒转原则:① 高层模块不应该依赖低层模块,两个都得依赖抽象 ② 抽象不应该依赖细节,而是细节应该依赖抽象
- 即面向接口编程而不是对实现编程
- 为什么叫“倒转”:因为一般程序设计都是高层调用底层,如某项目设计了使用某个数据库的算法操作库,而你现在换了数据库,想复用高层算法代码就不方便了!!!
那为什么依赖了抽象类就不再怕更改呢???
里氏代换原则LSP
- 面向对象设计的标志!
- 子类型必须能够替换掉它们的父类型
- 即 子类型拥有父类型全部非私有的行为和属性!
- 只要都是继承自同一个父类型,当更改子类型时,除了更改实例化的部分,其他都不变!企鹅不能继承自鸟,因为鸟会飞而企鹅不会!
- 只有当子类可以替换父类,父类才能真正被复用,子类也能够在父类基础上增加新的行为!才让继承复用成为了可能,采样依赖倒转原则得以实现!
- 正是由于子类型的可替代性才使得使用父类型的模型在不需修改的情况下可以扩展!
迪米特法则 (最少知识原则) LoD
- 最少知识原则
- ① 如果两个类不必彼此直接通信,那这两个类不应当发生直接的相互作用。② 如果其中一个类需要调用另一个类的方法,可以使用第三者进行转发!
- 即每个类要保护好自己的私有行为和变量,强调两类之间的松耦合,不需要让别的类知道的就不要公开!
- 越弱的耦合越有利于复用!封装的思想!
组成/聚合复用原则 CARP
- 尽量使用组成和聚合,而避免使用继承
- 即优先使用组成和聚合,有利于保持每个类被封装,这样类和类继承层次会保留较小规模!即
变宽以变浅

创建型模式
- 创建型模式(Creational Pattern)对类的实例化过程进行了抽象,能够将软件模块中 对象的创建 和 使用 分离
- 创建型模式在创建什么(What),由谁创建(Who),何时创建(When)等方面都为软件设计者提供了尽可能大的灵活性。
- 创建型模式隐藏了类的实例的创建细节,通过隐藏对象如何被创建和组合在一起达到使整个系统独立的目的。
简单工厂模式 Simple Factory Pattern 4
- 又称为静态工厂方法(Static Factory Method)模式
思路
- 简单工厂模式专门定义一个类来负责创建其他类的实例,被创建的实例通常都具有共同的父类。
结构

- 时序图

import public
public class OperationFactory
{
public static OperationFactory(string operate)
{
Operation oper = null;
switch (operate)
{
case "+";
oper = new OperationFactory();
break;
case "-";
oper = new OperationFactory();
break;
case "*";
oper = new OperationFactory();
break;
case "/";
oper = new OperationFactory();
break;
}
return oper;
}
}
优缺点
- 优点:① 简单工厂模式通过这种做法实现了对责任的分割,它提供了专门的工厂类用于创建对象 ② 客户端无须知道所创建的具体产品类的类名,只需要知道具体产品类所对应的参数即可 ③ 通过引入配置文件,可以在不修改任何客户端代码的情况下更换和增加新的具体产品类,灵活性。
- 缺点:① 简单工厂模式最大的问题在于工厂类的职责相对过重 ② 增加新的产品需要修改工厂类的判断逻辑,这一点与开闭原则是相违背的 ③ 使用简单工厂模式将会增加系统中类的个数,更复杂冗余 ④ 简单工厂模式由于使用了静态工厂方法,造成工厂角色无法形成基于继承的等级结构
工厂方法模式 Factory Method 5
思路
- 定义一个用于创建对象的接口,让子类觉得实例化哪一个类。即将类的实例化延迟到其子类
结构

- 时序图

interface IFactory{
Operation CreateOperation();
}
class AddFactory : IFactory{
public Operation CreateOperation() {
return new OperationAdd();
}
}
class SubFactory : IFactory{
public Operation CreateOperation() {
return new OperationSub();
}
}
class MulFactory : IFactory{
public Operation CreateOperation(){
return new OperationMul();
}
}
class DivFactory : IFactory{
public Operation CreateOperation() {
return new OperationDiv();
}
}
优缺点
- 优点 ① 由于使用了面向对象的多态性,工厂方法模式保持了简单工厂模式的优点,而且克服了它的缺点 ② 在工厂方法模式中,核心的工厂类不再负责所有产品的创建,而是将具体创建工作交给子类去做,隐藏了哪种具体产品类将被实例化这一细节 ③ 这个核心类仅仅负责给出具体工厂必须实现的接口,而不负责哪一个产品类被实例化这种细节,这使得工厂方法模式可以允许系统在不修改工厂角色的情况下引进新产品
- 缺点 ① 在添加新产品时,需要编写新的具体产品类,而且还要提供与之对应的具体工厂类,系统中类的个数将成对增加,在一定程度上增加了系统的复杂度,有更多的类需要编译和运行,会给系统带来一些额外的开销 ② 由于考虑到系统的可扩展性,需要引入抽象层,在客户端代码中均使用抽象层进行定义,增加了系统的抽象性和理解难度,且在实现时可能需要用到DOM、反射等技术,增加了系统的

本文深入讲解23种经典设计模式,包括创建型、结构型和行为型模式,探讨模式的应用场景、优缺点及其实现原理,帮助读者掌握设计模式的核心思想。
2284

被折叠的 条评论
为什么被折叠?



