二十四种设计模式与六大设计原则(五): “Gang of Four“ 设计模式(创建型、结构型、行为型)与六大设计原则(单一职责原则、开闭原则、里氏替换原则、依赖倒置原则、接口隔离原则、迪米特法则)

接上次博客:二十四种设计模式与六大设计原则(四):【状态模式、原型模式、中介者模式、解释器模式、享元模式、备忘录模式】的定义、举例说明、核心思想、适用场景和优缺点-CSDN博客

目录

"Gang of Four" 设计模式

创建型设计模式

结构型设计模式

行为型设计模式

六大设计原则

单一职责原则【Single Responsibility Principle】 

好处

应用范围

里氏替换原则【Liskov Substitution Principle】 

具体定义

意义与要求

应用与实践

总结

依赖倒置原则【Dependence Inversion Principle】 

关键点

优点 

重要性和应用

接口隔离原则【Interface Segregation Principle】

定义描述

解释说明

优势

总结

迪米特法则【Low Of Demeter】

四层含义

核心思想

开闭原则【Open Close Principle】

定义和原理

实现方式

优点

注意事项


 

"Gang of Four" 设计模式

我们前面已经学习了二十四种设计模式,细心一点的的话,你会发现这二十四种设计模式都被归了类。

这三个主要类别通常统称为 "Gang of Four" 设计模式。

"Gang of Four"(四人组)是指Erich Gamma、Richard Helm、Ralph Johnson和John Vlissides等四位软件工程师,他们在1994年出版的书籍《设计模式:可复用面向对象软件的基础》(Design Patterns: Elements of Reusable Object-Oriented Software)中提出了23种(单例+多例算一种)常见的设计模式,并将它们分为三个主要类别:创建型设计模式、结构型设计模式和行为型设计模式。

  • 创建型设计模式:这些设计模式关注对象的创建机制,帮助我们处理对象的创建方式,以便我们能够根据不同的场景选择合适的创建方式。
  • 结构型设计模式:这些设计模式关注对象之间的组合,帮助我们设计对象之间的结构,以便我们能够更好地管理对象之间的关系。常见的结构型设计模式包括:
  • 行为型设计模式:这些设计模式关注对象之间的交互行为,帮助我们设计对象之间的通信和协作方式,以便我们能够更好地组织和管理代码。

这些设计模式提供了一套经过验证的解决方案,帮助开发人员解决常见的设计问题,并提高代码的重用性、可维护性和灵活性。

创建型设计模式

定义: 创建型设计模式关注对象的实例化过程,它们提供了一种方法来创建对象,以解耦对象的创建与使用。

详细说明:

  1. 单例模式(Singleton Pattern): 确保一个类只有一个实例,并提供全局访问点。这可以确保在整个应用程序中只有一个类的实例,常用于需要全局访问点或资源共享的情况下。

  2. 多例模式(Multiton Pattern):确保一个类只有有限个实例存在,并且提供对它们的全局访问点。

  3. 工厂方法模式(Factory Method Pattern): 定义一个用于创建对象的接口,但将实际创建的工作延迟到子类中。这使得客户端代码不需要知道要实例化的具体类,只需调用工厂方法来创建所需的对象。

  4. 抽象工厂模式(Abstract Factory Pattern): 提供一个接口,用于创建一系列相关或依赖对象的家族,而不需要指定具体的类。它是工厂方法模式的一种扩展,用于创建一系列相关的对象。

  5. 建造者模式(Builder Pattern): 将一个复杂对象的构建过程与其表示分离,使得同样的构建过程可以创建不同的表示。它允许你逐步构建复杂对象,同时保持构建过程的灵活性。

  6. 原型模式(Prototype Pattern): 通过复制现有对象来创建新对象,而不是通过实例化类。它可以用于创建成本较高的对象,或者需要大量相似对象的情况下。

这些创建型设计模式提供了灵活的方法来实例化对象,并允许我们根据具体需求选择最适合的实现方式。

结构型设计模式

定义: 结构型设计模式关注对象之间的组合,它们提供了一种方法来实现对象之间的关系,以便构建更大的结构。

