设计模式之空对象模式

news2024/11/24 5:43:33

目录

1.简介

2.结构图

3.实例

4.优缺点


1.简介

        空对象模式也是我们平时编程用的比较多的一种行为型设计模式,它的宗旨在解决空对象引起的异常报错问题;在空对象模式(Null Object Pattern)中,一个空对象取代 NULL 对象实例的检查。Null 对象不是检查空值,而是反应一个不做任何动作的关系。这样的 Null 对象也可以在数据不可用的时候提供默认的行为。

        在空对象模式中,我们创建一个指定各种要执行的操作的抽象类和扩展该类的实体类,还创建一个未对该类做任何实现的空对象类,该空对象类将无缝地使用在需要检查空值的地方。

        在C/C++编程中,如果一个接口返回一个对象指针,如:

    class AbstractObject{
    public:
        int compareTo(int value){
            //...
            return 0;
        }
    }
    AbstractObject* getValue(int n);

在接口调用的时候,IMessageField*  p =  getValue(100); 一般都是去判断 p 是否 为null,如果不判断p, 直接调用IMessageField的成员函数compareTo,程序就崩溃了;利用空对象模式就解决了这个问题,从而避免不管怎么调用都不会导致程序崩溃的情况,下面我们就看看怎么解决这个问题的。

2.结构图

空对象模式的UML类图如下:

由上图可以看到,空对象模式主要包含3个角色。
1) 抽象对象(AbstractObject):定义所有子类公有的行为和属性,一般定义一个isNull接口是不必可少的。
2) 真实对象(CRealObject):继承AbstractObject类,并实现所有行为。
3) 空对象(CNullObject):继承AbstractObject类,对父类方法和属性不做实现和赋值。

3.实例

真实对象和空对象定义如下:

#include <iostream>
#include <map>
#include <memory>

// 抽象对象
class AbstractObject {
public:
	virtual void doSomething() = 0;
	virtual bool isNull() const = 0;
};

// 真实对象1
class CRealObject1 : public AbstractObject {
public:
	void doSomething() override {
		std::cout << "CRealObject1 is doing something." << std::endl;
	}
	bool isNull() const override { return false; }
};

// 真实对象2
class CRealObject2 : public AbstractObject {
public:
	void doSomething() override {
		std::cout << "CRealObject2 is doing something." << std::endl;
	}
	bool isNull() const override { return false; }
};

// 真实对象3
class CRealObject3 : public AbstractObject {
public:
	void doSomething() override {
		std::cout << "CRealObject3 is doing something." << std::endl;
	}
	bool isNull() const override { return false; }
};

// 空对象
class CNullObject : public AbstractObject {
public:
	void doSomething() override {
		// 空对象不进行任何操作
	}
	bool isNull() const override { return true; }
};

class CMessageEntity
{
public:
	void  add(int value, AbstractObject* pObject) {
		m_objects[value] = pObject;
	}
	void  remove(int value) {
		m_objects.erase(value);
	}

	AbstractObject* getObject(int value) {
		static CNullObject s_nullObject;
		if (m_objects.find(value) != m_objects.end()) {
			return m_objects[value];
		}
		return &s_nullObject;
	}
private:
	std::map<int, AbstractObject*> m_objects;
};

测试例程如下:

int main() {
	std::unique_ptr<AbstractObject> obj1(new CRealObject1());
	std::unique_ptr<AbstractObject> obj2(new CRealObject2());
	std::unique_ptr<AbstractObject> obj3(new CRealObject3());

	CMessageEntity entities;

	entities.add(10, obj1.get());
	entities.add(20, obj2.get());
	entities.add(234, obj3.get());

	entities.getObject(20)->doSomething();  // 输出: CRealObject2 is doing something.
	entities.getObject(234)->doSomething(); // 输出: CRealObject3 is doing something.
	entities.getObject(0)->doSomething();   // 输出: 
	entities.getObject(10)->doSomething();  // 输出: CRealObject1 is doing something.

	return 0;
}

上述示例中,定义了一个抽象对象类AbstractObject,真实对象类CRealObject1、CRealObject2、CRealObject3和空对象类CNullObject都继承自抽象对象类。在主函数中,创建了三个真实对象和一个空对象,并调用它们的doSomething()方法。真实对象会执行具体的操作,而空对象不进行任何操作。通过使用空对象,可以避免对空值的检查,使得代码更加简洁和健壮。

4.优缺点

