агрегация нарушает инкапсуляцию

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

Улучшите слабую связь.

public class Car{
    private Engine engine;
    Car(Engine e){
        this.engine=e;
    }
}

В приведенном выше примере любая реализация класса Engine может быть создана и помещена в объект Car во время создания, а поскольку экземпляр Engine может жить без автомобиля, это идеальный пример агрегации. (этот пример может быть не лучшим примером из реальной жизни, но я думаю, что я выразил свою точку зрения)

Теперь клиентский код имеет полный контроль над объектом Engine, поэтому он может изменить несколько состояний объекта Engine, переданного в Car, а реализация Car нарушит инкапсуляцию, поскольку его объект или состояние (которое является Engine) больше не имеет правильная целостность в Автомобиле.

правильно ли я понимаю?


person Abhiram mishra    schedule 11.12.2012    source источник
comment
Это зависит от инкапсуляции, вы не хотите когда-либо изменять состояние объекта, а хотите управлять объектом. Итак, с двигателем вместо engine.setOn(boolean) у вас есть engine.turnOn(). Если вы хотите, чтобы автомобиль мог работать только с двигателем, то в конструкторе вы должны клонировать объект, чтобы ограничить доступ. this.engine = (Движок)e.clone(); другие операции с автомобилем могут быть удалены, тогда вы можете получить доступ к двигателю, но у автомобиля его больше нет.   -  person BevynQ    schedule 11.12.2012
comment
ИМО, я не думаю, что клиент имеет контроль над объектом Engine. Я бы предположил, что существует класс более высокого уровня под названием «Изготовитель», который создаст правильный объект «Двигатель» и установит его в качестве двигателя для конкретного объекта «Автомобиль».   -  person Vaibhav Desai    schedule 11.12.2012
comment
Я думаю, что он имеет в виду, что процесс создания автомобиля будет иметь отношение к двигателю, хотя этого быть не должно.   -  person BevynQ    schedule 11.12.2012
comment
@Vaibhav, я согласен, что правильно спроектированный класс должен быть таким, как, возможно, вы сказали: «Но производитель в этом случае становится клиентом, и он просто может изменить некоторое состояние объекта Engine сразу после создания автомобиля, и тогда объект автомобиля будет сделать сломанным. Вы так не думаете?   -  person Abhiram mishra    schedule 11.12.2012
comment
@BevynQ, тогда я бы предположил, что весь класс Engine доступен только для чтения.   -  person Vaibhav Desai    schedule 11.12.2012


Ответы (2)


Engine может быть нарушен Car только в том случае, если он изменчив, т.е. автомобиль может изменить состояние двигателя. Однако вы можете либо определить неизменяемый класс Engine (у которого есть только геттеры для доступа к состоянию и бизнес-методы, которые не изменяют состояние), либо создать интерфейс Engine, реализованный классом EngineImpl. EngineImpl не является неизменным. Он включает в себя функции, которые могут изменять свое состояние. Однако он реализует интерфейс Engine, который предоставляет клиенту только «неизменяемые» методы. Таким образом, автомобиль не может изменить состояние EngineImpl, скрытого за интерфейсом только для чтения Engine. В этом случае инкапсуляция не нарушается.

Вы правы: это не реальный пример: в реальном мире водитель управляет двигателем через интерфейс, предоставленный его автомобилем, и может сломать двигатель :(

person AlexR    schedule 11.12.2012
comment
Согласен, +1 вам. Только одно сомнение, очень тривиальное, изменяемая реализация сломает Car, а не Engine, верно? - person Abhiram mishra; 11.12.2012

Здесь слабая связанность нацелена на отношения между автомобилем и двигателем.

Хотя автомобиль принимает любой двигатель через свой конструктор, я считаю, что автомобиль не будет выставлять двигатель с помощью метода получения.

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

Разрешение клиенту Автомобиля получить доступ к Двигателю должно осуществляться через интерфейс Автомобиля.

person R Kaja Mohideen    schedule 11.12.2012
comment
Я думаю, вы упустили мою мысль, позвольте мне сказать так. Двигатель e = новый EngineImpl(); Автомобиль c = новый Автомобиль (e); e.setSomethingOnEngine();// Это может нарушить поведение машин - person Abhiram mishra; 11.12.2012
comment
e.setSomethingOnEngine() обычно не выполняется какой-либо фабрикой или шаблоном создания. Возможно, Builder может построить двигатель, но он не будет изменять двигатель после того, как он будет создан и отдан для внедрения в Автомобиль. Если да, то код созидательного паттерна нарушает принципы. - person R Kaja Mohideen; 17.12.2012