详细说明:

  1. 适配器模式(Adapter Pattern): 将一个类的接口转换成客户端所期望的另一个接口。它允许不兼容接口的类协同工作。

  2. 桥梁模式(Bridge Pattern): 将抽象部分与其实现部分分离,使它们都可以独立地变化。这种分离允许你分别改变抽象和实现,而不会相互影响。

  3. 组合模式(Composite Pattern): 将对象组合成树形结构以表示“部分-整体”的层次结构。这种模式允许客户端统一处理单个对象和组合对象。

  4. 装饰器模式(Decorator Pattern): 动态地给一个对象添加一些额外的职责,而不影响其接口。这使得我们可以在运行时透明地扩展对象的功能。

  5. 外观模式(Facade Pattern): 为子系统中的一组接口提供一个统一的接口。它将复杂的子系统封装在一个简单的接口后面,使得客户端更容易使用。

  6. 享元模式(Flyweight Pattern): 运用共享技术有效地支持大量细粒度的对象,节省内存。它通过共享相同的状态来最大程度地减少内存占用。

  7. 代理模式(Proxy Pattern): 为其他对象提供一种代理以控制对这个对象的访问。代理模式允许你在访问对象时添加额外的行为,例如延迟加载或访问控制。

这些结构型设计模式提供了一种将对象组织在一起的灵活方法,并允许我们以更高层次的抽象来处理对象之间的关系。

行为型设计模式

定义: 行为型设计模式关注对象之间的通信和职责分配,它们提供了一种方法来协调对象之间的交互。

详细说明:

  1. 策略模式(Strategy Pattern): 定义一系列算法,将每个算法封装成一个类,并使它们可以互相替换。这使得算法可以独立于客户端而变化。

  2. 观察者模式(Observer Pattern): 定义了一种一对多的依赖关系,使得一个对象的状态改变时,其所有依赖对象都会收到通知并自动更新。这使得对象之间保持松耦合关系。

  3. 模板方法模式(Template Method Pattern): 定义一个算法的骨架,将一些步骤延迟到子类中实现。这使得子类可以在不改变算法结构的情况下重新定义算法的特定步骤。

  4. 迭代器模式(Iterator Pattern): 提供一种方法顺序访问一个聚合对象中的各个元素,而又不需要暴露该对象的内部表示。迭代器模式允许客户端透明地访问聚合对象的元素。

  5. 命令模式(Command Pattern): 将请求封装成对象,使得可以参数化客户端对象,队列或者日志请求,以及支持可撤销的操作。这使得请求发送者和接收者解耦,并支持日志、撤销和重做等功能。

  6. 状态模式(State Pattern): 允许对象在内部状态改变时改变它的行为,使得对象看起来好像修改了它的类。状态模式将每种状态都封装在一个类中,并将状态转换的逻辑封装在状态类中。

  7. 责任链模式(Chain of Responsibility Pattern): 将请求的发送者和接收者解耦,使得多个对象都有机会处理请求。责任链模式允许您动态地组织处理请求的对象。

  8. 访问者模式(Visitor Pattern): 封装一系列的操作,使得可以在不改变对象结构的前提下作用于这些对象上。访问者模式将操作封装在一个访问者对象中,并在访问者对象上调用对象的操作。

  9. 备忘录模式(Memento Pattern): 在不破坏封装性的前提下,捕获对象的内部状态,并在对象之外保存这个状态,以便日后恢复到这个状态。备忘录模式允许您在不暴露对象实现细节的情况下保存和恢复对象状态。

  10. 中介者模式(Mediator Pattern): 用一个中介对象来封装一系列的对象交互,中介者使各对象不需要显式地相互引用。中介者模式将对象间的通信封装在中介者对象中,并将对象解耦。

  11. 解释器模式(Interpreter Pattern): 给定一个语言,定义它的文法的一种表示,并定义一个解释器,该解释器使用该表示来解释语言中的句子。解释器模式将语言的解析和执行分离,使得语言的修改更加灵活。

这些行为型设计模式提供了一种灵活的方法来管理对象之间的通信和职责分配,并允许我们在系统中引入更多的灵活性和可扩展性。

六大设计原则

