Шаблон для атрибута класса, который может быть изменен только другими

Допустим, у меня есть класс Door и класс Lock. Экземпляры класса Door имеют свойство lock, которое является экземпляром класса Lock.

Я хочу, чтобы дверь «владела» этим экземпляром замка, но я не хочу, чтобы дверь могла изменить свой собственный замок. Например, я НЕ хочу, чтобы это было возможно:

class FancyDoor extends Door {
    function unlockMyself() {
        $this->lock->locked = false;
    }
}

Но я ДЕЙСТВИТЕЛЬНО хочу, чтобы дверной замок был доступен другим классам. Например, мне нужен класс DoorMan, чтобы иметь возможность запирать и открывать двери. Так что это не так просто, как сделать все свойства блокировки приватными.

Есть ли шаблон для этого? Я в основном работаю на PHP, но ответ должен быть специфичным для языка. Заранее спасибо.


person emersonthis    schedule 09.10.2016    source источник


Ответы (1)


Я предполагаю, что вы обеспокоены тем, что после того, как FancyDoor был закодирован без метода unlockMyself, какой-нибудь разработчик в будущем может непреднамеренно добавить его и испортить контракт.

Избежать этого было бы очень сложно, если lock принадлежит Door, учитывая саму природу классов. Я могу думать о следующем:

  • Door не имеет экземпляра lock.
  • Lock is modeled as a separate class. You can use State Pattern for it, because:
    • You might want to add more states, apart from lock and unlock, in future.
    • Тот же класс можно повторно использовать для работы, скажем, с Window в будущем. Его не нужно связывать с Doors.
  • DoorManager или что-то, что состоит из этих двух объектов. Этот класс предоставляет методы для блокировки/разблокировки экземпляра Door, который у него есть.

По сути, DoorManager отвечает за один Door и связанный с ним Lock.

person ketan vijayvargiya    schedule 10.10.2016
comment
Верно. Это то, что я делаю сейчас, но это очень неуклюже, потому что мне всегда приходится проходить Дверь и Замок вместе, а менеджер должен отслеживать, чей есть чей. - person emersonthis; 10.10.2016
comment
Поместите их обоих в один класс и передавайте объект этого класса, а не передавайте их оба по отдельности. - person ketan vijayvargiya; 10.10.2016