MVC and Other Design Patterns

Preview:

DESCRIPTION

This is Class 6 on a 6 week course I taught on Software Design Patterns. This course provides an introduction into the MVC patterns and briefly goes over other patterns not covered in detail in the class.Class based on "Head First Design Patterns."

Citation preview

04/13/23 1

Design Patterns

Week 6: MVC and Other Patterns

Jonathan Simonjonathan_simon@yahoo.com

DJView

Pg 534

Two Different User Interfaces View – Shows BPM and Beat in real time Control – Enter BPM and click start button. Increase and

Decrease buttons.

Pg 535 Start and Stop buttons

204/13/23

DJView: Version 1 //Fields

int bpm;

Sequencer sequencer;

public DJView() {

//Display UI Elements

CreateDisplayView();

CreateControlView();

//Enable/Disable UI State

DisableStopMenuItem();

EnableStartMenuItem();

sequencer = new Sequencer();

}304/13/23

DJView: Version 1 public void StartButtonPushed() {

sequencer.start();

bpm = 90;

sequencer.setTempoInBpm(bpm);

DisableStartMenuItem();

EnableStopMenuItem();

DisplayBpm(bpm);

}

public void StopButtonPushed() {

sequencer.turnOff();

bpm = 0;

EnableStartMenuItem();

DisableStopMenuItem();

DisplayBpm(bpm);

} 4

DJView: Version 1public void SetBpm(int bpm) {

this.bpm = bpm;

sequencer.setTempoInBpm(bpm);

DisplayBpm(bpm);

}

public void IncreaseBpm() {

this.bpm = bpm + 1;

sequencer.setTempoInBpm(bpm);

DisplayBpm(bpm);

}

public void DecreaseBpm() {

this.bpm = bpm - 1;

sequencer.setTempoInBpm(bpm);

DisplayBpm(bpm);

}

5

DJView: Version 1

public void UpdateBeat() {

while (true) {

if (sequencer.BeatChanged)

DisplayBeat(sequencer.getBeat());

}

}

604/13/23

DJView: Version 1

704/13/23

Requirement Change… Now we need another screen (ArtistView) to display BPM.

(as well other information just as Song Name, Artist, Album Name, year, etc). Note: ArtistView is not interested in a change in Beat.

How can we display BPM? We can modify function DisplayBpm() to update ArtistView and

DJView whenever a change is made to BPM. What happens when we create another screen, say AlbumView?

804/13/23

So.. We have a few different screens (DJView, ArtistView,

AlbumView) that are all interested whenever we have a change in data state (BPM or Beat). Some screens are interested in change in BPM, others change

Beat, and some changes in both.

Currently, we have to update DJView whenever we want to add another screen that is interested in changes in BPM or Beat.

What pattern is screaming to be used?

904/13/23

Creating a Subject

We need a Subject that contains the data state that we know is changing.

In this example, what should fields should go in our Subject?

How many different events should our Subject expose?

How do we “glue” our Observers to this Subject?

1004/13/23

Subject = BeatModel public class BeatModel {

int bpm;

Sequencer sequencer;

public void initialize() {

sequencer = new Sequencer();

}

public void RegisterObserver(BeatObserver o) { }

public void RemoveObserver(BeatObserver o) { }

public void NotifyBeatObservers() { }

public void RegisterObserver(BPMObserver o) { }

public void RemoveObserver(BPMObserver o) { }

public void NotifyBpmObservers() { }

}

11

BeatObserver and BPMObserver

public interface BeatObserver {

void updateBeat();

}

public interface BPMObserver {

void updateBPM();

}

1204/13/23

DJView: Version 2 //Fields

int bpm;

Sequencer sequencer;

public DJView() {

//Display UI Elements

CreateDisplayView();

CreateControlView();

//Enable/Disable UI State

DisableStopMenuItem();

EnableStartMenuItem();

sequencer = new Sequencer();

}

1304/13/23

Changes???

DJView: Version 2//Fields

BeatModel model;

public DJView() {

//Display UI Elements

CreateDisplayView();

CreateControlView();

//Enable/Disable UI State

DisableStopMenuItem();

EnableStartMenuItem();

model = new BeatModel();

model.initialize();

}

1404/13/23

DJView: Version 2 public void StartButtonPushed() {

sequencer.start();

bpm = 90;

sequencer.setTempoInBpm(bpm);

DisableStartMenuItem();

EnableStopMenuItem();

DisplayBpm(bpm);

}