六大设计原则是指面向对象设计中的六条基本原则,它们是:

  1. 单一职责原则(Single Responsibility Principle,SRP): 意味着一个类应该仅有一个引起它变化的原因。换句话说,一个类应该只负责一个职责或一个功能领域。这样可以使类更加专注、简单,降低其变更的风险,提高代码的可读性和可维护性。

  2. 开闭原则(Open-Closed Principle,OCP): 意味着软件实体(类、模块、函数等)应该对扩展开放,对修改关闭。这意味着可以通过扩展来改变软件的行为,而无需修改已有的代码。这样可以使得软件系统更加稳定、可维护和可扩展。

  3. 里氏替换原则(Liskov Substitution Principle,LSP): 意味着派生类(子类)必须能够替换其基类(父类)而不影响程序的正确性。换句话说,子类型必须能够替换掉父类型而不引起任何意外行为。这样可以确保继承关系的正确性,提高代码的可靠性和可维护性。

  4. 依赖倒置原则(Dependency Inversion Principle,DIP): 意味着高层模块不应该依赖于底层模块,两者都应该依赖于抽象。抽象不应该依赖于具体实现细节,具体实现细节应该依赖于抽象。这样可以降低模块之间的耦合度,提高代码的灵活性和可维护性。

  5. 接口隔离原则(Interface Segregation Principle,ISP): 意味着客户端不应该依赖于它不使用的接口。换句话说,一个类应该只依赖于它需要的接口,而不应该依赖于不需要的接口。这样可以使接口更加专注、清晰,提高代码的可读性和可维护性。

  6. 迪米特法则(Law of Demeter,LoD),也称为最少知识原则(Least Knowledge Principle,LKP)**: 意味着一个对象应该对其他对象有最少的了解,即一个对象应该只与其直接的朋友通信,而不应该与陌生对象通信。这样可以降低对象之间的耦合度,提高代码的灵活性和可维护性。

这些设计原则提供了指导性的准则,帮助开发人员设计出高质量、可维护、可扩展的软件系统。

单一职责原则【Single Responsibility Principle】 

单一职责原则(Single Responsibility Principle,SRP)是面向对象设计中的重要原则之一,它指导着如何设计类和模块以确保其功能单一且职责清晰。

单一职责原则的核心思想是:一个类应该只有一个引起变化的原因。

换句话说,一个类应该只负责一项职责或功能,而不应该承担过多的责任。如果一个类有多个功能,那么这些功能可能会因不同的原因而发生变化,这样就会增加类的复杂度和维护成本。

那使用了单一职责原则有什么好处呢?

好处

遵循单一职责原则的好处包括:

  1. 提高代码的可读性和可维护性:每个类都只关注一个特定的功能,使得代码更加清晰和易于理解。
  2. 降低类的复杂度:将功能拆分到不同的类中,使得每个类的职责更加明确,减少了类的复杂度。
  3. 降低变更的风险:当一个功能需要修改时,只需要修改一个类,而不会影响到其他功能,降低了变更的风险。

然而,需要注意的是,并不是所有情况下都要严格遵循单一职责原则。有时候,为了简化设计或提高效率,一个类可能会负责多个相关的功能。在这种情况下,需要权衡各种因素,根据具体情况来决定是否需要将功能拆分成多个类。

应用范围

单一职责原则适用于接口、类和方法的设计:

  • 接口: 接口一定要做到单一职责,每个接口只定义一种功能或服务,确保接口的设计粒度合适。
  • 类: 类的设计尽量只有一个原因引起变化,每个类只负责一项职责,避免一个类承担过多的功能。
  • 方法: 方法的设计也应遵循单一职责原则,一个方法尽可能只做一件事情,确保方法的功能单一且职责明确,提高方法的重用性和可维护性。例如,将修改用户密码和修改用户信息拆分为不同的方法,以提高方法的粒度和可复用性。

单一职责原则不仅适用于接口和类的设计,也同样适用于方法的设计。让我们更深入地了解一下:

单一职责原则在方法级别的应用:

在方法级别,单一职责原则要求一个方法只负责一项具体的功能或任务,不要将多个不同功能的代码混合在同一个方法中。这样可以提高方法的可读性、可维护性和灵活性,同时降低变更的风险。一个方法如果只负责一个明确的任务,那么当需求发生变化时,只需要修改对应的方法,而不会影响到其他功能,从而减少了代码的耦合性。

举例来说,如果有一个方法用于修改用户密码,那么该方法应该专注于密码的修改功能,而不应该包含其他与用户信息无关的逻辑。如果将密码修改功能和其他用户信息修改功能混合在同一个方法中,那么当需要修改密码规则或密码加密方式时,就会影响到整个方法的逻辑,增加了修改的复杂度。

