首页 > 解决方案 > 单例注册表类

问题描述

我想创建一个作为全局注册表的单例 MATLAB 类。handle注册表应该存储使用唯一名称寻址的对象(从 派生的某个类)。我想在没有临时变量的情况下方便地访问存储类的属性,例如:

Registry.instance().addElement('name1', NewObject(...));
Registry.instance().get('name1').Value
Registry.instance().get('name2').Value = 1;

()可以通过删除from来规避读取返回类的属性instance

 >> Equipment.instance.get('name1').Value

但是,使用赋值似乎并不容易,因为如注释中所述,如果不分配给中间变量,就不能直接在函数的输出上使用点索引。

在 MATLAB 中实现和使用这种“单例注册表”的正确方法是什么?

应该注意的是,单例类包含一些在向列表中添加元素时调用的逻辑、以正确顺序正确销毁对象的逻辑以及遍历对象列表的其他方法。因此,containers.Map不能使用“正常”。

标签: matlaboopdictionarysingletonhandle

解决方案


这可能是您正在寻找的:

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

由于 MATLAB不支持staticproperties,因此必须求助于各种解决方法,可能涉及methods变量persistent,就像我的回答中的情况一样。

这是上面的一个使用示例:

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); 

推荐阅读