当前位置: 首页 > article >正文

面向对象的设计原则与设计模式

目的

设计模式的目的是提高代码的重用性,可读性、可扩展性、可靠性,使程序呈现高内聚,低耦合的特性


原则

单一职责原则

假设有一个class负责两个职责,一旦发生需求变更,修改其中一个职责的逻辑代码,有可能会导致另一个职责的功能发生故障。这样一来,这个class就存在两个导致类变更的原因。如何解决这个问题呢?我们就要分别用两个Class来实现两个职责,进行解耦。后期需求变更维护互不影响。这样的设计,可以降低类的复杂度,提高类的可读性,提高系统的可维护性,降低变更引起的风险

单一职责注意事项:

降低类的复杂度,一个类只负责一项职责;

提高类的可读性,可维护性;

降低变更引起的风险。


依赖倒置原则

依赖倒置原则(Dependency Inversion Principle, DIP) :指设计代码结构时,高层模块不应该依赖底层模块,二者都应该依赖其抽象。抽象不应该依赖细节,细节应该依赖抽象。通过依赖倒置,可以降低类与类之间的耦合性,提高系统的稳定性,提高代码的可读性和可维护性,并降低修改程序带来的风险。

依赖倒置原则注意事项:

变量的声明类型尽量是抽象类接口,这样我们的变量引用和实际对象间,就存在一个缓冲层,利于程序扩展优化

抽象为基准比以细节为基准搭建起来的架构要稳定得多,因此大家再拿到需求后,要面向抽象编程,按照先顶层再细节的顺序设计代码结构。


开闭原则

开闭原则(Open-Closed PrincipleOCP) :指一个软件实体如类、模块和函数应该扩展开放修改关闭。强调的是用抽象构建框架,用实现扩展细节,当软件需要变化时,尽量通过扩展软件实体的行为来实现变化,而不是通过修改已有的代码来实现变化,可以提高软件系统的可复用性及可维护性。

本质:

本质是指:当在一个设计中增加新的模块时,不需要修改现有的模块。

开闭原则是面向对象设计中最基础的设计原则,他的核心思想是面向抽象编程。


依赖倒置原则与开闭原则的关系:

依赖倒置原则是程序要依赖于抽象接口,不要依赖于具体实现。

当设计某些系统时,经常需要面向抽象来考虑系统的总体设计,不要考虑具体类,这样容易设计出满足“开-闭原则”的系统。

在程序设计好以后,首先要对抽象类(或接口)的修改关闭,否则,一旦修改抽象类(或接口),将可能导致它的所有子类(或实现类)都需要作出修改;应当对增加抽象类的子类(或接口的实现类)开放,即在增加新的子类(或实现类)时,不需要修改其他面向抽象类(或接口)而设计的重要类,例如案例中的Pillar类。


接口隔离原则

接口隔离原则(Interface Segregation Principle, ISP):指用多个专门的接口,而不使用单一的总接口,客户端不应该依赖它不需要的接口。

接口隔离原则注意:

一个类对另一个类的依赖应该建立在最小接口上。

建立单一接口,不要建立庞大臃肿的接口。

尽量细化接口,接口中的方法尽量少(不是越少越好,一定要适度)。


里氏替换原则

里氏替换原则(Liskow Substitution PrincipleLSP) :如果对每个类型为T1的对象o1,都有类型为T2的对象o2,使得以T1定义的所有程序P的所有的对象o1都代换成o2时,程序P的行为没有发生变化,那么类型T2是类型T1的子类型。

可以理解为一个软件实体如果适用于一个父类,则一定适用于其子类,所有引用父类的地方必须能透明地使用其子类对象,子类对象能够替换父类对象,而程序逻辑不变。也可以理解为,子类可以扩展父类的功能,但不能改变父类原有的功能。


迪米特法则

迪米特法则(Law of DemeterLoD) :又叫最少知道原则,即一个类对自己依赖的类知道的越少越好,尽量降低类与类之间的耦合。也就是说,对于被依赖的类不管多么复杂,都尽量将逻辑封装在类的内部。对外除了提供public方法,不对外泄露任何信息。

迪米特法则还有个更简单的定义:只与朋友说话,不和陌生人说话。朋友:出现在成员变量、方法参数,方法返回值中的类为直接的朋友,出现在方法体内部的类不属于朋友类。


组合复用原则

组合复用原则(Composite Reuse Principle, CRP) :尽量使用对象组合has-a)或对象聚合contains-a)的方法实现代码复用,而不是用继承关系达到代码复用的目的。合成复用原则可以使系统更加灵活,降低类与类之间的耦合度,一个类的变化对其他类造成的影响相对较小

设计原则

一句话归纳

目的

单一职责原则

一个只干一件事

便于理解,提高代码可读性

依赖倒置原则

面向抽象

降低维护带来的新风险

开闭原则

对扩展开放,对修改关闭

更利于代码结构的升级扩展

接口隔离原则

一个接口只干一件事

提高内聚,减少对外交互

里氏替换原则

子类重写方法功能发生改变不应该影响父类方法的含义