因此,设计方法时应该尽量做到功能的细分,让每个方法尽可能只负责一个功能,这样可以使代码更加清晰、简洁,提高了代码的可维护性和可读性。

单一职责原则是面向对象设计的重要原则之一,它帮助我们设计出更加模块化、可维护和可扩展的代码。遵循单一职责原则可以降低代码的复杂度,提高代码的可读性、可维护性和灵活性,是编写高质量、易于理解和易于维护的软件的关键之一。

里氏替换原则【Liskov Substitution Principle】 

里氏替换原则(Liskov Substitution Principle,LSP)是面向对象设计中的重要原则之一,它指导着如何设计子类与父类之间的关系,以确保子类能够替换父类而不产生意外的行为变化。

具体定义

里氏替换原则有两种常见的定义:

  1. 正宗定义: 如果对于每一个类型为 S 的对象 o1,都有类型为 T 的对象 o2,使得以 T 定义的所有程序 P 在所有的对象 o1 都代换成 o2 时,程序 P 的行为没有发生变化,那么类型 T 是类型 S 的子类型。

  2. 通俗定义: 所有引用基类的地方必须能够透明地使用其子类的对象,即使用父类的地方必须能够无缝地替换为子类,而不会导致任何错误或异常。

意义与要求

里氏替换原则包含以下四个要求:

  1. 子类必须完全实现父类的方法: 子类在继承父类时,应该保证所有继承的方法在子类中完全实现,不能修改方法的预期行为。
  2. 子类可以有自己的个性: 子类可以在继承父类的基础上添加新的方法或属性,以扩展父类的功能,但不应该修改父类的行为。
  3. 覆盖或实现父类的方法时输入参数可以被放大: 子类的方法可以接受比父类方法更广泛的输入参数,即子类方法的参数类型可以是父类方法参数类型的子类型。
  4. 覆盖或实现父类的方法时输出结果可以被缩小: 子类的方法可以返回比父类方法更窄的输出结果,即子类方法的返回类型可以是父类方法返回类型的子类型。

应用与实践

里氏替换原则在面向对象设计和开发中具有广泛的应用,主要体现在以下方面:

  • 类继承关系设计: 在设计类的继承关系时,需要确保子类能够透明地替换父类,继承关系要符合里氏替换原则。
  • 接口设计: 接口的设计应该遵循里氏替换原则,接口的实现类应该能够替换接口而不影响系统的功能。
  • 方法重写与实现: 子类在重写父类方法或实现接口方法时,要确保方法的行为与父类方法一致,或者是行为的扩展而不是修改。
  • 使用多态特性: 利用多态特性,可以在运行时动态地替换父类对象为子类对象,提高代码的灵活性和可扩展性。

以下我们再对里氏替换原则的各个方面进行更加详细解释:

1. 使用父类或接口调用其他类

  • 在类设计中,当一个类需要调用其他类时,应该使用父类或接口来引用。这样做的目的是确保类之间的松耦合性,增强代码的灵活性和可维护性。
  • 如果类在调用其他类时不能使用父类或接口,而是直接引用具体的子类,那么这违背了里氏替换原则,因为这样会导致代码高度耦合,难以维护和扩展。

2. 子类可以有自己的个性

  • 尽管子类应该能够透明地替换父类,但是子类也应该有自己的特性和行为。这意味着子类可以在继承父类的基础上添加新的方法或属性,以扩展父类的功能,而不会修改父类的行为。
  • 子类的个性化特征使得系统更加灵活,能够应对不同的需求变化,同时保持了代码的一致性和可维护性。

3. 向下转型是不安全的

  • 向下转型是将父类类型的引用转换为子类类型的引用。根据里氏替换原则,这种操作是不安全的,因为父类未必能够适应于所有出现子类的地方。
  • 使用向下转型会破坏程序的健壮性,可能导致类型转换异常或其他意外情况的发生。因此,应尽量避免向下转型,而是通过多态性来实现统一的接口调用。

