面向对象设计原则实践:之一.开放封闭原则

简述SOLID的面向对象的设计原则 在这篇博文中,将给大家简要介绍一下SOLID的面向对象的设计与实现的基本原则。其实这个需要自己做项目和看代码的体会,个人经验觉得还是比较有用的。 什么是SOLID SOLID是面向对象设计与实现的时候推荐的一个基本的原则,分别是Single Responsibility Principle(单一职能原则),Open Close Principle(开放封闭原则), Liskov’s Subst 阅读详情

常用的面向对象设计原则包括7个,这些原则并不是孤立存在的,它们相互依赖,相互补充。

名称

易记符

设计原则及简介

实现关键

关系

重要性

开放封闭原则

开放闭合

程序对扩展是开放的,对修改是封装的。

即在不修改原有功能的基础上扩展其功能

抽象化;将可变因素封装;

最重要的原则

5

单一职责

职责单一

一个对象应该只包含单一的职责,

并且该职责被完整地封装在一个类中

归纳与抽象类的不同职责,并将其分离

是实现高内聚、

低耦合的指导方针

4

接口隔离原则

接口单一交互

客户端不应该依赖那些它不需要的接口

组合多个专一的接口实现总的接口

 

2

迪米特原则

中间类交互

一个软件实体应当尽可能少的

与其他实体发生相互作用

使用 中间类 进行间接交互

 

3

合成复用

组合聚合

继承关系的是静态的;

关联、组合、聚合关系的动态的

尽量使用关联、组合、聚合关系,少用继承。

 

4

      

依赖倒转原则

抽象类依赖

所有模块都依赖于抽象类;

客户端与实现类之间以抽象类进行耦合

通过抽象类进行耦合

最主要的实现手段

5

里氏代换

基类定义,

子类运行

所有引用基类(父类)的地方,

必须能透明地使用其子类的对象

在程序定义中,

使用基类类型来对对象进行定义,

在程序运行时,

确定其子类类型,用子类对象来替换父类对象 

实现开闭原则的

重要方式之一

4

 

一、开放封闭原则(Open-Closed principle)

1.  开闭原则定义

一个软件实体应当对扩展开放,对修改关闭。

也就是说在设计一个模块的时候,应当使这个模块可以在不被修改的前提下进行扩展,

即软件实体应当在不修改的前提下扩展。 

 

2.  开闭原则分析

(1)开闭原则由Bertrand Meyer于1988年提出,它是面向对象设计中最重要的原则之一。

(2)在开闭原则的定义中,软件实体可以指一个软件模块、一个由多个类组成的局部结构或一个独立的类。

(3)抽象化是开闭原则的关键。

(4)开闭原则还可以通过一个更加具体的“对可变性封装原则”来描述,

对可变性封装原则(Principle of Encapsulation of Variation,EVP)要求找到系统的可变因素并将其封装起来。

 

3.  实例一

某图形界面系统提供了各种不同形状的按钮,客户端代码可针对这些按钮进行编程,

用户可能会改变需求要求使用不同的按钮,原始设计方案如图所示:

开闭原则-图-1

现对该系统进行重构,使之满足开闭原则的要求。

开闭原则-图-2

 

对比分析

图(1):客户端的一个方法直接调用加法类,但是我想添加一个减法类,

你就会发现添加减法类就得改变加法类中代码(用switch语句实现),这就违背了“开闭原则”

图(2):在这个图中我们添加了一个运算类的父类,这样我们再添加减法类的时候就不用修改客户端类。

 

用【策略模式】实现这个方案的代码如下:

#include <stdio.h>

#include <stdlib.h>

#include <iostream>

#include <string>



using namespace std;



/* Step1: 使用vitual定义函数的功能模块,相当于实现公共界面设计 */

class IGetResult {

public:

//virtual double get_result(double numberA, double numberB) = 0;

virtual double get_result() = 0;



public:

/* 注意一定要不要忘记添加虚—析构函数 */

virtual ~IGetResult(){}

};



/* Step2 : 继承基类,定义具体的功能模块,并声明具体需要的私有成员变量 */

class Add : public IGetResult {

public:

Add(double a, double b){

std::cout << "Add" << endl;



m_numberA = a;

m_numberB = b;

};

~Add(void) {};



public:

double get_result();

private:

double m_numberA;

double m_numberB;

};



/* 实现具体的功能模块 */

double Add::get_result() {

std::cout << "Add::get_result()" << endl;



return m_numberA + m_numberB;

}



