设计模式——空对象模式

news/2024/11/28 17:41:02/

定义

空对象模式(Null Object Pattern)是一种软件设计模式。在 C++ 中,它主要用于用一个空对象来代替 NULL 引用的检查。这个空对象可以提供默认的行为,从而避免了在代码中频繁地进行空指针(NULL)检查。
例如,在一个图形绘制系统中,如果没有指定图形的颜色,不是返回一个空指针(这会导致很多地方需要检查是否为空),而是返回一个表示 “无色” 的空对象,这个空对象有自己的默认行为,比如在绘制图形时不进行任何颜色相关的操作。

结构组成

  • 抽象基类(Abstract Class):
    定义了接口,这个接口包含了真实对象和空对象都需要实现的方法。例如,在一个文件读取系统中,抽象基类可能定义了read()和close()等方法,这些方法无论是对于真正的文件对象还是空文件对象都有意义。
  • 真实对象类(Concrete Class):
    实现了抽象基类中定义的接口,提供了真实的功能。继续以文件读取系统为例,真实对象类会实现read()方法来从文件中读取内容,close()方法来关闭文件。
  • 空对象类(Null Class):
    同样实现抽象基类的接口,但是它的方法实现通常是提供默认行为或者不执行任何操作。在文件读取系统中,空对象类的read()方法可能返回一个空字符串或者特定的错误码,表示没有读取到任何内容,close()方法可能什么都不做。

工作原理

当客户端代码请求一个对象的服务时,它不需要知道这个对象是真实对象还是空对象。空对象会按照其预定义的默认行为来响应请求,而真实对象则会执行实际的功能。
比如,在一个游戏角色系统中,角色有一个武器装备接口。如果角色没有装备武器,不是返回一个空指针,而是返回一个空武器对象。当游戏逻辑调用武器的 “攻击” 方法时,真实武器对象会执行攻击计算等操作,而空武器对象的 “攻击” 方法可能只是返回一个表示 “没有造成伤害” 的值或者打印一条 “没有武器,无法攻击” 的消息。
代码示例
首先是抽象基类,以汽车驾驶接口为例:

class CarDriveInterface {
public:virtual void drive() = 0;virtual void stop() = 0;
};

真实对象类,比如普通汽车类:

class NormalCar : public CarDriveInterface {
public:void drive() override {std::cout << "正常驾驶汽车。" << std::endl;}void stop() override {std::cout << "汽车停止。" << std::endl;}
};

空对象类:

class NullCar : public CarDriveInterface {
public:void drive() override {std::cout << "没有汽车,无法驾驶。" << std::endl;}void stop() override {std::cout << "没有汽车,无需停止。" << std::endl;}
};

客户端代码使用示例:

class CarOwner {
private:CarDriveInterface* car;
public:CarOwner(CarDriveInterface* c) : car(c) {}void driveCar() {car->drive();}void stopCar() {car->stop();}
};

在main函数中使用:

int main() {CarDriveInterface* normalCar = new NormalCar();CarOwner owner1(normalCar);owner1.driveCar();owner1.stopCar();CarDriveInterface* nullCar = new NullCar();CarOwner owner2(nullCar);owner2.driveCar();owner2.stopCar();return 0;
}

在这个例子中,CarOwner类不需要判断它持有的car对象是真实汽车还是空汽车,因为空汽车对象已经有了自己的默认行为。

优点

  • 减少空指针检查:
    可以使代码更加简洁,减少了大量的空指针检查逻辑。在复杂的系统中,如果到处都需要检查对象是否为 NULL,代码会变得很杂乱,使用空对象模式可以避免这种情况。
  • 提高代码可读性和可维护性:
    代码的逻辑更加清晰,因为不需要频繁地处理特殊的空情况。例如,在一个员工管理系统中,如果没有员工对象就返回一个空对象,而不是 NULL,其他模块在调用员工相关的方法(如 “工作”“休息” 等)时,不需要复杂的空指针检查,直接调用方法即可,代码的可读性得到了提高。
  • 增强代码的健壮性:
    降低了因为空指针引用而导致程序崩溃的风险。即使在某些情况下对象不存在或者没有初始化,空对象的默认行为也可以让程序继续稳定地运行,而不是因为空指针异常而终止。

