chaper 1 questions · web viewthus, in the model, the context can push data to the dependents, and...

9
Chaper 2 Notes – Observer Pattern Motivating Observer 1. A common situation is when the state of an object (Context) changes, the object needs to inform some dependent objects (DependentObj’s): What are the problems with this? 1. Requires the context to have concrete references to the dependent objects. What if dependent objects change? What if we want to add another dependent object? Answer: the context has to change. 2. What if the dependent objects are only known at run time? In other words, there may be a number of classes that can supply the services, but the ones that are available at any point in time is not known. 3. What if we want to swap out dependent objects at run-time. We can’t do it unless they have the same class. 4. The DependentObj some responsibilities. It is easy to get part of these embedded in the context. All this points to heavy coupling which we would like to avoid. 2. Consider this design principle: program to an interface, not an implementation. If we apply this principle, then we can find what is common in the dependent objects and put that in an interface (or abstract class). In this case, we’ve decided that the Dependent interface will specify a method, m. This now lets the context depend on the common interface, not the (different) concrete classes of the dependent objects. Consider the Context class: The addDependent method is used to add dependent objects to the context. A client can use the change method to change the state of the Context, which in turn calls notifyDependents to let them know of the changes. The notifyDependents method loops through the list of dependents and call their m method. 1

Upload: others

Post on 23-Jan-2021

1 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Chaper 1 Questions · Web viewThus, in the model, the context can push data to the dependents, and the dependents can pull data from the context. This is the observer pattern. The

Chaper 2 Notes – Observer Pattern

Motivating Observer

1. A common situation is when the state of an object (Context) changes, the object needs to inform some dependent objects (DependentObj’s):

What are the problems with this?

1. Requires the context to have concrete references to the dependent objects. What if dependent objects change? What if we want to add another dependent object? Answer: the context has to change.

2. What if the dependent objects are only known at run time? In other words, there may be a number of classes that can supply the services, but the ones that are available at any point in time is not known.

3. What if we want to swap out dependent objects at run-time. We can’t do it unless they have the same class.

4. The DependentObj some responsibilities. It is easy to get part of these embedded in the context.

All this points to heavy coupling which we would like to avoid.

2. Consider this design principle: program to an interface, not an implementation. If we apply this principle, then we can find what is common in the dependent objects and put that in an interface (or abstract class). In this case, we’ve decided that the Dependent interface will specify a method, m. This now lets the context depend on the common interface, not the (different) concrete classes of the dependent objects. Consider the Context class:

The addDependent method is used to add dependent objects to the context. A client can use the change method to change the state of the Context, which in turn calls

notifyDependents to let them know of the changes. The notifyDependents method loops through the list of dependents and call their m method.

1

Page 2: Chaper 1 Questions · Web viewThus, in the model, the context can push data to the dependents, and the dependents can pull data from the context. This is the observer pattern. The

3. Consider this design principle: separate the things that change from the things that stay the same. With the current design, we see that the add, remove and notify methods don’t change while the change method and the state have a higher likelihood of changing. Why? Because it is a context and every problem will have a different context. Another way to look at this in terms of cohesion. Another design principle says: one class, one responsibility. Here, we could argue that the add, remove and notify methods are concerned with communication through a common interface. The change method (and others) are responsible for managing the context itself.

4. All this leads us to abstract out the context. When we separate the communication from the context, we effectively get a framework for communication which can be extended to provide an implementation for a specific context.

2

Page 3: Chaper 1 Questions · Web viewThus, in the model, the context can push data to the dependents, and the dependents can pull data from the context. This is the observer pattern. The

5. The framework above may work for a particular type of context. As shown above, there is a dependence on the parameters x and y. However, we can generalize this further as shown below. Notice that the method m now defines an Object parameter. Thus, a particular context can send any object it wants through the framework and rely on the dependent objects to be able to cast this to whatever it is. And, if that is not enough for the dependent objects, they also get a copy of the abstract context itself, which can be cast to the specific context and then dependent objects can fetch whatever they need. Thus, in the model, the context can push data to the dependents, and the dependents can pull data from the context. This is the observer pattern.

