Скрыть для остального мира некоторые методы, используемые только внутренними классами - PullRequest
2 голосов
/ 22 августа 2010

Короткий вопрос

У меня есть одна C ++ модель домена. У него есть некоторые методы, используемые внутренним API , а также другие открытые методы . Я не хочу показывать эти методы API. Я имею в виду использование прокси-шаблона , чтобы скрыть эти методы . Ты думаешь, это хорошая идея? Есть ли какой-то шаблон дизайна для этого?

Длинный пример

Допустим, в некотором удаленном месте есть роботизированная рука, которая может управляться программным обеспечением, но также может быть перемещена вручную каким-либо техником. У него есть некоторые датчики, которые позволяют ему знать, какой объект он держит. В моем проекте это что-то совершенно другое, но я просто использую это в качестве примера. Так что у меня будет один RoboticArm класс, который содержит RoboticHeldObject абстрактный класс. RoboticArm даст вам знать, какой RoboticHeldObject он удерживает, не говоря уже о том, чтобы позволить вам двигать руку. Однако вы не можете решить поднять и отпустить объект. Это решает техник, управляющий роботом. Так что это будет что-то вроде:

---------------------------------------------
RoboticArm
---------------------------------------------
+ heldObject()             RoboticHeldObject*
+ moveUp()
+ moveDown()
+ releaseObject()
+ holdObject(RoboticHeldObject*)
---------------------------------------------
- heldObject               RoboticHeldObject*
- service                  RobotService

Поскольку реализация довольно сложная, я использую внешний класс RobotService , который фактически выполняет тяжелую работу. Однако это не модель анемичного домена, поскольку RoboticArm фактически использует RobotService (таким образом, обладает функциональностью), а остальной мир ничего не знает о RobotService .

Вопрос здесь следующий: releaseObject () и holdObject () - это методы API, используемые здесь только RobotService . Они вызываются только RobotService всякий раз, когда техник отпускает объект, удерживаемый рукой, или помещает новый объект. Таким образом, они вызываются, когда какое-то сетевое событие обрабатывается RobotService (помните, что рука находится в удаленном месте, поэтому события принимаются через сеть). Например:

RobotService::handleObjectReleaseEvent(event)
{
 RoboticArm *arm = correspondingRoboticArm(event);
 arm->releaseObject();
}

Мой подход

Чтобы скрыть эти методы, я бы переименовал RoboticArm в RealRoboticArm и создал прокси-класс RoboticArm :

---------------------------------------------
RoboticArm        (the proxy)
---------------------------------------------
+ heldObject()             RoboticHeldObject*
+ moveUp()
+ moveDown()
---------------------------------------------
- realArm                  RoboticArm*



---------------------------------------------
RealRoboticArm    (the real object)
---------------------------------------------
+ heldObject()             RoboticHeldObject*
+ moveUp()
+ moveDown()
+ releaseObject()
+ holdObject(RoboticHeldObject*)
---------------------------------------------
- heldObject               RoboticHeldObject*
- service                  RobotService

Поскольку RoboticArm является прокси-сервером, RoboticArm :: holdObject () будет вызывать realArm-> holdObject (), RoboticArm :: moveUp () realArm-> moveUp () и т. Д.

RobotService будет иметь указатель на экземпляр RealRoboticArm , поэтому он может вызывать методы API, такие как releaseObject (). Однако другие части приложения смогут использовать методы только в RoboticArm , поскольку у них нет указателя на RealRoboticArm . Таким образом, releaseObject () и holdObject () будут эффективно скрыты от аудитории.

Вопрос

Я не уверен на 100%, является ли это шаблоном прокси или шаблоном адаптера. Как вы думаете, это правильный способ моделирования такой системы? Есть ли лучший шаблон?

Ответы [ 2 ]

0 голосов
/ 22 августа 2010

Вы можете решить свою проблему, используя интерфейсы.У вас есть один объект, RobotArm, который реализует два интерфейса: один для API и один для класса using.

Использующий класс будет использовать свой интерфейс, а другой - без методов API и, следовательно, не сможет вызватьМетоды API.

0 голосов
/ 22 августа 2010

Обычно есть классы, которые делают одно и то же, но на разных уровнях абстракции.

Пример, в порядке уменьшения уровня абстракции:

  • GrabbingRobot.GrabBottle ();
  • SpaciousRobotArm.MoveToCoordinates (x, y);
  • RobotBase.Turn (градусы), RobotArm.Extend (дюймы)
  • RobotElbow.Bend (в градусах)
  • RobotServoMotor.Turn (циклы)
  • RobotServoRelais.TurnOn (секунды)

В вашем примере RoboticArm абстрагировался от удержания вещей из RealRoboticArm. Вместо того, чтобы устанавливать и отпускать вещи, RoboticArm волшебным образом знает, держит ли он что-то и что он держит. Это не прокси и не адаптер.

Нет достаточно сложной структуры разрешений, которая бы не позволяла GrabbingRobot напрямую вызывать RobotElbow.

...