4. 覆盖或实现父类方法时的输入参数

  • 当子类覆盖或实现父类的方法时,应确保子类方法的输入参数能够满足父类方法的前置条件。也就是说,子类方法的输入参数应该比父类方法的输入参数更广泛,或者相同。
  • 这确保了子类方法在被调用时不会产生错误或异常,并且能够保证系统的稳定性和可靠性。通过满足父类方法的前置条件,子类可以保证行为的一致性,符合系统的设计规范。

5. 覆盖或实现父类方法时的输出结果

  • 子类覆盖或实现父类方法时,其输出结果应该是父类方法输出结果的子类型,或者与父类方法的输出结果相同。
  • 这意味着子类方法的返回值应该比父类方法的返回值更窄,或者相同。通过确保输出结果的一致性,可以保证程序的正确性和可靠性,符合里氏替换原则的要求。

6. 加强程序的健壮性与版本兼容性

  • 里氏替换原则的出现旨在加强程序的健壮性,使得代码更加可靠和稳定。通过正确地设计类之间的继承关系,可以降低系统的耦合度,提高代码的可维护性和可扩展性。
  • 同时,遵循里氏替换原则还能够保证系统的版本升级具有良好的兼容性。当新的子类被引入时,原有的子类仍然可以继续运行,不会产生兼容性问题,从而保护了系统的投资价值和长期发展。

总结

里氏替换原则是面向对象设计中的重要原则之一,它确保了子类能够透明地替换父类,从而提高了代码的灵活性、可维护性和可扩展性。遵循里氏替换原则能够有效地降低系统的耦合度,减少代码的依赖关系,是设计高质量、可靠性的面向对象系统的关键之一。

依赖倒置原则【Dependence Inversion Principle】 

依赖倒置原则(Dependence Inversion Principle,DIP)是面向对象设计中的重要原则之一,它指导着如何构建松耦合、可维护和可扩展的软件系统。该原则的核心思想是:高层模块不应该依赖于低层模块,二者都应该依赖于抽象;抽象不应该依赖于具体实现细节,具体实现细节应该依赖于抽象。

关键点

具体来说,依赖倒置原则包含以下两个关键点:

  1. 高层模块与低层模块的关系:传统的设计方法往往是高层模块直接依赖于低层模块,即高层模块直接使用和依赖于低层模块的具体实现。而依赖倒置原则则要求高层模块和低层模块都应该依赖于抽象,而不是具体的实现细节。

  2. 抽象与具体实现的关系:依赖倒置原则要求抽象不应该依赖于具体实现细节,而是具体实现细节应该依赖于抽象。这意味着在设计系统时,应该先定义好抽象接口或抽象类,然后由具体的实现类来实现这些抽象接口或继承这些抽象类。

优点 

依赖倒置原则的目标是降低模块之间的耦合度,提高系统的灵活性和可维护性。通过依赖倒置,可以实现如下几个优点:

  • 松耦合:高层模块不依赖于低层模块的具体实现细节,而是依赖于抽象接口,从而实现了模块之间的松耦合。

  • 可扩展性:由于模块之间的耦合度降低,系统变得更加灵活和可扩展。可以方便地替换和添加新的实现类,而不会影响到其他模块的功能和稳定性。

  • 可维护性:依赖倒置原则使得系统的各个模块之间的关系更加清晰明了,易于理解和维护。当需要修改某个模块时,只需要关注该模块的抽象接口或抽象类,而不需要考虑其他模块的具体实现细节。

重要性和应用

  1. 解耦业务逻辑与实现细节:依赖倒置原则有助于将业务逻辑与实现细节解耦。通过定义抽象接口或抽象类,高层模块只需要关注业务逻辑,而具体的实现细节则可以由低层模块负责。这样一来,即使实现细节发生变化,也不会影响到高层模块的业务逻辑。

  2. 提高代码的可测试性:依赖倒置原则可以使代码更容易进行单元测试。由于高层模块依赖于抽象接口或抽象类,可以通过使用模拟对象或桩对象来替代具体的实现类进行测试,从而更方便地进行单元测试。

  3. 促进面向接口编程:依赖倒置原则鼓励面向接口编程,而不是面向实现编程。通过定义接口,可以明确规定模块之间的交互方式,提高代码的灵活性和可扩展性。

  4. 依赖注入(Dependency Injection):依赖倒置原则与依赖注入密切相关。依赖注入是一种设计模式,通过将依赖关系从代码内部移动到外部容器中,实现了高层模块对低层模块的解耦。依赖注入通常通过构造函数注入、属性注入或接口注入等方式来实现,可以有效地应用依赖倒置原则。

  5. 应用于设计模式:依赖倒置原则是许多设计模式的基础原则之一,例如工厂模式、策略模式、观察者模式等。这些设计模式都是通过定义抽象接口或抽象类,实现了高层模块和低层模块之间的解耦,从而提高了代码的灵活性和可维护性。

