在不调用`clear all`的情况下破坏Matlab Singleton class实例
Destructing Matlab Singleton class instance without calling `clear all`
根据 Matlab documentation,为了创建单例设计模式,您需要在静态函数中为单例对象实例设置一个 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
几乎不可能 'destruct' 单例实例。我试过 clear SingleInstance
、clear getInstance()
、clear SingleInstance.getInstance()
、clear functions
、clear variables
和其他组合。在 SingleInstance
class 的 getInstance()
静态方法中 localObj
持久变量的唯一方法是调用 clear all
.
我可以在调用我的 Matlab OO 应用程序之前调用 clear all
。但是,我正在使用 Matlab 单元测试基础结构,并且有一些单元测试,我想在其中测试实例化单例 classes 的不同方法。但是,为此我需要调用 clear all
,这会使 Matlab 单元测试基础结构停止工作。
有谁知道一种无需调用 clear all
即可清除 Matlab classes 静态方法内部持久变量的方法吗?或者,换句话说,有人知道如何在不使用 persitent
变量的情况下实现单例设计模式吗?或者,至少,如何在不破坏单元测试基础结构的情况下在单元测试中调用 clear all
?
你必须使用delete
or look at this doc
在 clear
系列中,您还可以查看 clear classes
,但这不符合您的需要,因为它的功能与 clear all
相同,而且它删除了 classes定义。
您无需更改单例类型的设计 class,要销毁实例化的 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"
我在执行第三行的过程中在调试器中停止了,我得到:
当我调用 clear 时,我的变量 sobj
从工作区中消失了,但是对象仍然存在于内存中(并且句柄仍然由 localObj
变量保留)。
如果我现在将第二行替换为
delete(sobj)
在您的工作区中,您将获得:
>> sobj
sobj =
handle to deleted SingleInstance
在调试器中对 getInstance
的下一次调用时,我得到:
出现在工作区中的 localObj
仍然显示为 SingleInstance
的句柄,但它知道该对象已被删除。
所以在您的 class 设计中,您可以在继续其他操作之前检查 localObj
的状态。
函数 isvalid
可用于了解句柄是否指向真实对象。
我的第一个想法是,只要有可能,您就应该避免单例和其他形式的全局状态,这不仅是为了可测试性,也是为了代码的整洁和接口的完整性。更多信息 here and here.
另一种想法是您可以发出以下调用:
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
)。如果它在它自己的函数中,则不需要该范围内的任何其他变量,因此您可以有效地清除 类。
然而,请注意,以这种方式使用 clear 类 确实是一种试图告诉你一些事情的气味(主要是为了避免全局状态),你应该期望 运行 进入特质。例如,我相信调用 clear 类 也会清除探查器数据,因此您将无法使用 CodeCoveragePlugin.
有效地测量代码覆盖率
Hoki 的回答很好,只要您同意用户清除唯一实例的能力,这也可以清除您的应用程序所依赖的全局状态,并且有可能在未来导致错误,如果您不小心
希望对您有所帮助!
根据 Matlab documentation,为了创建单例设计模式,您需要在静态函数中为单例对象实例设置一个 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
几乎不可能 'destruct' 单例实例。我试过 clear SingleInstance
、clear getInstance()
、clear SingleInstance.getInstance()
、clear functions
、clear variables
和其他组合。在 SingleInstance
class 的 getInstance()
静态方法中 localObj
持久变量的唯一方法是调用 clear all
.
我可以在调用我的 Matlab OO 应用程序之前调用 clear all
。但是,我正在使用 Matlab 单元测试基础结构,并且有一些单元测试,我想在其中测试实例化单例 classes 的不同方法。但是,为此我需要调用 clear all
,这会使 Matlab 单元测试基础结构停止工作。
有谁知道一种无需调用 clear all
即可清除 Matlab classes 静态方法内部持久变量的方法吗?或者,换句话说,有人知道如何在不使用 persitent
变量的情况下实现单例设计模式吗?或者,至少,如何在不破坏单元测试基础结构的情况下在单元测试中调用 clear all
?
你必须使用delete
or look at this doc
在 clear
系列中,您还可以查看 clear classes
,但这不符合您的需要,因为它的功能与 clear all
相同,而且它删除了 classes定义。
您无需更改单例类型的设计 class,要销毁实例化的 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"
我在执行第三行的过程中在调试器中停止了,我得到:
当我调用 clear 时,我的变量 sobj
从工作区中消失了,但是对象仍然存在于内存中(并且句柄仍然由 localObj
变量保留)。
如果我现在将第二行替换为
delete(sobj)
在您的工作区中,您将获得:
>> sobj
sobj =
handle to deleted SingleInstance
在调试器中对 getInstance
的下一次调用时,我得到:
出现在工作区中的 localObj
仍然显示为 SingleInstance
的句柄,但它知道该对象已被删除。
所以在您的 class 设计中,您可以在继续其他操作之前检查 localObj
的状态。
函数 isvalid
可用于了解句柄是否指向真实对象。
我的第一个想法是,只要有可能,您就应该避免单例和其他形式的全局状态,这不仅是为了可测试性,也是为了代码的整洁和接口的完整性。更多信息 here and here.
另一种想法是您可以发出以下调用:
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
)。如果它在它自己的函数中,则不需要该范围内的任何其他变量,因此您可以有效地清除 类。
然而,请注意,以这种方式使用 clear 类 确实是一种试图告诉你一些事情的气味(主要是为了避免全局状态),你应该期望 运行 进入特质。例如,我相信调用 clear 类 也会清除探查器数据,因此您将无法使用 CodeCoveragePlugin.
有效地测量代码覆盖率Hoki 的回答很好,只要您同意用户清除唯一实例的能力,这也可以清除您的应用程序所依赖的全局状态,并且有可能在未来导致错误,如果您不小心
希望对您有所帮助!