Как правильно спроектировать / реализовать два (или более) класса, которые имеют отношения «имеет» с одним и тем же объектом? - PullRequest
4 голосов
/ 18 сентября 2008

Предположим, у меня есть такой дизайн:

Объект GUI имеет два объекта: объект aManager и объект bManager, которые никогда не общаются друг с другом.

Как aManager, так и bManager имеют объект cManager в качестве атрибута (или, скорее, указатель на cManager). Поэтому, когда aManager изменяет свой cManager, он также влияет на cManager bManager.

Мой вопрос: как правильно спроектировать / реализовать это?

Я думал о создании cManager как атрибута GUI, и GUI передает указатель на cManager при создании aManager и bManager. Но IMHO, GUI не имеет ничего общего с cManager, так почему же GUI должен иметь его как атрибут?

Есть ли здесь особый шаблон проектирования, который я должен использовать?

Ответы [ 7 ]

1 голос
/ 18 сентября 2008

Используйте синглтоны с осторожностью (или не используйте их вообще, если вам нужны простые тесты!)

1 голос
/ 18 сентября 2008

Я рекомендую просто передать cManager в качестве параметра в вашем конструкторе GUI-объекта, но не поддерживать ссылку на него (здесь Java-код, но вы поняли):

public GUI(CManager cManager)
{
    this.aManager = new AManager(cManager);
    this.bManager = new BManager(cManager);
    // don't bother keeping cManager as a field
}

Я не думаю, что здесь подходит Singleton или Factory.

1 голос
/ 18 сентября 2008

Я собираюсь объяснить это как можно проще, если я не отвечаю на ваш вопрос, я прошу прощения.

Когда вы действительно получите ответ на этот вопрос, это ваш первый шаг к реальному мышлению Объектно-ориентированного.

В ОО, когда два объекта оба "имеют" другой объект, вполне допустимо, чтобы оба ссылались на этот другой объект. Уловка с ОО состоит в том, что у объектов есть собственная жизнь, они текучие, и любой, кто нуждается в них, может сохранить ссылку на них. Объект должен сохранять себя «Действительным» и поддерживать стабильность при использовании многими другими объектами. (Вот почему неизменяемые объекты, такие как String, так хороши, они ВСЕГДА действительны, как и во время их создания)

Единственное исключение - если вы кодируете в C ++, потому что тогда вам действительно нужно вручную освобождать объекты, что подразумевает владельца, который может отслеживать жизненный цикл каждого объекта - что делает действительно очень трудным «думать» в ОО в С ++.

[Дополнение] Поскольку вы имеете в виду указатели, я думаю, что вы программируете на C ++, что отличается. В этом случае вы правы. Сделайте одного менеджера "своим" для жизненного цикла вашего общего объекта. Он не должен позволить этому объекту умереть, пока все другие ссылки не исчезнут.

Вы также можете использовать подсчет ссылок. Всякий раз, когда кто-то получает ссылку на ваш объект, он вызывает «addReference» или что-то еще, когда это делается, он удаляет ссылку. Если кто-то вызывает removeReference, когда счетчик равен 1, объект может очиститься. Это, вероятно, настолько близко, насколько вы можете прийти к истинному распределению / освобождению в ОО-стиле в C ++. Это очень подвержено ошибкам.

Я полагаю, что есть библиотеки для таких вещей.

0 голосов
/ 05 января 2013

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

При переходе с C ++ на Java или .net можно подумать: «Эй, круто, мне больше не нужно беспокоиться о владении объектами», но это не так. Право собственности на изменчивые объекты так же важно в системе на основе GC, как и в системе без GC. Отсутствие каких-либо средств выражения права собственности не освобождает программиста от обязанности знать, кому что принадлежит. Это только усложняет выполнение этого обязательства.

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

Даже если кто-то использует язык или структуру, которая не признает какую-либо концепцию владения, всегда думайте такими терминами, когда имеете дело с изменчивыми объектами. Делать иначе - значит вызывать смятение и бедствие.

0 голосов
/ 18 сентября 2008

Сложно ответить без обсуждения того, чего вы хотите достичь. Но я бы сказал, что нужно заставить GUI передавать указатель на aManager и bManager, как вы говорите.

Если вы пытаетесь создать графический интерфейс и хотите знать, как вводить и выводить данные, я могу порекомендовать это: http://codebetter.com/blogs/jeremy.miller/archive/2007/07/25/the-build-your-own-cab-series-table-of-contents.aspx

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

Как новичок, я рекомендую вам не пытаться делать все наиболее совершенным и правильным способом с первого раза, а просто заставить что-то работать Со временем (и много читая) вы узнаете, что делает решение лучше других по различным критериям. Там нет правильного ответа на ваш вопрос.

0 голосов
/ 18 сентября 2008

Вы должны разобраться в том, как отделить графический интерфейс от модели и реализации.

Вы могли бы сделать cManager одиночным, если когда-либо существует только один cManager для всего приложения.

0 голосов
/ 18 сентября 2008

Вы можете использовать шаблон Factory для запроса ссылки на cManager как aManager, так и bManager по мере необходимости.

http://msdn.microsoft.com/en-us/library/ms954600.aspx

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...