public void StopButtonPushed() {

sequencer.turnOff();

bpm = 0;

EnableStartMenuItem();

DisableStopMenuItem();

DisplayBpm(bpm);

} 15

Does DJView have a direct reference :To sequencer? To bpm field?

DJView: Version 2public void StartButtonPushed() {

model.on();

DisableStartMenuItem();

EnableStopMenuItem();

DisplayBpm(bpm);

}

public void StopButtonPushed() {

model.off();

EnableStartMenuItem();

DisableStopMenuItem();

DisplayBpm(bpm);

}

1604/13/23

What should we do with this DisplayBpm function?

What interfaces does DJView need to implement? Remember BeatModel…

DJView: Version 2public class DJView : BeatObserver, BPMObserver {

public void updateBeat() {

//Display change in Beat in the UI

}

public void updateBpm() {

int bpm = model.getBpm();

if (bpm == 0)

//Display "offline"

else

//Display "Current BPM" with value

}

}

}

}

1704/13/23What are we missing?

DJView: Version2

public DJView() {

//Display UI Elements

CreateDisplayView();

CreateControlView();

//Enable/Disable UI State

DisableStopMenuItem();

EnableStartMenuItem();

model = new BeatModel();

model.initialize();

model.RegisterObserver((BeatObserver)this);

model.RegisterObserver((BPMObserver)this);

}

1804/13/23

DJView: Version 2public void StartButtonPushed() {

model.on();

DisableStartMenuItem();

EnableStopMenuItem();

}

public void StopButtonPushed() {

model.off();

EnableStartMenuItem();

DisableStopMenuItem();

}

public void SetBpm(int bpm) {

model.setBPM(bpm);

}

public void IncreaseBpm() {

model.increaseBpm();

}

public void DecreaseBpm() {

model.decreaseBpm();

}19

Version 2

2004/13/23

Notice beatObservers and bpmObservers in BeatModel.

View and Model

We now have a View and a Model

The View is also an Observer. It is interested in changes in the Model.

When the Model has a data change, the View gets notified (updateBPM). The View then gets data from the Model (getBPM).

We can have multiple Views all interested in this Model.

2104/13/23

Multiple Views w/One Model

2204/13/23

Question: Does the Model know any specific details about the UI elements on the View?

Definition (Partial): Model

Contains the data, state, and application logic.

State changes can occur internally or externally. (more on this later).

When a change of state occurs, the Model sends a notification message.

The Model doesn’t have any direct references to the Views that need it. (Since the Views registers themselves with the Model).

2304/13/23

Definition (Partial): ViewGraphic User Interface.

It is the “window” to the model.

View registers with the Model for notification of certain events.

When notified by the Model, the View asks the Model for state information.

View must have a direct reference to the Model in order to get data. (can also be an interface the Model uses)

2404/13/23

Requirement Change We need to change all of these views from a Windows

application to a Web application.

We would like to minimize the amount of code that we need to re-write for the new user interface.

Let’s look at the DJView code again..

2504/13/23

DJView: Version 2public DJView() {

CreateDisplayView();

CreateControlView();

DisableStopMenuItem();

EnableStartMenuItem();

//Hidden: Create model, initialize and register observers

}

public void StartButtonPushed() {

model.on();

DisableStartMenuItem();

EnableStopMenuItem();

}

public void updateBeat() { ... }

public void updateBPM() { ... }

26

We know that we cannot re-use UI elements when we change Views.

Challenge

We want to separate elements from DJView that vary from the things that do not vary.

What varies?

What does not vary?

2704/13/23

What Varies Internals of CreateDisplayView() + CreateControlView() Internals of all of the Disable/Enable methods The internals of the updateBeat and updateBPM that has to do

with updating UI How events are associated with UI element

What does not vary The sequence of events. For example, StartButtonPushed has

a specific set of steps. Calling the Model to do something (on(), off()) Registering View with the Model The internals of the updateBPM that has to do with getting data

from the Model

2804/13/23

Inheritance Base View class that contains:

Reference to BeatModel Template Pattern to define known set of steps; use abstract

methods for pieces that need to be implemented by sub class.

Each subclass just defines the UI specific elements.

What problems will we encounter?

2904/13/23

Inheritance (cont)

