简体   繁体   中英

How do I correctly implement the Factory Pattern in MATLAB?

I am writing a program in which I can select from a list of available Sensor objects; upon selection and user validation, the program should instantiate that Sensor .

The following code snippet is what I might naively do:

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

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

    %...
end

There are some obvious problems here, but the biggest problem I have is making this extensible. I want to be able to create lots of various Sensor subclasses (or have other developers generate Sensor subclasses) without having to continuously add to this switch statement. More generally, I want to adhere to the open/closed principle . I ought to be able to have lots of different Sensor subclasses. (I also want to populate a popupmenu uicontrol with the available Sensors , but that probably gets solved if this problem gets solved generally.) Other naive solutions such as peeking into a folder full of Sensor subclasses doesn't work very well either, since object construction may be different for each subclass.

I believe I'm looking to use the factory method pattern , but I'm not entirely sure how to implement it. I could put the above code snippet into a separate SensorFactory , but this just moves the switch statement around, meaning extending it requires modifying it.

How do I implement the factory method pattern correctly such that the factory object doesn't require modification every time I add a new Sensor subclass?

Regarding extensibility you can use a containers.Map object as a hash table in your factory. Here is some simple example:

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

This class can be used like this:

At the beginning of the code create the factory:

factory = SensorFactory();

In some initialization part add new sensors on the fly:

factory.RegisterSensor('Custom Sensor', @() createCustomSensor());
factory.RegisterSensor('Specific Sensor aperture=42', @() createSpeficSensor(42));
factory.RegisterSensor('Specific Sensor aperture=666', @() createSpecificSensor(666));

NB: For automation purpose, this may be done also parsing class files in some folder. Each class having a static method to get the user name of the sensor. Just some thoughts and pseudo code here:

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  

Then, in some GUI part, add a combo listing all available sensors to date:

set(myCombo, 'String', factory.GetListOfSensors());

Finally, in the run part, instantiate appropriate sensor:

index = get(myCombo, 'Value');

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

sensor = factory.CreateSensor(name);

I don't really see a reason to use the factory pattern here. A typical piece of code for matlab is:

if ischar(fun)
  if exist(fun,'function')
    fun=str2func(fun)
  else
    error('invalid input') 
  end
end
if ~isa(fun, 'function_handle')
  error('invalid input') 
end
sensor=fun()

Using this, fun can be name or function handle to a function or constructor which returns your sensor object.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM