写在前面:什么是设计模式,大学生适不适合学,(坐标重庆某双非)最起码从我认识到的很多去大厂的人来说,包括研究生,本科生,甚至博士生,去到了华为、腾讯、阿里等大厂。嗯,他们根本没了解过。。。。哈哈哈,是不是学了也没用的,学了就是浪费时间?NONONO!我想在这里说的是,设计模式是与数据结构相提并论的技术方法,虽然没有数据结构,或者算法那样有很明显的使用场景,但是对于设计模式,我想把它描述成为一个雄鸡,不鸣则已,一鸣惊人。对于传统普通软件开发,确实只有少量的设计模式是被用到的,但是,对于更高级的工业领域,对于高级工业控制,流程自动化,自动驾驶,机器人操作系统开发,等等。当面对着成万的代码文件,一个小改动就会导致整体架构难以运转,设计模式体现出了它的作用,对于读者,不知道各位在开发的时候,是否涉及到了上万的代码与上万的代码文件,如果没有设计模式这一大家公认的一个标准,代码维护的难度可想而知。
由于本人能力有限,目前只在Unity开发中与ROS系统集成中,已经初步了解到了设计模式的重要意义,如果没有它,开发一个但凡有点难度的Unity混合现实设计产品或者开发基于ROS的小车,那将根本无从下手,代码逻辑不清楚,动不动就上万的代码,又该怎么维护呢。
这里复制百度对于设计模式的定义:
设计模式(Design pattern)代表了最佳的实践,通常被有经验的面向对象的软件开发人员所采用。设计模式是软件开发人员在软件开发过程中面临的一般问题的解决方案。这些解决方案是众多软件开发人员经过相当长的一段时间的试验和错误总结出来的。
设计模式是一套被反复使用的、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了重用代码、让代码更容易被他人理解、保证代码可靠性。 毫无疑问,设计模式于己于他人于系统都是多赢的,设计模式使代码编制真正工程化,设计模式是软件工程的基石,如同大厦的一块块砖石一样。项目中合理地运用设计模式可以完美地解决很多问题,每种模式在现实中都有相应的原理来与之对应,每种模式都描述了一个在我们周围不断重复发生的问题,以及该问题的核心解决方案,这也是设计模式能被广泛应用的原因。
这里不得不说一下设计的两大原则:
- 对接口编程而不是对实现编程。
- 优先使用对象组合而不是继承。
我知道对于刚看到的同志们不知道什么意思:以下是更详细的解释
1. 开闭原则(Open-Closed Principle, OCP)
详细解释:
开闭原则要求软件实体(类、模块、函数等)应该对扩展开放,对修改关闭。这意味着在软件的生命周期内,对于因为需求变化而需要添加新功能时,应该通过扩展现有软件实体来实现,而不是通过修改已有的代码。这有助于保持软件的稳定性,减少因修改旧代码而引入的bug。
实现方式:
- 使用抽象类和接口定义软件实体的基础结构和行为。
- 当需要添加新功能时,通过创建新的类来实现这些接口或继承抽象类,而不是修改现有的类。
2. 里氏代换原则(Liskov Substitution Principle, LSP)
详细解释:
里氏代换原则表明,如果每个类型的S对象都可以被当作T类型的对象使用(S是T的子类型),那么程序中使用T类型的地方,在不改变程序行为的前提下,可以替换成S类型。这要求子类必须能够替换掉它们的基类,同时保持程序的正确性。
实现方式:
- 子类不应该违反基类中的契约(即方法的行为和前置条件、后置条件)。
- 在设计子类时,要确保子类可以无缝地替换基类,而不会破坏使用基类的地方的代码。
3. 依赖倒转原则(Dependence Inversion Principle, DIP)
详细解释:
依赖倒转原则强调要针对抽象编程,不要针对具体编程。这意味着高层模块不应该依赖低层模块,两者都应该依赖其抽象;抽象不应该依赖细节;细节应该依赖抽象。这有助于减少类之间的耦合,提高系统的可维护性和可扩展性。
实现方式:
- 使用接口或抽象类来定义依赖关系。
- 高层模块通过接口或抽象类来引用低层模块,而不是直接引用具体的实现类。
4. 接口隔离原则(Interface Segregation Principle, ISP)
详细解释:
接口隔离原则要求不应该强迫客户依赖于它们不使用的方法。这意味着一个类对另一个类的依赖应该建立在最小的接口上。如果一个大接口包含了许多客户不需要的方法,那么应该将这些方法拆分到多个更小的接口中,客户只需要知道它们感兴趣的方法即可。
实现方式:
- 细化接口,使其更加专一化。
- 客户端仅依赖它们需要的接口。
5. 迪米特法则(Law of Demeter, LoD),又称最少知道原则
详细解释:
最少知道原则要求一个软件实体应当尽可能少地与其他实体发生相互作用。这意味着一个类应该只与它的直接朋友(即类的成员变量、方法的输入输出参数中的类、方法内部创建的类)通信。这有助于降低系统的耦合度,提高系统的可维护性。
实现方式:
- 减少类之间的直接依赖。
- 使用中介者模式等设计模式来降低类之间的耦合。
6. 合成复用原则(Composite/Aggregate Reuse Principle, CARP)
详细解释:
合成复用原则要求尽量使用合成/聚合的方式来实现复用,而不是使用继承。继承是一种强耦合的复用方式,它会使子类和基类之间产生紧密的联系,一旦基类发生变化,子类也会受到影响。而合成/聚合则是一种更灵活的复用方式,它可以在运行时动态地组合对象,从而实现功能的复用。
实现方式:
- 使用组合(Composition)或聚合(Aggregation)来构建复杂对象。
- 将复杂的系统分解成多个简单的对象,并通过这些对象的组合来实现系统的功能。
以上六大原则,详细介绍了设计模式的意义
由于菜鸡(我)长期做混合现实的工作,主要利用到Unity开发中的C#语言,所以本系列采用C#语言进行描述,当然,Java也是同样适用的,原理是相通的,只不过菜鸡不会,嘤嘤嘤。。。
设计模式优点:
设计模式为开发团队构建了一个共通的设计语言和思想框架,极大地增强了团队成员间在设计构思上的交流准确性和相互理解深度。它们不仅是理论上的指导,更是实践中的智慧结晶,为软件开发提供了经过时间验证的、可信赖的构建块,显著提升了软件在维护、复用和适应变化方面的能力。
设计模式鼓励并促进了代码级别的重用,这意味着相似的功能或问题可以通过复用已有的设计模式来快速解决,而非每次都从零开始设计,从而大幅减少了不必要的重复劳动和潜在的设计缺陷。
最终,遵循设计模式进行软件开发,实质上是在实践一种更为严谨和高效的开发方法,它有助于预防常见的设计陷阱和错误,确保代码质量的稳步提升,为构建更加健壮、可靠和可扩展的软件系统奠定坚实基础。
嗯是的。。
以下是常见的设计模型的含义
类别 | 中文名称 | 英文名称 | 含义 | 概括 |
---|---|---|---|---|
创建型 | 工厂方法 | Factory Method | 允许子类决定实例化对象的类型,提供了创建对象的灵活接口。 | 灵活创建 |
创建型 | 抽象工厂 | Abstract Factory | 提供一个接口来创建一系列相关或依赖的家族对象,无需具体指定类。 | 家族对象工厂 |
创建型 | 构建器 | Builder | 将复杂对象的构建过程与其表示分离,支持逐步构建对象的不同表示。 | 逐步构建 |
创建型 | 原型 | Prototype | 通过复制现有对象来创建新对象,实现快速实例化。 | 快速克隆 |
创建型 | 单例 | Singleton | 确保类只有一个实例,并提供全局访问点,防止多实例问题。 | 全局单例 |
结构型 | 适配器 | Adapter | 将一个类的接口适配为另一个不兼容的接口,促进接口间的协作。 | 接口适配 |
结构型 | 桥接 | Bridge | 将抽象与实现分离,允许它们独立变化,增强系统的可扩展性。 | 抽象实现分离 |
结构型 | 组合 | Composite | 将对象组合成树状结构,表示部分与整体的关系,实现统一操作。 | 部分整体统一 |
结构型 | 装饰 | Decorator | 运行时动态给对象添加职责,提供灵活的扩展方式。 | 动态扩展 |
结构型 | 外观 | Facade | 为复杂子系统提供一个简化的接口,便于客户端访问。 | 简化接口 |
结构型 | 享元 | Flyweight | 通过共享技术减少对象数量,支持大量细粒度对象的有效管理。 | 对象共享 |
结构型 | 代理 | Proxy | 为其他对象提供一种代理以控制对这个对象的访问。 | 访问代理 |
行为型 | 职责链 | Chain of Responsibility | 将请求沿着链传递,直到找到处理者,实现请求的灵活分发。 | 请求分发 |
行为型 | 命令 | Command | 将请求封装成对象,支持命令的存储、传递、撤销和恢复。 | 命令封装 |
行为型 | 解释器 | Interpreter | 定义一个语言的文法,并解释语言中的句子。 | 语言解释 |
行为型 | 迭代器 | Iterator | 提供遍历集合的统一接口,隐藏集合的内部结构。 | 集合遍历 |
行为型 | 中介者 | Mediator | 封装对象间的交互,降低对象间的耦合度。 | 对象交互中介 |
行为型 | 备忘录 | Memento | 捕获并保存对象的内部状态,以便将来恢复。 | 状态恢复 |
行为型 | 观察者 | Observer | 定义对象间的一对多依赖,实现状态的自动通知和更新。 | 状态通知 |
行为型 | 状态 | State | 允许对象在内部状态改变时改变其行为,实现行为的灵活性。 | 状态行为 |
行为型 | 策略 | Strategy | 定义一系列算法,并封装起来,让它们之间可以互相替换。 | 算法替换 |
行为型 | 模板方法 | Template Method | 定义一个算法骨架,允许子类在不改变结构的情况下重定义特定步骤。 | 算法骨架 |
行为型 | 访问者 | Visitor | 为对象结构中的元素提供新的操作,支持操作与数据结构的分离。 | 操作分离 |
以下是从菜鸟偷的图,辅助更好的理解他们之间的关系
哈哈哈,这只是概述哦,看的一头雾水吧,嗯,学习总是有渐进过程的,学完回头看,才会发现,nnd果然难理解。。。嘤嘤嘤
下课!