I would like to create a singleton MATLAB class acting as a global registry. The registry should store objects (of a certain class derived from handle
) addressed with unique names. I would like to access the properties of the stored classes conveniently without temporary variables, for example:
Registry.instance().addElement('name1', NewObject(...));
Registry.instance().get('name1').Value
Registry.instance().get('name2').Value = 1;
Reading out properties of the returned class can be circumvented by removing the ()
from instance
:
>> Equipment.instance.get('name1').Value
However, it does not seem easy to use assignments because as noted in the comments, dot-indexing can't be used directly on the output of a function without assigning to an intermediate variable.
What is the proper way to implement and use such a "singleton registry" in MATLAB?
It should be noted that the singleton class contains some logic which is called when adding elements to the list, logic to properly destroy the objects in the right order and other methods which iterate through the object list. For that reason, a "normal" containers.Map
cannot be used.
This might be what you're looking for:
classdef (Abstract) Registry % < handle <-- optional
methods (Access = public, Static = true)
function addElement(elementName, element)
Registry.accessRegistry('set', elementName, element );
end
function element = get(elementName)
element = Registry.accessRegistry('get', elementName);
end
function reset()
Registry.accessRegistry('reset');
end
end
methods (Access = private, Static = true)
function varargout = accessRegistry(action, fieldName, fieldValue)
% throws MATLAB:Containers:Map:NoKey
persistent elem;
%% Initialize registry:
if ~isa(elem, 'containers.Map') % meaning elem == []
elem = containers.Map;
end
%% Process action:
switch action
case 'set'
elem(fieldName) = fieldValue;
case 'get'
varargout{1} = elem(fieldName);
case 'reset'
elem = containers.Map;
end
end
end
end
Since MATLAB doesn't support static
properties, one must resort to various workarounds, possibly involving methods
with persistent
variables, as is the case in my answer.
Here's a usage example of the above:
Registry.addElement('name1', gobjects(1));
Registry.addElement('name2', cell(1) ); % assign heterogeneous types
Registry.get('name1')
ans =
GraphicsPlaceholder with no properties.
Registry.get('name1').get % dot-access the output w/o intermediate assignment
struct with no fields.
Registry.get('name2'){1} % {}-access the output w/o intermediate assignment
ans =
[]
Registry.get('name3') % request an invalid value
Error using containers.Map/subsref
The specified key is not present in this container.
Error in Registry/accessRegistry (line 31)
varargout{1} = elem(fieldName);
Error in Registry.get (line 10)
element = Registry.accessRegistry('get', elementName);