class Del : public IGetResult {

public:

Del(double a, double b){

std::cout << "Del" << endl;

m_numberA = a;

m_numberB = b;

};

virtual ~Del(void) {};

public:

double get_result();

private:

double m_numberA;

double m_numberB;

};



double Del::get_result(){

std::cout << "Del::get_result()" << endl;

return m_numberA - m_numberB;

}



int main(int argc, char* argv[]){

std::cout << "main()" << endl;

int a = 22;

int b = 10;

int ret = 0;

Add add = Add(a, b);

ret = add.get_result();

std::cout << "ret = " << ret << endl;





Del del = Del(a, b);

ret = del.get_result();

std::cout << "ret = " << ret << endl;

return 0;

}

编译:

g++ -Wall -g strategy-pattern.cpp -o strategy

 

运行结果:

main()

Add

Add::get_result()

ret = 32

Del

Del::get_result()

ret = 12

 

 

4. 实例二

假如,我们要写一个工资税类,工资税在不同国家有不同计算规则。

如果我们不坚持OCP,直接写一个类封装工资税的算税方法,而每个国家对工资税的具体实现细节是不尽相同的!

如果我们允许修改,即把现在系统需要的所有工资税(中国工资税、美国工资税等)都放在一个类里实现,

谁也不能保证未来系统不会被卖到日本,一旦出现新的工资税,而在软件中必须要实现这种工资税,

这个时候我们能做的只有找出这个类文件,在每个方法里加上日本税的实现细节并重新编译库。

虽然我们只要将新的库覆盖到原有的库即可,并不影响现有程序的正常运行,

但每次出现新情况都要找出类文件,添加新的实现细节,

这个类文件不断扩大,以后维护起来就变的越来越困难,也并不满足我们以前说的单一职责原则(SRP),

因为不同国家的工资税变化都会引起对这个类的改变动机!

 

如果我们在设计这个类的时候坚持了OCP的话,把工资税的公共方法抽象出来做成一个接口,封闭修改,

在客户端(使用该接口的类对象)只依赖这个接口来实现对自己所需要的工资税,

以后如果系统需要增加新的工资税,只要扩展一个具体国家的工资税实现我们先前定义的接口,就可以正常使用,

而不必重新修改原有类文件! 

 

5. 实例三

下面这个例子就是既不开放也不封闭的,

因为Client和Server都是具体类,

如果我要Client使用不同的一个Server类那就要修改Client类中所有使用Server类的地方为新的Server类。 

class Client{  

Server server;  

void GetMessage(){  

server.Message();  

 }  

}  

 

class Server{  

void Message();  

}

 

下面为修改后符合OCP原则的实现,

我们看到Server类是从ClientInterface继承的,不过ClientInterface却不叫ServerInterface,

原因是我们希望对Client来说ClientInterface是固定下来的,变化的只是Server。

这实际上就变成了一种策略模式(Gof Strategy) 

 

interface ClientInterface{  

public void Message();  

//Other functions  

}  

 

class Server:ClientInterface{  

public void Message();  

}  

 

class Client {  

ClientInterface ci;  

 public void GetMessage(){  

ci.Message();  

}  

public void Client(ClientInterface paramCi){  

ci=paramCi;  

}  

}  

 

//那么在主函数(或主控端)则  

public static void Main(){  

ClientInterface ci = new Server();  

//在上面如果有新的Server类只要替换Server()就行了.  

Client client = new Client(ci);  

client.GetMessage();  

}

 

6. 实例四

使用Template Method实现OCP:

abstract class Policy{

private int[] i ={ 1, 1234, 1234, 1234, 132 };

public bool Sort(){

SortImp();

}

protected virtual bool SortImp(){

 

}

}

 

class Bubbleimp : Policy{

protected override bool SortImp(){

//冒泡排序

}

}

class Bintreeimp : Policy{

protected override bool SortImp(){

//二分法排序

}

}

 

//主函数中实现

static void Main(string[] args){

//如果要使用冒泡排序,只要把下面的Bintreeimp改为Bubbleimp

Policy sort = new Bintreeimp();

sort.Sort();

}  

 

7. 开闭原则总结

面对需求,对程序的改动是通过增加新代码进行的,而不是改变原来的代码。

 

OCP优点: 

1)、降低程序各部分之间的耦合性,使程序模块互换成为可能; 

2)、使软件各部分便于单元测试,通过编制与接口一致的模拟类(Mock),可以很容易地实现软件各部分的单元测试; 

3)、利于实现软件的模块的互换,软件升级时可以只部署发生变化的部分,而不会影响其它部分; 

 

