在不调用`clear all`的情况下破坏Matlab Singleton类实例

时间:2015-07-18 13:03:31

标签: matlab unit-testing oop singleton persistent

根据Matlab documentation,要创建Singleton设计模式,您需要在单个对象实例的静态函数内设置persistent变量,即:

classdef (Sealed) SingleInstance < handle
  methods (Access = private)
    function obj = SingleInstance
    end
  end
  methods (Static)
    function singleObj = getInstance
      persistent localObj
      if isempty(localObj) || ~isvalid(localObj)
        localObj = SingleInstance;
      end
      singleObj = localObj;
    end
  end
end

几乎不可能“破坏”单例实例。我尝试过clear SingleInstanceclear getInstance()clear SingleInstance.getInstance()clear functionsclear variables和其他组合。 localObj类的getInstance()静态方法中SingleInstance持久变量的唯一方法是调用clear all

我可以在调用我的Matlab OO应用程序之前调用clear all。但是,我正在使用Matlab单元测试基础设施,并且有单元测试,我想测试实例化单例类的不同方法。但是,为此,我需要调用clear all,这将使Matlab单元测试基础设施停止工作。

有没有人知道如何在不调用clear all的情况下清除Matlab类静态方法中的持久变量?或者,换句话说,是否有人知道如何在不使用persitent变量的情况下实现Singleton设计模式?或者,至少,如何在不破坏单元测试基础设施的情况下在单元测试中调用clear all

2 个答案:

答案 0 :(得分:2)

您必须使用delete或查看此doc

clear系列中,您还可以查看clear classes,但这不适合您需要,因为它与clear all完全相同,而且删除了类定义。

您无需更改单件类型类的设计,以销毁必须使用handle的实例化delete object2dispose对象。使用clear object2dispose时,只清除工作空间中保存对象句柄的变量,但不要销毁对象本身。这就是为什么当你调用getInstance方法时,你仍然会看到句柄保存在localObj持久变量中(这是其目的之一,以保存你可能丢失的句柄)。

所以,如果我使用

sobj = SingleInstance.getInstance %// instantiate object
clear sobj                          %// clear it ? (... not really)

sobj = SingleInstance.getInstance %// To see the state of "localObj"

我在执行第三行期间停在调试器中,得到: instantiated

当我调用clear时,我的变量sobj从工作区中消失了,但是对象仍然存在于内存中(并且句柄仍由localObj变量保存)。

如果我现在用

替换第二行
delete(sobj)

在您的工作区中,您将获得:

>> sobj
sobj = 
  handle to deleted SingleInstance

在下次调用调试器中的getInstance时,我得到: deleted

工作区中显示的localObj仍显示为SingleInstance的句柄,但它知道该对象已被删除。

因此,在您的课堂设计中,您可以先检查localObj的状态,然后再继续。

函数isvalid对于了解句柄是否指向真实对象非常有用。

答案 1 :(得分:0)

我的第一个想法是,只要有可能,你应该避免单例和其他形式的全局状态,不仅是为了可测试性,还为了代码清洁度和接口完整性。更多信息herehere

另一个想法是你可以发出以下电话:

classdef FuadTest < matlab.unittest.TestCase

    methods(Test)
        function testSomething(testCase)
             clearClasses;
             % Do other stuff
        end
    end
end

function clearClasses
clear classes;
end

这里的要点是将clear类调用放入它自己的本地函数(或私有方法,静态方法,无论如何),这样你就可以在自己的范围内调用clear而不清除所有其他变量在您的测试方法中(例如,testCase)。如果它在它自己的功能中你不需要该范围内的任何其他变量,那么你可以有效地清除类。

然而,一句警告,用这种方式使用明确的类确实是一种试图告诉你某事的气味(主要是为了避免全局状态),你应该期待遇到特质。例如,我认为调用明确的类也会清除分析器数据,因此您无法使用CodeCoveragePlugin来有效地测量代码覆盖率。

只要您能够清除唯一的实例,Hoki的答案就可以了,这也可以清除您的应用所依赖的全局状态,并有可能导致如果你不小心的话就会出问题。

希望有所帮助!