From Design Pattern by Gang of Four enter image description here

Why are field observers, and methods Attach, Detach and Notify are in the interface Subject, while methods GetState and SetState and field SubjectState are in the concrete subclass ConcreteSubject? Why are the members distributed in the subject interface and concrete subclass as they are?

Why is method Update in the interface Observer, while fields subject and observerState in the concrete subclass ConcreteObserver? Why are the members distributed in the observer interface and concrete subclass as they are?

There doesn't seem to be symmetry between subject and observer. For example, why does field observers belong to interface Subject, while field subject belong to ConcreteObserver?

Thanks.

2

There are 2 answers

2
Avishek Bhattacharya On

The method GetState and SetState in the Subject interface would make Subject interface dependent on how the dependent objects are updated. This is a violation of Dependency Inversion principle.

All Subject interface does is attach a concrete subject and notifies the observer. How the states of the concrete objects are changing it is independent of that. This is the reason why getState and setState not part of the Subject Interface.

Similar reason why observeState is not part of Observer interface.

0
Kedar Tokekar On

This is an Observer Design pattern. All the GOF patterns will use OO principles to maximum extent. If the responsibilities (and state) are common in many child classes those need to be escalated in the base class hierarchy to the uppermost possible layer. Following demo code and comments will answer the above questions. Its true that some of the design patterns (and Observer is one of those. see the type casting in update()) violate the OO principles. Its perfectly fine to violate these principles only one needs to know which principle and why we are violating. and check - are we getting more benefit than the probable inflexibility/ damage introduced in to the implementation?

    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();
        }
    }