使用OCP注意点: 

1)、实现OCP原则的关键是抽象; 

2)、两种安全的实现开闭原则的设计模式是:Strategy pattern(策略模式),Template Methord(模版方法模式); 

3)、依据开闭原则,我们尽量不要修改类,只扩展类,

但在有些情况下会出现一些比较怪异的状况,这时可以采用几个类进行组合来完成; 

4)、将可能发生变化的部分封装成一个对象,如: 状态, 消息,,算法,数据结构等等 ,

封装变化是实现"开闭原则"的一个重要手段,如经常发生变化的状态值,如温度,气压,颜色,积分,排名等等,

可以将这些作为独立的属性,如果参数之间有关系,有必要进行抽象。

对于行为,如果是基本不变的,则可以直接作为对象的方法,否则考虑抽象或者封装这些行为; 

5)、在许多方面,OCP是面向对象设计的核心所在。

遵循这个原则可带来面向对象技术所声称的巨大好处(灵活性、可重用性以及可维护性)。

然而,对于应用程序的每个部分都肆意地进行抽象并不是一个好主意。

应该仅仅对程序中呈现出频繁变化的那部分作出抽象。拒绝不成熟的抽象和抽象本身一样重要

 

 

面向对象设计原则总结 参考博文:http://www.cnblogs.com/shaosks/category/351488.html 面向对象设计的原则主要有:单一职责原则,开放封闭原则,里氏替换原则,依赖倒置原则,迪米特法则,合成/聚合复用原则。下面将对每个原则做一个学习理解与总结,加深对面向对象的理解,促进工作中对这些原则的运用。 1、单一职责原则(Single Responsibility Principl 阅读详情

相关推荐

【嵌入式面经】上海 70迈 线上笔试

“关注|点赞|收藏” 福利干货第一时间送达!最近在做免费的嵌入式知识分享,帮助对嵌入式感兴趣的同学学习嵌入式、做项目、找工作!

qq_56921854的博客 1139

开闭原则

一、什么是开闭原则 开闭原则(Open-Closed Principle, OCP)是指一个软件实体如类、模块和函数应该对扩展开放, 对修改关闭。所谓的开闭,也正是对扩展和修改两个行为的一个原则。强调的是用抽象构建框架,用实 现扩展细节。可以提高软件系统的可复用性及可维护性。开闭原则,是面向对象设计中最基础的设计原 则。它指导我们如何建立稳定灵活的系统,例如:我们版本更新,我尽可能不修改源代码,...

Mark-Zoe的博客 4052

如何设计一个低代码平台

近些年来,低代码发展火热,各种低代码平台如雨后春笋纷纷崛起,这些平台各定位不同,优劣不同,用户的选择空间很大。那么,如果用户想从零开始设计一个低代码平台,该如何做呢?

Jarod_Chou的博客 8260

类设计-开闭、单一、里氏替换、依赖倒置、接口隔离、迪米特原则

某图形界面系统提供了各种不同形状的按钮,客户端代码科针对这些按钮进行编程,用户可能会改变要求使用不同的按钮,原始设计如图1所示。 画出利用开闭原则重构后的类图。 结合题目分析这个类图,题目中说到“用户可能会改变要求使用不同的按钮”,而且要求我们利用开闭原则画出重构后的类图。 开闭原则:可以增加按钮,但是不能修改原来的代码。 我们都知道抽象比较稳定,所以这里使用抽象,那用接口还是抽象类呢?我的选择是抽象类,因为这里需要抽象的是按钮,抽象的物,不是按钮的操作,所以我们选择抽象类。 public abs..

blue_mxy的博客 956

告别ROS1思维:在ROS2 Humble上,用Python搞定MoveIt2机械臂控制的完整流程

本文详细介绍了在ROS2 Humble环境下使用Python控制MoveIt2机械臂的完整流程。从环境配置、架构变革到实战操作,涵盖URDF适配、Action接口编程及性能优化技巧,帮助开发者高效迁移ROS1项目至ROS2平台,实现工业级机械臂控制。

weixin_30352645的博客 450

【ESP32-S3量产指南】基于Flash下载工具实现Release模式Flash加密与安全配置

本文详细介绍了ESP32-S3量产阶段如何通过Flash下载工具实现Release模式下的Flash加密与安全配置。从加密模式选择、工具配置到分区表优化,提供了一套完整的量产安全解决方案,帮助开发者有效防止固件泄露和篡改,确保设备安全。

weixin_28730131的博客 231