总之,依赖倒置原则是面向对象设计的重要原则之一,它促使我们在设计系统时应该尽量使用抽象来降低模块之间的耦合度,,同时促进了面向接口编程和依赖注入等良好的编程实践,从而实现系统的灵活性、可扩展性和可维护性。

接口隔离原则【Interface Segregation Principle】

接口隔离原则(Interface Segregation Principle,ISP)是面向对象设计中的重要原则之一,它强调设计接口时应该保持高内聚性和低耦合性,以提高系统的灵活性、可维护性和可扩展性。

ISP源于SOLID设计原则之一,旨在指导如何设计接口以满足面向对象设计的基本原则。该原则强调了接口的设计应该精简、专注,并且每个接口应该服务于特定的子模块或业务逻辑,避免一个臃肿的接口包含过多的方法,以减少接口之间的耦合度,提高系统的灵活性。

定义描述

  • 第一种定义: Clients should not be forced to depend upon interfaces that they don't use.

    • 客户端不应该依赖它不需用的接口。
  • 第二种定义: The dependency of one class to another one should depend on the smallest possible interface.

    • 类间的依赖关系应该建立在最小的接口上。

这两种定义都强调了接口应该尽可能小,且与特定的业务逻辑或子模块相关联。这样做有助于避免不相关的类或模块依赖于同一个接口,从而减少了系统的耦合度。

解释说明

接口隔离原则的核心概念是将一个臃肿的接口分解为多个专注的小接口。这意味着一个接口应该只包含与特定子模块或业务逻辑相关的方法,而不应该包含与其他模块无关的方法。这样的设计保证了接口的粒度尽可能小,而接口中的方法尽可能少,以满足“定制服务”的要求。

主要原则:

  1. 接口尽量要小:这个原则强调接口的设计应当遵循单一职责原则,每个接口应该只服务于一个子模块或业务逻辑,不应该设计臃肿的接口,避免“Fat Interface”。

  2. 接口要高内聚:高内聚的接口意味着相关的方法应该组织在一起,减少对外的交互,降低耦合度。这与将接口分解为专注的小接口密切相关,也可以视为接口尽量要小的一部分。

  3. 定制服务:为不同的模块或业务逻辑提供专门定制的接口,避免一种“一刀切”的方式。这个原则可以看作是接口要高内聚的延伸,即不同的模块应该有针对性地使用接口,提高系统的灵活性和可维护性。

  4. 分解臃肿接口:这个原则强调了将一个大而臃肿的接口分解为多个专注的小接口,每个小接口服务于特定的子模块或功能。这与接口尽量要小以及接口要高内聚密切相关。

  5. 专注的小接口:每个小接口应该只包含与其功能相关的方法,避免将不相关的方法放在同一个接口中。这也是将臃肿的接口分解为多个专注的小接口的具体实践。

如何实践接口隔离原则:

  • 按需定制接口,尽量避免“一刀切”的设计。
  • 遵循单一职责原则,确保每个接口只服务于一个子模块或业务逻辑。
  • 不断回顾和优化接口设计,避免接口过度臃肿。
  • 根据经验和常识决定接口的粒度大小,避免过度设计和不足设计。
  • 实践经验和领悟,根据项目需求和实际情况灵活运用接口隔离原则。

接口隔离原则的正确实践能够提高系统的灵活性、可维护性和可扩展性,降低系统的耦合度,使系统更加健壮和可靠。

优势

  • 定制服务: 通过将接口细分为小而专注的接口,可以为不同的模块或业务逻辑提供定制服务,满足各个模块的需求,提高了系统的灵活性和可维护性。

  • 降低耦合度: 接口粒度较小、方法较少的设计降低了接口之间的耦合度,减少了变更的传播范围,使得系统更加稳定和可靠。

  • 清晰明确: 每个接口都专注于特定的功能或子模块,使得接口的用途更加清晰明确,降低了对接口的误用和滥用的可能性。