缺点

  • 增加类的数量:
    需要创建一个额外的空对象类,对于简单的系统来说,这可能会使代码看起来有些臃肿。如果有很多不同类型的对象都需要空对象模式,会导致类的数量显著增加。
  • 可能隐藏错误:
    如果空对象的默认行为没有设计好,可能会掩盖一些本应该被发现的错误。例如,在一个计算系统中,如果空对象的计算方法总是返回 0,可能会导致用户误以为计算是正确的,而实际上是因为使用了空对象而没有进行真正的计算。

http://www.ppmy.cn/news/1550682.html

相关文章

Linux的前台进程和后台进程

概念定义 前台进程&#xff1a; 前台进程是和用户直接交互的进程&#xff0c;它会占用终端的输入/输出&#xff08;I/O&#xff09;设备。当一个进程在前台运行时&#xff0c;它会从终端读取用户输入的命令&#xff0c;并且将输出结果显示在终端上。例如&#xff0c;当你在终端…

git使用文档手册

创建一个本地代码工作空间&#xff0c;比如这里使用test目录作为工作目录 针对仓库地址 http://192.168.31.125:9557/poxiaoai-crm/project-crm.git。 1. 安装 Git 确保您的系统已经安装了 Git。如果未安装&#xff0c;请根据操作系统访问 Git 官网 下载并安装。 验证安装 …

daos源码编译

1. 前言 本文详细介绍如何在almalinux8.9上编译daos.2.0.0源码。系统环境如下&#xff1a; daos: 2.0.0 linux os: almalinux 8.9 linux kernel: 4.18.0-513.5.1.el8_9.x86_64之所以选择2.0.0版本&#xff0c;是因为daos从2.0.0开始是一个全新的架构设计&a…

ASUS/华硕灵耀14 UX3402ZA 原厂win11系统 工厂文件 带ASUS Recovery恢复

华硕工厂文件恢复系统 &#xff0c;安装结束后带隐藏分区&#xff0c;一键恢复&#xff0c;以及机器所有驱动软件。 系统版本&#xff1a;windows11 原厂系统下载网址&#xff1a;http://www.bioxt.cn 需准备一个20G以上u盘进行恢复 请注意&#xff1a;仅支持以上型号专用…

(四)3D视觉机器人的手眼标定(眼在手外)

内容 1.背景介绍1.1 思路T_target_to_cam求解公式求解 2.操作流程 1.背景介绍 3D视觉机器人指的是机器人通过3D相机提供的3D点云视觉信息&#xff0c;完成某些实际的功能。   目标是将场景信息从相机坐标系变换至机械臂坐标系中&#xff0c;最终是获得相机到机械臂基座的空间…

CTF之密码学(RSA加密)

RSA加密算法是一种公钥加密算法&#xff0c;以下是对其的详细解析&#xff1a; 一、RSA加密算法概述 RSA加密算法由Ron Rivest、Adi Shamir和Leonard Adleman在1977年共同发明&#xff0c;并因此得名。它是第一个既能用于数据加密也能用于数字签名的算法。RSA的安全性基于数论…

android12锁屏界面pin码或者图案解锁居中显示

设置pin码或者图案锁屏后&#xff0c;在锁屏界面向上划左边&#xff0c;图案解锁就在左边&#xff0c; 向上划右边图案就在右边&#xff0c;如何设置一直居中显示呢&#xff1f; diff --git a/packages/SystemUI/res/layout/super_notification_shade.xml b/packages/SystemUI…

go-学习

文章目录 简介标识符字符串的拼接&#xff0c;关键字数据类型声明变量常量算术运算符关系运算符逻辑运算符位运算赋值运算符其他运算符 简介 Go 语言的基础组成有以下几个部分&#xff1a; 1.包声明 2.引入包 3.函数 4.变量 5.语句 & 表达式 6.注释 package main import &q…