优点:
1.避免NullPointerException:这是空对象模式最主要的好处。通过提供一个空对象实例,可以避免在调用方法时抛出NullPointerException
2.改善代码质量:通过明确地表示一个对象是空的,可以使代码更具可读性,也减少了因为错误地使用空引用而导致的运行的错误。
3.更好的扩展性:如果一个类经常需要一个空实例,那么在将来需要改变这个类的行为时,可以更容易地适应这些变化
缺点:
1增加类的数量:为了使用空对象模式,口能需要为每一个类都提供一个空对象实现,这会增加类的数量,也可能会增加代码的复杂性。
2.不易发现错误:有时候,开发者可能会错误地认为空对象实例表示正常的操作,这可能导致在运行时出现难以发现的错误。
3.违反开放封闭原则:开放封闭原则鼓励的是添加新的行为,而不是新的具体类。而空对象模式需要为每个类添加新的空实现类,这似乎与开放封闭原则相违背。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1374052.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Redis常用连接工具

RedisInsight 官网地址&#xff1a; RedisInsight | The Best Redis GUI Redis Desktop Manager 官网地址&#xff1a; RedisInsight | The Best Redis GUI 样式&#xff1a; QuickRedis 官网地址&#xff1a; QuickOfficial - QuickRedis 样式&#xff1a; AnotherRed…

SSL证书链是什么?SSL证书链如何工作?

SSL证书链作为公钥基础设施&#xff08;PKI&#xff09;的一项关键功能&#xff0c;它支持许多与安全相关的服务&#xff0c;包括数据机密性、数据完整性和最终实体身份验证&#xff0c;它使得互联网上的安全在线通信成为可能。那么SSL证书链是什么&#xff1f;SSL证书链如何工…

使用Python打造一个爱奇艺热播好剧提前搜系统

目录 一、系统功能设计 二、数据获取与处理 三、搜索功能实现 四、用户界面设计 五、系统部署与维护 六、总结 随着互联网的普及和人们对于娱乐需求的增加&#xff0c;视频网站成为了人们观看电视剧、电影等视频内容的主要渠道。爱奇艺作为国内知名的视频网站之一&#x…

自动化控制面板-1Panel

一、1Panel自动化控制面板 官网地址 1Panel 可以实现&#xff1a; 快速建站、高效管理、安全可靠、一键备份、应用商店 快速建站&#xff1a;深度集成 Wordpress 和 Halo&#xff0c;域名绑定、SSL 证书配置等一键搞定&#xff1b;高效管理&#xff1a;通过 Web 端轻松管理 …

Linux习题7

解析&#xff1a;du命令用于显示目录或文件的大小&#xff0c;du会显示指定的目录或文件所占用的磁盘空间。df命令用于显示目前在Linux系统上的文件系统磁盘使用情况统计。 解析&#xff1a;www是80&#xff0c;ftp是20,21 解析&#xff1a;光盘安装 (常规情况) 硬盘安装 (无光…

面试算法111:计算除法

题目 输入两个数组equations和values&#xff0c;其中&#xff0c;数组equations的每个元素包含两个表示变量名的字符串&#xff0c;数组values的每个元素是一个浮点数值。如果equations[i]的两个变量名分别是Ai和Bi&#xff0c;那么Ai/Bivalues[i]。再给定一个数组queries&am…

哪种小型洗衣机好用?高性价比的小型洗衣机推荐

大型洗衣机作为家居必备小家电&#xff0c;对生活品质的提升十分显著&#xff0c;在很多人的认知中&#xff0c;这种大型洗衣机主要是用来清洁大件的衣服和外套的&#xff0c;不方便将内衣裤都放入到里面&#xff0c;内衣裤的材质和尺寸都是比较特殊&#xff0c;若是直接将其放…

轻量化神奇!看3D模型格式转换工具HOOPS Exchange如何轻松实现减面操作?

现在很多CAD模型都比较复杂&#xff0c;有时候为了一些特殊用途&#xff08;轻量化显示、布尔运算、CAE网格剖分等&#xff09;&#xff0c;需要到对原始模型进行减面操作。在HOOPS Exchange中&#xff0c;就提供了对模型进行减面操作支持&#xff0c;以下内容就是HOOPS Exchan…

用TF-IDF处理文本数据

计算机擅长处理数字&#xff0c;但不擅长处理文本数据&#xff0c;TF-IDF是处理文本数据最广泛使用的技术之一&#xff0c;本文对它的工作原理以及它的特性进行介绍。 根据直觉&#xff0c;我们认为在文本数据分析中出现频率更高的单词应该具有更大的权重&#xff0c;但事实并…

python使用广度优先搜索算法解决二叉树最大、最小深度