总结

接口隔离原则是设计优秀的面向对象系统的基础之一。通过细化、定制和高内聚的接口设计,可以有效地降低系统的复杂度,提高系统的可维护性和可扩展性,从而使系统更加健壮和可靠。

迪米特法则【Low Of Demeter】

迪米特法则(Law of Demeter)是一项面向对象设计的原则,也被称为最少知识原则(Least Knowledge Principle,LKP)。该原则旨在降低对象之间的耦合度,使系统更具灵活性和可维护性。迪米特法则强调了对象应该尽可能少地了解其他对象的内部结构和实现细节,只与直接的朋友进行通信。

四层含义

具体来说,迪米特法则可以被解释为:

  1. 只和朋友交流:这一层含义强调了对象之间的通信方式。根据迪米特法则,一个对象应该只与其直接的朋友进行通信,而不应该直接与非直接朋友通信。直接的朋友包括出现在成员变量、方法的返回值以及通过方法参数传递的对象。通过与直接朋友交流,可以减少对象之间的耦合度,提高系统的灵活性和可维护性。这意味着对象应该尽量避免直接调用非直接朋友的方法,而应该通过直接朋友提供的接口进行通信。

  2. 朋友间也是有距离的:这一层含义指出即使是朋友之间的通信,也应该保持一定的距离。对象不应该过度了解其朋友对象的内部结构和实现细节,而应该通过公开的接口来进行通信。这样可以降低对象之间的耦合度,使系统更加灵活和可维护。虽然对象之间存在朋友关系,但过度依赖朋友对象的内部实现会导致代码的脆弱性和不稳定性,因此需要保持一定的距离,避免过于密切的通信。

  3. 是自己的就是自己的:这一层含义强调了对象应该尽可能地处理自己的事务,而不是依赖其他对象来完成自己的任务。对象应该尽量少地暴露自己的内部状态和行为,以减少对外部环境的依赖。通过封装对象的内部实现细节,可以提高对象的内聚性和封装性,使其更加独立和可重用。这样可以降低对象之间的耦合度,减少对其他对象的依赖,提高系统的稳定性和可维护性。

  4. 谨慎使用 Serializable:Serializable 接口用于将对象转换为字节流以进行网络传输或持久化存储。然而,使用 Serializable 接口会增加对象之间的耦合度,并可能导致意外的行为。因此,在使用 Serializable 接口时需要谨慎考虑,并确保对象的修改不会影响到系统的其他部分。Serializable 接口可能会暴露对象的内部实现细节,使其对外部环境产生依赖,从而增加系统的脆弱性。为了降低耦合度,可以考虑使用其他替代方案来进行对象的序列化和反序列化,或者通过设计模式来解耦对象之间的依赖关系。

核心思想

迪米特法则的核心思想是类间解耦,通过弱耦合来提高类的复用率和系统的灵活性。它要求对象之间尽量减少直接的通信,避免过度依赖其他对象的内部实现细节。

 这一原则强调了弱耦合的重要性,以增加类的复用率,并降低代码的耦合程度。在实践中,迪米特法则可以帮助开发人员设计出更加松耦合、模块化的系统,提高代码的可维护性和可扩展性。

具体而言,迪米特法则要求:

  1. 减少直接通信:对象应该尽可能少地了解其他对象的内部实现细节,只与其直接的朋友进行通信。这意味着对象应该通过接口来与其他对象进行交互,而不是直接访问其内部状态或调用其方法。

  2. 避免过度依赖:一个对象不应该过度依赖其他对象的内部实现细节,而应该依赖于抽象接口。这样可以降低对象之间的耦合度,使系统更加灵活,更易于维护和修改。

  3. 弱耦合提高复用率:通过减少对象之间的直接依赖关系,可以提高类的复用率。当一个类的内部实现发生变化时,只有与之直接交互的类需要进行相应的调整,而其他类不受影响,从而提高了代码的可维护性和可扩展性。

在实践中,遵循迪米特法则可以帮助开发人员设计出松耦合、模块化的系统架构。通过定义清晰的接口和抽象层,可以将系统拆分为相互独立的模块,每个模块都专注于自己的功能,降低了模块之间的耦合度,同时也提高了代码的可读性和可维护性。

