如何在 MATLAB 中正确实现工厂模式?

Dan*_*hoa 3 oop matlab factory

我正在编写一个程序,可以在其中从可用对象列表中进行选择Sensor;在选择和用户验证后,程序应实例化该Sensor.

下面的代码片段是我可能会天真地做的事情:

switch userInput
    case 'Sensor A' 
        s = SensorA; % subclass of Sensor

    case 'Sensor B'
        s = SensorB; % subclass of Sensor

    %...
end
Run Code Online (Sandbox Code Playgroud)

这里有一些明显的问题,但我遇到的最大问题是使其可扩展。我希望能够创建许多不同的Sensor子类(或让其他开发人员生成Sensor子类),而不必不断添加到此switch语句中。更一般地说,我想坚持开放/封闭原则。我应该能够有很多不同的Sensor子类。(我也想用uicontrol可用的内容填充弹出菜单Sensors,但是如果这个问题得到普遍解决,这可能会得到解决。)其他简单的解决方案,例如查看充满Sensor子类的文件夹也不能很好地工作,因为对象构造可能是每个子类都不同。

我相信我正在寻找使用工厂方法模式,但我不完全确定如何实现它。我可以将上面的代码片段放入一个单独的 中SensorFactory,但这只是移动了switch语句,这意味着扩展它需要修改它。

如何正确实现工厂方法模式,以便每次添加新子类时不需要修改工厂对象Sensor

Cit*_*ane 6

关于可扩展性,您可以使用containers.Map对象作为工厂中的哈希表。这是一些简单的例子:

classdef SensorFactory < handle

    % Lifetime
    methods
        function [factory] = SensorFactory()
        % Creates the factory

            % Call super class
            factory = factory@handle();

            % Pre-register some well-known sensors if you want
            factory.RegisterSensor('Sensor A', @() error('TODO: Here of course use appropriate method to create sensor A'));
            factory.RegisterSensor('Sensor B', @() error('TODO: Here of course use appropriate method to create sensor B'));
            factory.RegisterSensor('Sensor C', @() error('TODO: Here of course use appropriate method to create sensor C'));

        end
    end

    methods

        function [] = RegisterSensor(factory, sensorName, createSensorCallback)
        % Adds new sensor to the factory    
            factory.dictionnary(sensorName) = createSensorCallback;
        end
        function [sensorList] = GetListOfSensors(factory)
        % Obtains the list of available sensors    
            sensorList = factory.dictionnary.keys;
        end
        function [sensor] = CreateSensor(factory, sensorName)  
        % Creates sensor instance
            createCallback = factory.dictionnary(sensorName);
            sensor = createCallback();            
        end

   end

    properties(GetAccess  = private)
        dictionnary = containers.Map(); % Hash table
    end   

end
Run Code Online (Sandbox Code Playgroud)

这个类可以这样使用:

在代码的开头创建工厂:

factory = SensorFactory();
Run Code Online (Sandbox Code Playgroud)

在某些初始化部分中动态添加新传感器:

factory.RegisterSensor('Custom Sensor', @() createCustomSensor());
factory.RegisterSensor('Specific Sensor aperture=42', @() createSpeficSensor(42));
factory.RegisterSensor('Specific Sensor aperture=666', @() createSpecificSensor(666));
Run Code Online (Sandbox Code Playgroud)

注意:出于自动化目的,这也可以在解析某些文件夹中的类文件时完成。每个类都有一个静态方法来获取传感器的用户名。这里只是一些想法和伪代码:

classdef MySuperSensor
  methods(Static)
      funcion [name] = GetUserName()
         name = 'My super sensor';
      end
  end
end

---
l = dir('.\sensors');
foreach file in l
  try
     meta = eval(sprintf('?%s', l.name)); 
     factory.Register(...GetUserName()..., ...CreateCallback...)
  catch
  end
end  
Run Code Online (Sandbox Code Playgroud)

然后,在某些 GUI 部分中,添加一个组合,列出迄今为止所有可用的传感器:

set(myCombo, 'String', factory.GetListOfSensors());
Run Code Online (Sandbox Code Playgroud)

最后,在运行部分,实例化适当的传感器:

index = get(myCombo, 'Value');

name = factory.GetListOfSensors();
name = name{index};

sensor = factory.CreateSensor(name);
Run Code Online (Sandbox Code Playgroud)