软件系统设计-1-软件设计原则

软件系统设计-1-软件设计原则

SpriCoder的博客 3430

UE4免费资产库新玩法:Quixel Bridge插件安装与Megascans资源导入全攻略

本文详细介绍了如何在UE4中安装Quixel Bridge插件并导入Megascans资源,帮助开发者快速获取高质量3D资产。通过分步教程和实用技巧,提升游戏或影视场景的制作效率,特别适合需要真实感环境的项目。

weixin_27729671的博客 367

面向对象设计原则(二):开放-封闭原则(OCP)

开放-封闭原则(Open-closed principle,OCP)也称开闭原则,是面向对象设计(OOD)中比较重要的一种,下面来总结开放-封闭原则的知识点,包括:1、什么是开放-封闭原则?2、为什么需要遵守开放-封闭原则?3、怎么做到开放-封闭原则?4、开放-封闭原则需要注意什么?

tjiyu的博客 4931

银河麒麟arm64 V10 SP1桌面系统高效部署onnxruntime推理环境实战

本文详细介绍了在银河麒麟arm64 V10 SP1桌面系统上高效部署onnxruntime推理环境的完整实战流程。从系统环境准备、关键依赖安装,到onnxruntime的安装验证,并以YOLOv5模型部署为例进行性能对比分析,提供了在国产化飞腾D2000平台上进行AI边缘推理的实用指南和避坑技巧。

ss78901的博客 636

SAP 实施:Waterfall vs. Agile —— 一场“结构性矛盾“的深刻比较先说结论:在 SAP 世界里,这从来不是“谁更好“的宗教问题,而是“你的项目 DNA 是什么“的战略选择。​

SAP 实施:Waterfall vs. Agile —— 一场"结构性矛盾"的深刻比较 先说结论:在 SAP 世界里,这从来不是"谁更好"的宗教问题,而是"你的项目 DNA 是什么"的战略选择。​ SAP 早已用 SAP Activate​ 给出了官方态度——它不是纯 Agile,也不是回头去搞旧 Waterfall,而是一个带质量门的混合架构。 1. 先回到本质:两者解决的是不同维度的风险 维度 Waterfall(传统 ASAP 路线)​ Agile(SCRUM/Kanban 式迭代)​

金牌架构师 336

开放封闭原则的理解与具体实现 C#Unity

在软件、程序设计的时候,追求的目标是达到封装变化、降低耦合,来实现高内聚低耦合。开放封闭原则正是对这一目标的最直接体现,而其他的设计原则,很多时候也是为实现这一目标服务的。开放封闭原则(OCP,Open Closed Principle)是所有面向对象原则的核心其核心的思想是:软件实体应该是可扩展,而不可修改的。也就是说,对扩展是开放的,而对修改是封闭的。因此,开放封闭原则主要体现在两个方面:对扩展开放,意味着有新的需求或变化时,可以对现有代码进行扩展,以适应新的情况。

qq_60831089的博客 457

Ansible 面板工具之AWK ( Anssible Tower )界面介绍

整理这部分笔记博文内容为AWX和UI 界面的简单介绍理解不足小伙伴帮忙指正傍晚时分,你坐在屋檐下,看着天慢慢地黑下去,心里寂寞而凄凉,感到自己的生命被剥夺了。当时我是个年轻人,但我害怕这样生活下去,衰老下去。在我看来,这是比死亡更可怕的事。--------王小波这里AWX使用的是最新的版本AWX 21.7.0目前最新版是3.8.6,博客中的版本为3.5.0对于Redhat的,官网上看到在 2022 年 11 月之后不在维护了,改版之后现在叫,感兴趣小伙伴可以了解下虽然有AWX是。

山河已无恙 1303

《敏捷软件开发-原则、方法与实践》-Robert C. Martin读书笔记(转)

Review of Agile Software Development: Principles, Patterns, and Practices 本书主要包含4部分内容,这些内容对于今天的软件工程师都非常的重要,它们是: ●Agile方法:主要讲述了如何去使用Agile方法,其中有很大一部分内容是告诉你为什么要这样做。 ●面向对象设计原则:本书包含了11个面向对象设计原则...

weixin_33805743的博客 226

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

面向对象设计原则

面向对象设计原则 S.O.L.I.D S.O.L.I.D是面向对象设计和编程(OOD&OOP)中几个重要编码原则(Programming Priciple)的首字母缩写,是敏捷开发以及自适应软件开发的基本原则的重要组成部分。 简写 全拼 中文翻译 SRP The Single Responsibility Principle 单一职责原则 OCP The Open Cl...

