Какова логика композиции в объектно-ориентированном дизайне?

Я запутался в композиции (есть) отношения. Мне понятно что например авто класс has a мотор класс. Моя проблема в том, что классы не имеют логически другого класса, но владеют им физически, чтобы использовать их. Вы должны иметь ссылку или собственный класс, чтобы использовать его методы, но иногда это не имеет смысла на логическом уровне. Например, скажем, есть класс garbage man и другой класс waste container, Мусорщик использует empty метод контейнера для отходов и, чтобы использовать его методы, имеет ссылку на контейнер для отходов. Означает ли это, что мусорщик имеет (ну, несколько) контейнер для отходов на объектно-ориентированном дизайне? Я бы сказал, что мусорщик использует мусорный контейнер, но это сбивает меня с толку, так как мусорщик физически имеет его. Может кто-нибудь сказать мне логику, пожалуйста?

2 ответа

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

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

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

GarbageMan не имеет WasteContainer, поскольку контейнер для отходов никоим образом не описывает мусорщика и не расширяет его атрибуты каким-либо образом.

Я думаю, что вы пропустили операцию здесь. WasteContainer имеет empty() метод, потому что это действие, которое может быть выполнено над ним. Но GarbageMan также есть операция. GarbageMan Можно performJob(), Вот где WasteContainer приходит. Рассмотрим что-то вроде этого (не зависит от языка):

class WasteContainer {
    empty() { ... }
}

class GarbageMan {
    performJob(Collection<WasteContainer> containers) {
        foreach (var container in containers) {
            container.empty();
        }
    }
}

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

Это может быть дополнительно абстрагировано с использованием интерфейса. Например:

interface Emptyable {
    empty();
}

class WasteContainer : Emptyable {
    empty() { ... }
}

class GarbageMan {
    performJob(Collection<Emptyable> bins) {
        foreach (var bin in bins) {
            bin.empty();
        }
    }
}

Сейчас GarbageMan далее отделен от WasteContainer, Там может быть много видов контейнеров, которые можно опорожнить, и GarbageMan может справиться со всеми из них. Операция выполняется идентично, просто предоставьте коллекцию контейнеров GarbageMan и он делает свою работу.

Это, кажется, более точно моделирует наблюдаемый сценарий реального мира, а не GarbageMan владеть состоянием WasteContainers, Там, вероятно, будут некоторые Employer который управляет каким WasteContainers отправляются на конкретный GarbageMan Например, могут быть разные Customerкто на самом деле владеет WasteContainerс или другие виды Emptyableс и т. д.

Другие вопросы по тегам