Я знаю, что это много, но, пожалуйста, потерпите меня, я не знаю, как еще всесторонне описать проблему. Представьте, что есть машина с двумя устройствами A
и B
. Каждое из устройств имеет 2 оси, которые можно включать и выключать. (У осей на самом деле больше свойств для установки, но для простоты давайте сосредоточимся только на 1):
mashine
|
------------
| |
A B
------ ------
| | | |
X Y X Y
--- --- --- ---
||| ||| ||| |||
ESP ESP ESP ESP
E: Enable(bool) | S: Start(bool) | P: Position(double)
Машина представлена следующим классом (который я не могу изменить!):
// МАШИНА
public static class Mashine
{
public static bool Enable_B_X { get; set; }
public static bool Enable_B_Y { get; set; }
public static bool Enable_A_X { get; set; }
public static bool Enable_A_Y { get; set; }
// actually much more properties for each axis and device
}
Моя цель — запрограммировать управляющий класс, предоставляющий методы, которые можно использовать для установки этих переменных. Я попытался использовать шаблон стратегии (или, по крайней мере, что-то похожее на это). Шаблон дерева деталей машины заставил меня попытаться применить шаблон дважды (поскольку он имеет 2 уровня разделения). Один раз в сменных устройствах и один в сменных осях. Это код, который у меня есть до сих пор:
// Интерфейс управления устройствами и 2 разных класса устройств A и B
public class DeviceControl
{
public virtual IAxis Axis { get; set; }
public void Enable()
{
Axis.Enable = true;
}
public void Disable()
{
Axis.Enable = false;
}
}
public class DeviceControl_A : DeviceControl
{
public override IAxis Axis
{
get { return base.Axis as IAxis_A; }
set { base.Axis = value as IAxis_A; }
}
}
public class DeviceControl_B : DeviceControl
{
public override IAxis Axis
{
get { return base.Axis as IAxis_B; }
set { base.Axis = value as IAxis_B; }
}
}
Представление осей (интерфейс и явные классы): в основном они предназначены для сопоставления переменных в static
классе Mashine
со свойствами различных осей.
public interface IAxis
{
bool Enable { get; set; }
}
// These Interfaces are to ensure that Axis_A goes only into Device A
// and Axis_B only with device B
public interface IAxis_A : IAxis { }
public interface IAxis_B : IAxis { }
public class X_Axis_A : IAxis_A
{
public bool Enable
{
get => Mashine.Enable_A_X;
set => Mashine.Enable_A_X = value;
}
}
public class Y_Axis_A : IAxis_A
{
public bool Enable
{
get => Mashine.Enable_A_Y;
set => Mashine.Enable_A_Y = value;
}
}
public class X_Axis_B : IAxis_B
{
public bool Enable
{
get => Mashine.Enable_B_X;
set => Mashine.Enable_B_X = value;
}
}
public class Y_Axis_B : IAxis_B
{
public bool Enable
{
get => Mashine.Enable_B_Y;
set => Mashine.Enable_B_Y = value;
}
}
И это класс управления, который предоставляет методы управления машиной в зависимости от устройства и соответствующей оси:
public enum Device { A, B }
public enum Axis { X, Y }
public class Control
{
public DeviceControl devControl;
public void Disable(Device dev, Axis dim)
{
// initialize
InitAxisAndDevice(dev, dim);
devControl.Disable();
}
public void Enable(Device dev, Axis dim)
{
InitAxisAndDevice(dev, dim);
devControl.Enable();
}
private void InitAxisAndDevice(Device dev, Axis dim)
{
switch (dev)
{
case Device.A:
this.devControl = new DeviceControl_A();
switch (dim)
{
case Axis.X: this.devControl.Axis = new X_Axis_A(); break;
case Axis.Y: this.devControl.Axis = new Y_Axis_A(); break;
case Axis.Z: this.devControl.Axis = new Z_Axis_A(); break;
}
break;
case Device.B:
this.devControl = new DeviceControl_B();
switch (dim)
{
case Axis.X: this.devControl.Axis = new X_Axis_B(); break;
case Axis.Y: this.devControl.Axis = new Y_Axis_B(); break;
case Axis.Z: this.devControl.Axis = new Z_Axis_B(); break;
}
break;
}
}
}
Вопрос 1
Как я могу избежать этого случая двойного переключения в методе InitAxisAndDevice
?
Вопрос 2
Есть ли лучший способ убедиться, что только оси типа A совместимы с устройством A?
У меня есть стойкое ощущение, что я что-то неправильно понял в применении этого шаблона. Может быть, есть другой подход/шаблон, который был бы более подходящим для решения этой проблемы сопоставления управления?
Любая помощь очень приветствуется. Заранее спасибо.
ИЗМЕНИТЬ
Поскольку я был слишком расплывчатым в объяснении, вот пример использования. Все оси имеют почти идентичный набор переменных, которые должны быть установлены, например: [enable(bool), position(double), start(bool)]
Точка абстракции состоит в том, чтобы иметь один класс управления, который может использовать один метод Enable
f.e. для включения любой оси в зависимости от типа устройства и типа оси.
надеюсь стало немного понятнее
public interface IAxis_A : IAxis { }
? Пожалуйста, попробуйте описать желаемыйControl
интерфейс (т.е. публичные методы, которые вам нужны). - person Zohar Peled   schedule 15.11.2017DeviceControl.Enabled
устанавливает соответствующую переменную, соответствующую типу устройства и типу оси, и отправляет ее в ПЛК. - person Mong Zhu   schedule 15.11.2017