6. The figure above is the Observer Pattern. It is shown in the more usual format below. The idea is that Observers observe objects that are Observable (some authors use Subject and ConcreteSubject instead of Observable and ConcreteObservable). When an Observable object changes, it calls notify to inform all the Observers. This is also called the Publish-Subscribe pattern.

7. Summary:

The Observer Pattern provides a mechanism so that an object can notify dependent objects of changes without having to know their concrete classes.

The Observer Pattern defines a one-to-many dependency between object so that when one object changes state, all of its dependents are notified and updated automatically [HFDP]

Design Principle: Strive for loosely coupled designs between objects that interact (new).

3

Page 4: Chaper 1 Questions · Web viewThus, in the model, the context can push data to the dependents, and the dependents can pull data from the context. This is the observer pattern. The

8. Example. The Observer pattern transforms:

to:

4

Page 5: Chaper 1 Questions · Web viewThus, in the model, the context can push data to the dependents, and the dependents can pull data from the context. This is the observer pattern. The

Observer in Java

1. The java.util package supplies the (concrete) Observable class and the Observer interface as shown below.

Implementation details:

a. The Observable class has a private flag that is set to false initially. When the flag is false, a call to notify does nothing, the observers are not notified. A protected method, setChanged sets the flag to true. Then, a subsequent call to notify will call update on all observers and then set the flag back to false. So, we can view this flag as a protection mechanism in the sense that clients can call notify at any time, but notify will only work when the subclass has previously called setChanged. Thus, a client can call notify, but only the concrete observable can allow the notification to take place. The clearChanged method sets the flag to false so that calls to hasChanged return false.

b. The update method has two parameters, a reference to the Observable and an arbitrary Object.

c. The notify method is overloaded. If it is called with no argument, then null is used as an argument in the update method. Otherwise, notify can be called with an argument which is then used as an argument to the update method. Thus, we can push information to the observers if we want.

d. The order of notification of observers is not specified. In other words, if we want a specific order, we would need to write our own Observable.

2. Design questions:

a. Who should call notify? The client or the ConcreteObservable?b. Should we push data to the observers or should we require that observers pull the information they

need?c. How could we prevent clients from being able to call notify?d. Do we want the observers to access everything in the observable?

Of course, we could write our own observable to solve these problems.

5

Page 6: Chaper 1 Questions · Web viewThus, in the model, the context can push data to the dependents, and the dependents can pull data from the context. This is the observer pattern. The

3. Sometimes the ConcreteObserver(s) may contain a reference to the ConcreteObserverable so that it can disconnect itself at any time or for convenience.

4. GUI Event handling in Java Swing (and AWT and JavaFX) utilizes the Observer Pattern for GUI elements that can be interacted with by a user. For instance, when a user presses a button, an event is fired, which triggers the execution of some code to handle the event. In Java, ActionListeners handle events by supplying an actionPerformed method and are registered with GUI elements.

6

Page 7: Chaper 1 Questions · Web viewThus, in the model, the context can push data to the dependents, and the dependents can pull data from the context. This is the observer pattern. The

Other Examples

1. Observers that are also observable

2. ObservableList is an interface which is also a List and utilizes ListChangeListeners that receives notifications of changes to the ObservableList. Such a list can be created with: FXCollections.observableArrayList(), which is simply an ArrayList with a wrapper to make it observable.

3. C# has a more general approach to the Observer pattern through the use of delegates and events.

Observablepublic class A {

// Declare the signature of an event handler public delegate void MyDelegate( Object arg );

// Declare the name of the eventpublic event MyDelegate MyEvent;

public void MyMethod(); {...// Fire the eventMyEvent( myArg );

}}

Observerpublic class B {

...// A method that matches the delegate signaturepublic void MyEventHandler( Object thing ) {

...}...

}

Driverpublic class C {

...A a = new A()B b = new B()

// Create delegate instance and bind to event handlerA.MyDelegate del = new A.MyDelegate( b.MyEventHandler );

// Add delegate to eventA.MyEvent += del;

...}

4. How does recalculation work in Excel, or any spreadsheet? What is a circular reference? Draw a class diagram of a circular reference.

7