Steven's blog 328

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

面向对象的三大特征和五大基本原则

在依赖之间定义一个抽象的接口,使得高层模块调用接口,而底层模块实现接口定义,以此来有效控制耦合关系,达到依赖于抽象的设计目标。实现方式:面向接口编程,将公共部分抽象为基类接口或抽象类,通过扩展抽象类,在子类中重写父类的方法实现新的方式支持同样的职责。接口隔离原则体现在:接口应该内聚,避免接口臃肿,一个类对另一个类的依赖应该建立在最小的接口上,不要强迫依赖不用的方法。通过面向对象的继承和多态机制,又可以实现对抽象类的继承,通过重写其方法来改变固有的行为,实现新的拓展,这就是开放。核心思想:依赖于抽象。

杰尼龟的小龟壳的博客 689

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

面向对象

面向对象(OOP) 什么是对象 抽象【类】实例化的集合 简单理解 面想对象【oop】可以看做是面向事件的结果,是相对于面向过程来说的,面向过程【pop】就是实现这一事件结果的具体过程 【“面向过程”(Procedure Oriented)【破涩i这 奥瑞忒的】是一种以过程为中心的编程思想。这些都是以什么正在发生为主要目标进行编程,不同于面向对象的是谁在受影响。与面向对象明显的不同就是封装、继承、类。简写为POP。】 面向对象是模型化的,其中包括三大特性:封装、继承、多态 五大原则 单一职责原则、开放封闭原则

龘 103

JAVA面向对象的学习(第一章)

文章目录一、面向对象是什么二、面向对象和面向过程的区别三、面向对象的三大特性四、五大基本原则:SPR, OCP, LSP, DIP, ISP 一、面向对象是什么 面向对象是一种软件开发思路 面向对象是模型化的,你只需抽象出一个类,这是一个封闭的盒子,在这里你拥有数据也拥有解决问题的方法。需要什么功能直接使用就可以了,不必去一步一步的实现,至于这个功能是如何实现的,管我们什么事?我们会用就可以了。 对象:对象是类的一个实例(对象不是找个女朋友),有状态和行为。例如,一条狗是一个对象,它的状态有:颜色、名字、

yancheng7747的博客 182

java开发五大原则_Java学习之路-五大基本原则

Java学习之路-五大基本原则Java学习之路-五大基本原则转载:https://github.com/hollischuang/toBeTopJavaer/blob/master/basics/java-basic/principle.md下面懒得打字了,就简称“哈理”吧单一职责原则(Single-Resposibility Principle)其核心思想为:一个类,最好只做一件事,只有一个引起...

weixin_31321361的博客 286

面向对象的5个基本设计原则

面向对象的3个基本要素:封装、继承、多态 面向对象的5个基本设计原则: 单一职责原则(Single-Resposibility Principle)     其核心思想为:一个类,最好只做一件事,只有一个引起它的变化。单一职责原则可以看做是低耦合、高内聚在面向对象原则上的引申,将职责定义为引起变化的原因,以提高内聚性来减少引起变化的原因。职责过多,可能引起它变化的原因就越多,这将导致职责依赖

luxiaoxun的专栏 4万+

[C++设计模式] 深入理解面向对象设计原则

深入理解面向对象的设计,简略讲解关于面向对象的设计原则。

kevin_blog 1349

面向对象五大设计原则-开放封闭原则

1、开放封闭原则 开放封闭原则(Close Open Principle),是指软件应该对扩展开放,而对修改封闭。在软件的生命周期内,需求变化是客观存在的且不以人的意志而转移,而对应的软件也必须做相应的变化。 对扩展开放:意味着有新的需求或变化时,可以对现有的系统进行扩展,以适应新的情况。 对修改关闭:在扩展原有系统的功能时,只需增加新的代码,而不需要对原有的代码进行修改。 2、不合理的设计示例 – 超人的超能力 超人拥有这几项超能力,但是在特殊的环境下需要隐身的超能力时,超人就必须回炉重造。

u014354882的博客 1248

面向对象七大设计原则之开放封闭原则

主要记录面向对象开放封闭原则的记录与分析。

nanyupeng的博客 566
上一篇: FFmpeg中的时间戳表示方法
下一篇: 面向对象设计原则实践.之二.依赖倒转原则
北雨南萍
北雨南萍 领域专家: 操作系统技术领域 领域专家: 操作系统技术领域
博客等级 码龄20年 2665粉丝 453原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

北雨南萍

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值