设计模式之空对象模式

目录

1.简介

2.结构图

3.实例

4.优缺点


1.简介

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

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

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

cpp 复制代码
    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.实例

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

cpp 复制代码
#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;
};

测试例程如下:

cpp 复制代码
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.违反开放封闭原则:开放封闭原则鼓励的是添加新的行为,而不是新的具体类。而空对象模式需要为每个类添加新的空实现类,这似乎与开放封闭原则相违背。

相关推荐
AI玫瑰助手1 分钟前
Python模块:from...import...导入指定内容
开发语言·python·信息可视化
石山代码2 分钟前
JavaScript 进阶核心知识点
开发语言·javascript·ecmascript
FL162386312913 分钟前
[cmake]基于C++使用纯opencv部署ppocrv5v6的onnx模型
开发语言·c++·opencv
玖玥拾17 分钟前
C/C++ 数据结构(六)链表迭代器与底层
c语言·数据结构·c++·链表·stl库
牛油果子哥q28 分钟前
AVL平衡树与红黑树深度精讲对比,平衡因子、四大旋转原理、着色规则、平衡策略、性能差异与面试手撕全解
数据结构·c++·面试
汉克老师1 小时前
GESP7级C++考试语法知识(二、指数函数(3、综合练习)
c++·算法·数学建模·指数函数·gesp7级·复利
C++ 老炮儿的技术栈1 小时前
Ubuntu root账号自动登陆
linux·运维·服务器·c语言·c++·ubuntu·visual studio
Irissgwe1 小时前
map/set/multimap/multiset 的底层逻辑与实现
数据结构·c++·算法·二叉树·stl·c·红黑树
(Charon)2 小时前
【C++ 面试高频:内存管理、RAII 和智能指针详解】
java·开发语言·word