开闭原则【Open Close Principle】

定义和原理

开闭原则(Open Close Principle,OCP)是面向对象设计中的一个重要原则,由勃兰特·梅耶(Bertrand Meyer)提出。该原则强调软件实体(如类、模块、函数等)应该对扩展开放,对修改关闭。简而言之,就是一个软件实体应该通过扩展来实现变化,而不是通过修改已有的代码来实现变化。

具体来说,开闭原则包含以下几个核心概念:

  1. 对扩展开放(Open for Extension):意味着软件实体应该允许在不修改原有代码的情况下进行功能的扩展。这通常通过创建新的类、接口、方法等来实现,以满足新的需求或变化的业务逻辑。

  2. 对修改关闭(Closed for Modification):意味着软件实体的内部结构和实现应该对外部不可见,不应该直接修改已有的代码。这样可以避免对已有功能的破坏,确保系统的稳定性和可靠性。

开闭原则的目的是使系统更加稳定、灵活和可扩展,从而降低软件开发和维护的成本。通过遵循开闭原则

实现方式

  • 多态性:通过多态性,可以在不修改现有代码的情况下,通过子类扩展父类的功能。
  • 依赖注入:使用依赖注入可以通过接口或抽象类传递依赖,从而在不修改现有类的情况下,替换或增加新的实现。
  • 策略模式:策略模式将算法封装在独立的策略类中,并使用组合或依赖注入的方式将策略注入到上下文中,从而可以灵活地切换和扩展算法而不修改现有的代码。
  • 模板方法模式:模板方法模式将算法的骨架定义在抽象类中,具体的步骤由子类实现。这样可以在不修改模板方法的情况下,通过扩展子类来修改具体的步骤。
  • 观察者模式:观察者模式定义了一种一对多的依赖关系,当一个对象的状态发生变化时,其所有依赖的对象都会得到通知。这样可以在不修改被观察对象的情况下,通过添加或删除观察者来实现新的功能。

优点

  • 可维护性:开闭原则通过封装和抽象,减少对已有代码的修改,从而提高了系统的可维护性。由于不需要频繁地修改已有的代码,系统更加稳定,容易被理解和维护。当需要修改功能或适应新的需求时,可以通过扩展已有代码来实现,而不会对现有功能产生影响。
  • 可扩展性:开闭原则鼓励通过扩展而不是修改现有代码来添加新的功能或适应新的需求,从而提高了系统的可扩展性。通过定义良好的接口和抽象类,并使用多态性和依赖注入等技术,可以轻松地添加新的功能或替换现有的实现,而不会影响到现有的代码。
  • 复用性:开闭原则通过多态、接口、抽象类等方式实现了代码的复用,减少了重复编码的工作量。通过定义通用的接口和抽象类,可以实现不同类之间的高度相似性和可替换性,从而提高了代码的复用性。这种复用性使得系统更加灵活,减少了开发时间和成本。

开闭原则的优点并不仅仅体现在代码层面,还体现在系统架构和设计理念上。通过遵循开闭原则,我们可以设计出更加模块化、可扩展和可维护的系统,从而降低了系统的风险和维护成本。开闭原则也是设计模式的基础之一,在实际的软件开发中具有广泛的应用价值。 

注意事项

1. 适度修改

开闭原则并非绝对禁止修改已有的代码,而是要尽量减少修改的频率和范围。在进行修改时,需要仔细考虑修改的必要性,并确保修改不会对现有的功能产生负面影响。只有在确实有必要时才进行修改,避免不必要的代码重构和风险。

2. 合理扩展

对扩展开放并不意味着随意添加新的功能,而是要根据需求合理地设计和组织代码,使得系统更加灵活和可扩展。在设计新功能时,需要考虑与现有代码的兼容性和一致性,避免破坏现有的设计和逻辑。通过良好的设计和规范,确保新功能的添加不会影响到现有的系统稳定性和可维护性。

3. 灵活应对变化

开闭原则的目标是使系统更加灵活和可维护,因此在面对需求变化时,我们应该采取灵活的策略来应对。通过设计良好的接口和抽象类,以及采用面向对象的设计原则,可以使系统更加适应变化,轻松地添加新的功能或调整现有的实现。灵活应对变化是保持系统长期健康发展的关键。

  • 7
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值