对于广度优先搜索算法的一个经典应用问题&#xff0c;也就是对二叉树求其最大深度、最小深度问题。对于给定的二叉树的最大深度即为二叉树的根节点到最远的叶子结点之间的高度&#xff0c;而相应的最小深度就是根节点与离根节点最近的叶子节点之间的高度。 添加图片注释&#x…

MyBatisPlus学习笔记一

1、简介 MyBatisPlus&#xff08;简称MP&#xff09;是一个MyBatis的增强工具&#xff0c;在MyBatisMyBatisMyBatis的的基础上只做增强不做改变&#xff0c;为简化开发&#xff0c;提高效率而生。 官网&#xff1a;MyBatis-Plus mybatisplus通过扫描实体类&#xff0c;并基于…

贪心算法(思路)

最近在cf上做了很多贪心的题&#xff0c;写篇博客来总结一下 Problem - C - Codeforces 看第一道题 不难看出&#xff0c;我们需要在数组中找到一段奇偶相间的序列&#xff0c;要使他们的和最大&#xff0c; 在图中我们假设[1,2]和[3,4]是奇偶相间的序列&#xff0c;我们在在…

如何在 Microsoft Edge 浏览器中启用自动刷新

你是否经常发现自己在使用 Microsoft Edge 时点击刷新按钮&#xff1f;如果您需要一个网页以设定的时间间隔自动更新&#xff0c;那么请接着往下看。 在这篇博文中&#xff0c;我们探讨如何在 Microsoft Edge 浏览器中启用和管理自动刷新功能。 为什么选择自动刷新&#xff1…

【分布式】分布式链路跟踪技术

为什么需要分布式链路追踪 提到分布式链路追踪&#xff0c;我们要先提到微服务。相信很多人都接触过微服务。微服务是一种开发软件的架构和组织方法&#xff0c;它侧重将服务解耦&#xff0c;服务之间通过API通信。使应用程序更易于扩展和更快地开发&#xff0c;从而加速新功能…

使用requests库测试post请求 操作流程

第一步 谷歌f12或其他抓包工具抓包&#xff0c;这里随机抓一个post请求 url&#xff1a;https://eva2.csdn.net/v3/06981375190026432f77c01bfca33e32/lts/groups/dadde766-b087-42da-8e67-d2499a520ee7/streams/a0119567-bf91-4314-ab75-f683ba6c0c0a/logs 第二步 导包 impo…

国科大计算机体系结构期末考试——停更,手写更快

题型一、第二章的画图 给一个逻辑表达式&#xff0c;画出晶体管级别的电路图 cmos电路的基本电路&#xff1a; 与非门的功能是对多个输入信号进行逻辑与操作&#xff0c;然后对结果进行取反。 或非门的功能是对多个输入信号进行逻辑或操作&#xff0c;然后对结果进行取反。 …

适用于安防 音响 车载等产品中中的音频接口选型分析

在人工智能兴起之后&#xff0c;安防市场就成为了其全球最大的市场&#xff0c;也是成功落地的最主要场景之一。对于安防应用而言&#xff0c;智慧摄像头、智慧交通、智慧城市等概念的不断涌现&#xff0c;对于芯片产业催生出海量需求。今天&#xff0c;我将为大家梳理GLOBALCH…

怎么使用EIDE进行调试STM32单片机?

cortex-debug 用法 - Blog - Embedded IDE Forum (em-ide.com) 【VScode Embedded IDE】Keil工程导入VScode&#xff0c;与Keil协同开发MCU_vscode编辑keil工程-CSDN博客 Vscode EIDECortex Debug搭建STM32开发仿真环境_vscode cortex-debug-CSDN博客 可以结合一下上述三位大…

帆软report 设置条件属性,值为负数标为红色功能时,不生效

详细情况&#xff1a; 在设置负数为红色功能前&#xff0c;已经有一个条件属性&#xff0c;数据集获取的值为空或者为0时&#xff0c;转换成 - 符号。如下图&#xff1a; 具体表单显示效果如下&#xff1a; 条件属性2设置 原因 因为条件属性1设置的 - 符号没有设置颜色&#xf…

怎么做拼团链接_生鲜果蔬商家都在用的小程序拼团系统

拼团链接&#xff1a;重塑营销新格局 在当今这个信息爆炸的时代&#xff0c;消费者面对海量信息&#xff0c;选择变得尤为重要。如何在众多品牌中脱颖而出&#xff0c;让消费者愿意主动为你驻足&#xff1f;答案就是——拼团链接。 拼团&#xff0c;是一种社交电商的创新形式。…