We can’t inherit form the base View and the specific UI form (which contains a lot of functionality for interacting with UI elements)

We would need to inherit from the Base View and wrap the specific UI element (Windows or Web form) and then expose what we need. (Adapter Pattern!)

This would be painful…

3004/13/23

Composition View just contains the UI elements and functions that

manipulate the UI elements (What Varies)

View associates UI element with a handler. (What Varies)

The UI handler may do a special sequence of events (which may manipulate a combination of model changes and UI updates). This is What Not Varies.

Here is our separation of View and Controller (the New Guy).

3104/13/23

What about the Model?

The View interacts with the Model in two ways:

1) Sends a message to the Controller to update the Model. (setBPM, increase, decrease)

2) Gets notified when Model changes (updateBeat, updateBPM)

3204/13/23

DJView: Version 3 (Pt 1)

public class DJView : BeatObserver, BPMObserver {

BeatModel model;

BeatController controller;

public DJView(BeatModel model, BeatController controller)

{

this.model = model;

this.controller = controller;

model.RegisterObserver((BeatObserver)this);

model.RegisterObserver((BPMObserver)this);

}

public void updateBeat() { . . }

public void updateBPM() { . . }

3304/13/23

Note: The only reason that View needs Model is for registering of events and getting state from Model.

DJView: Version 3 (Pt 2)public void StartButtonPushed() {

controller.start();

}

public void StopButtonPushed() {

controller.stop();

}

public void SetBpm(int bpm) {

controller.setBPM(bpm);

}

public void IncreaseBpm() {

controller.increaseBPM();

}

public void DecreaseBpm() {

controller.decreaseBPM();

}

3404/13/23

The View delegates all actions to the Controller.

DJView: Version 3 (Pt 3)

//Lastly, we have all of the functions that directly manipulate

//UI elements in the View. These functions are called externally

//by the Controller!

public void CreateDisplayView() { }

public void CreateControlView() { }

public void DisableStopMenuItem() { }

public void EnableStopMenuItem() { }

public void DisableStartMenuItem() { }

public void EnableStartMenuItem() { }

3504/13/23

NOTE: If we have to port this View from Windows to Web, here is where the crux of our changes will occur.

BeatControllerpublic class BeatController {

BeatModel model;

DJView view;

public BeatController(BeatModel model)

this.model = model;

view = new DJView(model, this);

view.CreateDisplayView();

view.CreateControlView();

view.DisableStopMenuItem();

view.EnableStartMenuItem();

model.initialize();

}36

Why???

BeatController

public void start() {

model.on();

view.DisableStartMenuItem();

view.EnableStopMenuItem();

}

public void stop() {

model.off();

view.EnableStartMenuItem();

view.DisableStopMenuItem();

}

public void setBPM(int bpm) {

model.setBPM(bpm);

}

3704/13/23

Controller sends a message to Model to update data…and sends a message back to the View.

Note: Not showing the Model here. It is exactly the same!

The Big Picture

3804/13/23

See diagram on page 530.

Definition: Model

Contains the data, state, and application logic.

State changes can occur internally or externally (by a message from the Controller)

When a change of state occurs, the Model sends a notification message to the Views that want to be notified.

The Model doesn’t have any direct references to the Views or Controllers that need it.

3904/13/23

Definition: ViewGraphic User Interface.

It is the “window” to the model.

View registers with the Model for notification of certain events. When notified by the Model, the View asks the Model for state information.

View must have a direct reference to the Model in order to get data. (can also be an interface the Model uses)

View delegates actions to the Controller.

4004/13/23

Definition: Controller

Handles user actions initiated on the View.

Informs the Model of any data changes.

When applicable, tells the View to change it’s UI state.

4104/13/23

Lab: Part I In BeatController.start() function does three things:

Sends on() message to the Model Sends DisableStartMenuItem() message to the View Sends EnableStopMenuItem() message to the View.

Then we get a requirement that the end user needs to change the Mode (Basic or Advanced) at any time. If user calls start() during Basic mode, the same functionality

occurs. If user calls start() during Advanced mode, the Basic mode

functionality occurs, but in addition, the UI displays a video of the song.

What can we do? What pattern can help us?

42

Lab: Part II

Let’s say we need to add permissions. Which object should be modified? (Model, View, Controller)

Let’s say a change in the Model needs to result in the enabling and disabling of certain UI elements in the View. What can we do?

4304/13/23

Answer : Part I BeatController can be an abstract class with default

implementation for all methods, except start (which can be marked abstract)

Create two classes that inherit from BeatController (Basic and Advanced). Each class defines the unique behavior of start.

Associate the View with the appropriate version of BeatController.

Use Strategy Pattern to change behavior at run time.

4404/13/23

Answer: Part II

Controller. We could easily create a Permission object that is accessed by the Controller. This has the benefit of keeping permission-related code out of the View.

Two Answers: The View can easily respond to the change in the Model and set

the appropriate UI elements; however, that is putting more business logic in the View.

Controller can become an Observer of certain events in the Model (in addition to the View!). If a certain change of state occurs in the Model, the Controller can tell the View which UI elements to change.

4504/13/23

Testing

Testing is a lot easier with MVC.

Unit Tests can target the Controller and Model.

It is harder to unit test the View.

4604/13/23

Frameworks for MVC

Spring MVC Java Swing Windows Presentation Foundation (WPF) ASP.NET MVC Framework PureMVC Bistro Apache Struts And many more…

4704/13/23

Model View Presenter (MVP)

Derivative of MVC.

Focuses on the Presentation Layer. For example, interaction of different UI elements on a form.

References http://en.wikipedia.org/wiki/Model-view-presenter http://www.mvcsharp.org/

4804/13/23

Other Patterns

Iterator Composite Builder Façade State Chain of Responsibility Flyweight Memento

4904/13/23

Iterator

GoF Intent: “Provides a way to access the elements of an aggregate object sequentially without exposing its underlying representation.”

There are different types of “aggregate objects” Collection ArrayList List<> Array string[]

5004/13/23

Iterator (cont)

Each of these objects have different ways of looping through and accessing different elements.

Iterator patterns hides the implementation of the aggregate object from the clients that access it.

Advantage: You can change an ArrayList into a List<> without breaking clients that use you it.

5104/13/23

Composite

GoF Intent: “allows you to compose objects into tree structures to represent whole-part hierarchies. Composite lets clients treat individual objects and composition of objects uniformly.”

Think of a tree hierarchy Business objects User Interface elements (Window Panel Button)

A Node (with Children) and a Leaf Node are all treated the same.

5204/13/23

Composite (cont)

Example: Windows form where all UI elements are in a tree. Message is sent to top node to “disable all elements”. The tree is traversed and Disable message is applied to each node in the tree.

Composite and Iterator are often used together.

5304/13/23

Builder

Encapsulate the construction of a product and allow it to be constructed in steps.

Good for the creation of complex objects.

Client sends multiple messages to the Builder for creating certain parts of the structure. Then Builder returns Composite result.

5404/13/23

Facade

“Provides a unified interface to a set of interfaces in a subsystem. Façade defines a higher-level interface that makes the subsystem easier to use”.

Example, communication between Business and Data Layer.

5504/13/23

State Pattern GoF Intent: “Allows an object to alter its behavior when

its internal state changes. The object will appear to change its class.”

Strategy Pattern – behavior change due to an external change. (Remember the setBehavior() method). The Clients had to be aware of the different possible Strategies.

State is basically like Strategy; however, changes occur internally.

5604/13/23

Chain of Responsibility

“Avoid coupling the sender of a request to its receiver by giving more than one object a chance to handle the request. Chain the receiving objects and pass the request along the chain until an object handles it.”

Each object in chain acts as a handler. If it cannot handle the request, passes it to the next object in the chain.

Often using in Windows system for handling events generated by keyboard or mouse.

5704/13/23

Flyweight

GoF Intent: “Use sharing to support large numbers of fine-grained objects efficiently.”

Addresses memory issues.

Instead of having 100 large objects that take up memory: One stateless object Manager object that contains the state of the 100 objects

Single instances will not be able to behave independently from other instances. (Probably better for read-only purposes!)

5804/13/23

Memento

Be able to return object to a previous state.

Handle undo.

5904/13/23

Next Steps?

Read the rest of the book!

Buy the Gang of Four book to get more details on the patterns mentioned in this book.

Understand commonly used frameworks MVC Spring Dependency Injection

6004/13/23

Martin Fowler

http://www.martinfowler.com/ Refactoring: Improving the Design of Existing Code Patterns of Enterprise Application Architecture

6104/13/23

Recommended