Почему некоторые методы относятся к интерфейсу субъект / наблюдатель, а другие — к конкретному подклассу субъект / наблюдатель?

Из Дизайнерской картины Банды Четырех
введите описание изображения здесь

Почему поля observersи методы Attach, Detach а также Notify в интерфейсе Subjectв то время как методы GetState а также SetState и поле SubjectState находятся в конкретном подклассе ConcreteSubject? Почему члены распределены в предметном интерфейсе и конкретном подклассе как они есть?

Почему метод Update в интерфейсе Observerв то время как поля subject а также observerState в конкретном подклассе ConcreteObserver?
Почему члены распределены в интерфейсе наблюдателя и конкретном подклассе как они есть?

Кажется, нет симметрии между субъектом и наблюдателем.
Например, почему поле observers принадлежат интерфейсу Subjectв то время как поле subject принадлежать ConcreteObserver?

Благодарю.

0

Решение

Методы GetState и SetState в интерфейсе субъекта сделают интерфейс субъекта зависимым от того, как обновляются зависимые объекты. Это нарушение принципа инверсии зависимости.

Все, что делает предметный интерфейс — это прикрепляет конкретный предмет и уведомляет наблюдателя. То, как изменяются состояния конкретных объектов, не зависит от этого. Это причина, почему getState и setState не являются частью Subject Interface.

Похожая причина, по которой наблюдаемое состояние не является частью интерфейса Observer.

1

Другие решения

Это шаблон Observer Design. Все паттерны GOF будут максимально использовать принципы ОО. Если обязанности (и состояние) распространены во многих дочерних классах, их необходимо повысить в иерархии базовых классов до самого верхнего возможного уровня. Следующий демо-код и комментарии ответят на вышеуказанные вопросы.
Это правда, что некоторые шаблоны проектирования (и Observer — один из них. См. Приведение типов в update ()) нарушают принципы ОО. Нарушать эти принципы прекрасно, нужно знать, какой принцип и почему мы нарушаем.. и проверить — получаем ли мы больше пользы, чем вероятная негибкость / ущерб, внесенный в реализацию?

    public interface Observer {
/**
* IF THIS METHOD IS NOT HERE SUBJECT WILL NOT BE ABLE TO CALL IT
* REFER TO OO BASICS - INHERITANCE
*/
void update(Subject subject);
}

public abstract class Subject {
// THE COMPLETE LOGIC HERE IS INDEPENDENT OF
// WHO THE CONCRETE SUBJECT IS.
// HENCE THIS IS A RIGHT PLACE FOR IT AS PER OO PRINCIPLES
// NOTE THAT THIS CLASS KNOWS ONLY ABOUT ABSTRACT OBSERVER
private Set<Observer> observers;
public void add(Observer o){/*...*/}
public void remove(Observer o){/*...*/}
protected void notifyAllObservers(){
for (Observer observer : observers) {
observer.update(this);
}
}
}

class ConcreteSubject extends Subject {
/**
* HERE THERE IS NO NEED TO KNOW THE CONCRETE OBSERVER-
* By DEFINITION OF THIS PATTERN.
* THE JOB HERE IS TO ONLY NOTIFY ALL OBSERVERS THAT "I HAVE CHANGED"* ITS OBSERVER'S RESPONSIBILITY TO REACT IN PULL METHOD
*/

// Concrete Subject state
// Concrete Subject behavior
public void specificMethod(){
//... concrete class specific logic
}
}

class ConcreteObserver implements Observer{
@Override
public void update(Subject subject) {
/**
* OBSERVE HERE WE NEED TO TYPE CAST, WHICH LEADS TO VIOLATION OF
* OO PRINCIPLES. BUT WE GET BENEFIT OF LOOSELY COUPLED OBSERVERS
* AGAINST THIS EXTRA COST
* ITS SAFE TO VIOLATE HERE AS OBSERVER INSTANCES MAKE ONLY
* SENSE IN CONTEXT WITH SUBJECT AND WILL NEVER BE REUSED AS
* OBSERVERS IN UNRELATED CONTEXT.
*/
((ConcreteSubject)subject).specificMethod();
}
}
1

По вопросам рекламы [email protected]