提高代码健壮性及复用性

迪米特法则

不该知道的不要知道

解耦,高内聚,低耦合

组合复用原则

尽量是用组合实现代码复用,而不使用继承

降低类之间的耦合度


设计模式的分类

一般可以按照设计模式的目的(模式是用来做什么的)将其分为创建型(Creational)结构型(Structural)行为型(Behavioral)3种:

 创建型模式主要用于创建对象

 结构型模式主要用于处理类或对象的组合

 行为型模式主要用于描述对类或对象怎样交互怎样分配职责


创建型模式:

涉及对象的实例化这类模式的特点是,不让用户代码依赖于对象的创建或排列方式,避免用户直接使用new运算符创建对象包括:

抽象工厂模式(Abstract Factory)

建造者模式(Builder):又称生成器模式

工厂方法模式(Factory Method)

原型模式(Prototype)

单例模式(Singleton)  :又称单件模式


结构型模式:

涉及如何组合类和对象以形成更大的结构,和类有关的结构型模式涉及如何合理地使用继承机制,和对象有关的结构型模式涉及如何合理地使用对象组合机制。包括:

抽象适配器模式(Adapter)

桥接模式(Bridge)

组合模式(Composite)

装饰模式(Decorator)

外观模式(Facade)

享元模式(Flyweight)

代理模式(Proxy)


行为型模式:

涉及怎样合理地设计对象之间的交互通信,以及怎样合理地为对象分配职责,让设计富有弹性、易维护、易复用。包括:

职责链模式(Chain of Responsibility)

命令模式(Command)

解释器模式(Interpreter)

迭代器模式(Iterator)

中介者模式(Mediator)

备忘录模式(Memento)

观察者模式(Observer)

策略模式(Strategy)

状态模式(State)

模板方法模式(Template Method)

访问者模式(Visitor)


简单工厂模式

模式定义

简单工厂模式(Simple Factory Pattern):又称为静态工厂方法(Static Factory Method)模式,它属于类创建型模式。在简单工厂模式中,可以根据参数的不同返回不同类的实例。简单工厂模式专门定义一个类来负责创建其他类的实例被创建的实例通常都具有共同的父类

简单工厂模式的优点

工厂类含有必要的判断逻辑,可以决定在什么时候创建哪一个产品类的实例,客户端可以免除直接创建产品对象的责任,而仅仅“消费”产品;简单工厂模式通过这种做法实现了对责任的分割,它提供了专门的工厂类用于创建对象

客户端无须知道所创建的具体产品类的类名,只需要知道具体产品类所对应的参数即可,对于一些复杂的类名,通过简单工厂模式可以减少使用者的记忆量。

通过引入配置文件,可以在不修改任何客户端代码的情况下更换和增加新的具体产品类,在一定程度上提高了系统的灵活性。

简单工厂模式的缺点

由于工厂类集中了所有产品创建逻辑,一旦不能正常工作,整个系统都要受到影响

使用简单工厂模式将会增加系统中类的个数,在一定程序上增加了系统的复杂度和理解难度。

系统扩展困难,一旦添加新产品就不得不修改工厂逻辑,在产品类型较多时,有可能造成工厂逻辑过于复杂,不利于系统的扩展和维护。

简单工厂模式由于使用了静态工厂方法,造成工厂角色无法形成基于继承的等级结构


http://www.kler.cn/a/456979.html

相关文章:

  • android studio gradle 如何解决下载依赖一直卡住的问题
  • Kerberos用户认证-数据安全-简单了解-230403
  • 【中间件】docker+kafka单节点部署---zookeeper模式
  • 计算机网络 (7)物理层下面的传输媒体
  • Kubernetes Gateway API-2-跨命名空间路由
  • uniapp——APP读取bin文件,解析文件的数据内容(二)
  • HuggingFace peft LoRA 微调 LLaMA
  • Mysql数据库中,监测某张表中某字段的修改情况(被哪个ip所修改、新老值)
  • InceptionNeXt: When Inception Meets ConvNeXt
  • 不安全物联网的轻量级加密:综述
  • 【最新】宇鹿家政小程序系统v1.1.3高级版源码全开源+搭建环境
  • 太通透了,Android 流程分析 蓝牙enable流程(stack/hidl)
  • 配置vue2项目中组件命名忽略大小写
  • ch.h:38:10:致命错误: rpc/rpc.h:没有那个文件或目录38 I#include <rpc/rpc.h>
  • 【Java基础面试题041】Java中的深拷贝和浅拷贝有什么区别?
  • 解决tomcat双击startup.bat乱码的几种方法
  • 前端+后端之网站部署(Front End and Backend Website Deployment)
  • TCP Analysis Flags 之 TCP Out-Of-Order
  • C++的第一个程序
  • 1228java面经
  • Mybatis插件better-mybatis-generator的下载与使用
  • 为什么深度学习和神经网络要使用 GPU?
  • 数据标注的流程
  • C#中的属性索引器(Indexer)
  • JavaScript 箭头函数
  • 强化特种作业管理,筑牢安全生产防线