Создаем два класса: класс А и класс В. Требуется сделать так, чтобы объекты класса А могли изменять состояние только в результате запросов объектов класса В и никак иначе. (Например: "остаток на складе может изменяться только документами") Подскажите, как это лучше реализовать с архитектурной точки зрения.
Здравствуйте, Miroff, Вы писали:
M>Создаем два класса: класс А и класс В. Требуется сделать так, чтобы объекты класса А могли изменять состояние только в результате запросов объектов класса В и никак иначе. (Например: "остаток на складе может изменяться только документами") Подскажите, как это лучше реализовать с архитектурной точки зрения.
Можно экземпляры класса Б (умеющие работать с классом А) создавать только с помощью методов класса А. А саму реализацию класса Б поместить в локальный или анонимный класс, который сможет иметь доступ к private методам класса А (которые меняют его состояние).
Можно поместить класс А и Б в отдельный пакет (сборку?) и поставить методам класса А область видимости пакета.
Здравствуйте, Miroff, Вы писали:
M>Создаем два класса: класс А и класс В. Требуется сделать так, чтобы объекты класса А могли изменять состояние только в результате запросов объектов класса В и никак иначе. (Например: "остаток на складе может изменяться только документами") Подскажите, как это лучше реализовать с архитектурной точки зрения.
можно Observer, State или через фабрику в которой они зарегистрированы и через которую могут обмениваться сообщениями
Здравствуйте, Miroff, Вы писали:
M>Создаем два класса: класс А и класс В. Требуется сделать так, чтобы объекты класса А могли изменять состояние только в результате запросов объектов класса В и никак иначе. (Например: "остаток на складе может изменяться только документами") Подскажите, как это лучше реализовать с архитектурной точки зрения.
M>Создаем два класса: класс А и класс В. Требуется сделать так, чтобы объекты класса А могли изменять состояние только в результате запросов объектов класса В и никак иначе.
class A
{
void SetSomething(B sender, int value);
void SetSomethingElse(B sender, Date date);
}
Это даст возможность и ПОТОМКАМ B изменять A, что вам, скорее, понадобится.
Здравствуйте, Сим, Вы писали:
Сим>Здравствуйте, Miroff, Вы писали:
M>>Создаем два класса: класс А и класс В. Требуется сделать так, чтобы объекты класса А могли изменять состояние только в результате запросов объектов класса В и никак иначе. (Например: "остаток на складе может изменяться только документами") Подскажите, как это лучше реализовать с архитектурной точки зрения.
Сим>friend ф-ии?
Можно, конечно, но ИМХО это противоречит принципам ООП.
Здравствуйте, Miroff, Вы писали:
M>Создаем два класса: класс А и класс В. Требуется сделать так, чтобы объекты класса А могли изменять состояние только в результате запросов объектов класса В и никак иначе. (Например: "остаток на складе может изменяться только документами") Подскажите, как это лучше реализовать с архитектурной точки зрения.
Попробую уточнить постановку задачи. Изменяющих классов может быть много. Изменяемых тоже. А вопрос о правомерности изменения выносится на этап RunTime. При этом классы могут быть семантически различныим. ИМХО порождать их от общего предка или через общую фабрику — криво. Я думаю ввести класс посредник, который будет решать, разрешено воздействие или нет. Но может есть другое решение? Observer и State это немного не то.
Здравствуйте, Miroff, Вы писали:
M>Здравствуйте, Miroff, Вы писали:
M>>Создаем два класса: класс А и класс В. Требуется сделать так, чтобы объекты класса А могли изменять состояние только в результате запросов объектов класса В и никак иначе. (Например: "остаток на складе может изменяться только документами") Подскажите, как это лучше реализовать с архитектурной точки зрения.
M>Попробую уточнить постановку задачи. Изменяющих классов может быть много. Изменяемых тоже. А вопрос о правомерности изменения выносится на этап RunTime. При этом классы могут быть семантически различныим. ИМХО порождать их от общего предка или через общую фабрику — криво. Я думаю ввести класс посредник, который будет решать, разрешено воздействие или нет. Но может есть другое решение? Observer и State это немного не то.
Могу посоветовать почитать Александреску "Современное проектирование на С++"
Используй шаблоны ...
Здравствуйте, Miroff, Вы писали:
M>Создаем два класса: класс А и класс В. Требуется сделать так, чтобы объекты класса А могли изменять состояние только в результате запросов объектов класса В и никак иначе. (Например: "остаток на складе может изменяться только документами") Подскажите, как это лучше реализовать с архитектурной точки зрения.
Может быть что-то такое (Visitor, если я не ошибаюсь) с некоторыми модификациями? Попробую на основании примера
// Остатки
Class GoodRests
{
// применим правило
public AcceptRule(RuleDocument someModifier){ someModifier.Modify(this)}
}
// Правило. Создается только фабрикой правил
sealed Class RuleDocument
{
private RuleDocument()
{}
public Modify(GoodRests class)
{
// Какие-то изменения
}
}
class RuleFactory
(
// Для
static RuleDocument CreateModifier(КлассОбъектаКоторыйМожетПопроситьИзменения t)
{
CheckState(t); //
}
)
Идея состоит в том, что мы вводим класс, который может проверять состояние объекта, просящего модификацию, и, соответственно, разрешать изменения
Здравствуйте, Miroff, Вы писали:
M>Здравствуйте, Miroff, Вы писали: Я думаю ввести класс посредник, который будет решать, разрешено воздействие или нет. Но может есть другое решение? Observer и State это немного не то.
Ты собираешься ввести Mediator?
Но как ты собираешься разрешать эту же ситуацию с распознаванием "кто есть кто" (уже в методах медиатора), если не использовать (шаблонный или нешаблонный) вариант type_id?
M>Создаем два класса: класс А и класс В. Требуется сделать так, чтобы объекты класса А могли изменять состояние только в результате запросов объектов класса В и никак иначе. (Например: "остаток на складе может изменяться только документами") Подскажите, как это лучше реализовать с архитектурной точки зрения.
По-моему, так и делай, straightforward решением.
run-time:
Выдели весь сервис, к примеру "изменение остатка" в отдельный интерфейс, например
IInventoryBalanceChanger
Далее действуй по принципу COM — запрашивай интерфейсы-сервисы. Получив not-null ссылку, ты сможешь работать с сервисом, изменять состояние объекта, предварительно запросив его (или передав). Т.е. IInventoryBalanceChanger должен предоставлять свой сервис:
IInventoryBalanceChanger::ChangeBalance(IInventory* ptrInv, IDocument* ptrDoc);
compile-time
Запрос интерфейса (protocol-query) в C++ реализуется через dynamic_cast