我正在编写一个程序,我可以从可用的Sensor
对象列表中进行选择;在选择和用户验证时,程序应该实例化Sensor
。
以下代码片段是我可能天真地做的事情:
switch userInput
case 'Sensor A'
s = SensorA; % subclass of Sensor
case 'Sensor B'
s = SensorB; % subclass of Sensor
%...
end
这里有一些明显的问题,但我遇到的最大问题是使其具有可扩展性。我希望能够创建许多不同的Sensor
子类(或让其他开发人员生成Sensor
子类),而无需不断添加到此switch
语句。更一般地说,我想坚持open/closed principle。我应该能够拥有许多不同的Sensor
子类。 (我还希望使用可用的uicontrol
填充弹出菜单Sensors
,但如果这个问题得到解决,这可能会得到解决。)其他天真的解决方案,例如偷看到{{1}的文件夹由于每个子类的对象构造可能不同,因此子类也不能很好地工作。
我相信我希望使用factory method pattern,但我并不完全确定如何实施它。我可以将上面的代码段放到单独的Sensor
中,但这只会移动SensorFactory
语句,这意味着扩展它需要修改它。
如何正确实现工厂方法模式,以便每次添加新的switch
子类时工厂对象都不需要修改?
答案 0 :(得分:4)
关于可扩展性,您可以使用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
这个类可以像这样使用:
在代码的开头创建工厂:
factory = SensorFactory();
在某些初始化部分中,动态添加新传感器:
factory.RegisterSensor('Custom Sensor', @() createCustomSensor());
factory.RegisterSensor('Specific Sensor aperture=42', @() createSpeficSensor(42));
factory.RegisterSensor('Specific Sensor aperture=666', @() createSpecificSensor(666));
注意:出于自动化目的,这也可以解析某些文件夹中的类文件。每个类都有一个静态方法来获取传感器的用户名。这里只是一些想法和伪代码:
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
然后,在某些GUI部分中,添加一个列出所有可用传感器的组合:
set(myCombo, 'String', factory.GetListOfSensors());
最后,在运行部分中,实例化适当的传感器:
index = get(myCombo, 'Value');
name = factory.GetListOfSensors();
name = name{index};
sensor = factory.CreateSensor(name);
答案 1 :(得分:0)
我真的没有理由在这里使用工厂模式。 matlab的典型代码是:
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()
使用它,fun可以是返回传感器对象的函数或构造函数的名称或函数句柄。