Design Patterns in Java Chapter 22 State

Slides:



Advertisements
Similar presentations
Chapter 8 Singleton Summary prepared by Kirk Scott 1.
Advertisements

The Bridge Pattern.. Intent Decouple an abstraction from its implementation so that the two can vary independently Also known as: Handle/Body.
More Interfaces, Dynamic Binding, and Polymorphism Kirk Scott.
Programming with Java © 2002 The McGraw-Hill Companies, Inc. All rights reserved. 1 Chapter 12 More OOP, Interfaces, and Inner Classes.
Design Patterns in Java Appendix D UML at a Glance Summary prepared by Kirk Scott 1.
The State Pattern Joshua Hertz Nik Reiman. Roadmap What is the State Pattern What is the State Pattern Modeling States Modeling States Setup of the State.
Chapter 10 Classes Continued
1 Chapter 8 Objects and Classes. 2 Motivations After learning the preceding chapters, you are capable of solving many programming problems using selections,
REFACTORING Lecture 4. Definition Refactoring is a process of changing the internal structure of the program, not affecting its external behavior and.
Design Patterns in Java Chapter 21 Template Method Summary prepared by Kirk Scott 1.
Design Patterns in Java Chapter 13 Flyweight Summary prepared by Kirk Scott 1.
Design patterns. What is a design pattern? Christopher Alexander: «The pattern describes a problem which again and again occurs in the work, as well as.
CMSC 202 Exceptions. Aug 7, Error Handling In the ideal world, all errors would occur when your code is compiled. That won’t happen. Errors which.
CS1Q Computer Systems Lecture 8
Polymorphism, Inheritance Pt. 1 COMP 401, Fall 2014 Lecture 7 9/9/2014.
Unit 4 Prototype Summary prepared by Kirk Scott 1.
Design Patterns in Java Chapter 1 Introduction Summary prepared by Kirk Scott 1.
Unit 18 Strategy Summary prepared by Kirk Scott 1.
Unit 6 Proxy Summary prepared by Kirk Scott 1. Design Patterns in Java Chapter 11 Proxy Summary prepared by Kirk Scott 2.
Lecture 21 Multiple Inheritance. What is Multiple Inheritance? We defined inheritance earlier in the semester as a relationship between classes. If class.
Chapter 2 Introducing Interfaces Summary prepared by Kirk Scott.
3-1 State Design Pattern C Sc 335 Rick Mercer. State Design Pattern State is one of the Behavioral patterns It is similar to Strategy Allows an object.
Appendix D UML at a Glance Summary prepared by Kirk Scott 1.
Exceptions, cont’d. Factory Design Pattern COMP 401 Fall 2014 Lecture 12 9/30/2014.
Factory Method Explained. Intent  Define an interface for creating an object, but let subclasses decide which class to instantiate.  Factory Method.
Object-Oriented Programming (Java), Unit 28 Kirk Scott 1.
Programming with Java © 2002 The McGraw-Hill Companies, Inc. All rights reserved. 1 McGraw-Hill/Irwin Chapter 5 Creating Classes.
Interfaces About Interfaces Interfaces and abstract classes provide more structured way to separate interface from implementation
The State Pattern (Behavioral) ©SoftMoore ConsultingSlide 1.
Quick Review of OOP Constructs Classes:  Data types for structured data and behavior  fields and methods Objects:  Variables whose data type is a class.
Session 7 Introduction to Inheritance. Accumulator Example a simple calculator app classes needed: –AdderApp - contains main –AddingFrame - GUI –CloseableFrame.
Author: DoanNX Time: 45’.  OOP concepts  OOP in Java.
 Description of Inheritance  Base Class Object  Subclass, Subtype, and Substitutability  Forms of Inheritance  Modifiers and Inheritance  The Benefits.
Structure A Data structure is a collection of variable which can be same or different types. You can refer to a structure as a single variable, and to.
9.1 CLASS (STATIC) VARIABLES AND METHODS Defining classes is only one aspect of object-oriented programming. The real power of object-oriented programming.
Chapter 5 Introduction to Defining Classes Fundamentals of Java.
Summary prepared by Kirk Scott
Summary prepared by Kirk Scott
Summary prepared by Kirk Scott
Building Java Programs
Summary prepared by Kirk Scott
The Movement To Objects
Design Patterns in Java Chapter 23 Strategy
Chapter 5:Design Patterns
Unit 11 Generic Interfaces and Encapsulation, Continued
Summary prepared by Kirk Scott
More Interfaces, Dynamic Binding, and Polymorphism
Lecture 25 More Synchronized Data and Producer/Consumer Relationship
Summary prepared by Kirk Scott
About the Presentations
Creating Objects & String Class
Summary prepared by Kirk Scott
Chapter 3 Inheritance © 2006 Pearson Education Inc., Upper Saddle River, NJ. All rights reserved.
Chapter 17 Abstract Factory
Understanding Inheritance
Object Oriented Analysis and Design
Stacks.
Introduction to Behavioral Patterns (2)
Inheritance Dr. Bhargavi Goswami Department of Computer Science
Improving the structure of existing code
Stacks.
Focus of the Course Object-Oriented Software Development
CMSC 202 Generics.
Review of Previous Lesson
Review of Previous Lesson
EGR 2131 Unit 12 Synchronous Sequential Circuits
ECE 352 Digital System Fundamentals
ECE 352 Digital System Fundamentals
CMSC 202 Exceptions.
Presentation transcript:

Design Patterns in Java Chapter 22 State Summary prepared by Kirk Scott

In reference to an object, the term state can mean the particular set of values of its instance variables at a given time More broadly, for a system, the term state can refer to the collective states of the objects existing in the system at a given time In a more focused sense, state may refer to the value of a single, critical instance variable in an object (or system)

Not surprisingly, if the value of an instance variable is of interest, changes in the value are also of interest In an object oriented system, the state changes as a result of calls to methods—as a result of the logic of code in methods The current state may be critical in how methods act

In other words, methods of a class with some critical state characteristic may contain if statements If the state is x, the method does y; if the state is q, the method does r, and so on If this kind of code appears in multiple methods, changes in the logic of state handling can lead to a maintenance burden

A possible solution, the topic of this chapter, is to model state separately In other words, let state be represented by an object, not a single, simple instance variable or set of variables The goal is to move the if/then/else logic out of multiple methods in the domain classes, and into a single method in the state class

Book definition: The intent of the State pattern is to distribute state-specific logic across classes that represent an object’s state

Comment mode on: Although the book uses the term “distribute”, keep in mind that the overall goal, and saving, is that the state-specific logic will occur fewer times in the new model than in the old model Or particular bits of that logic will occur only once, in one state method, rather than many times, in several different domain methods

Modeling States The book summarizes this idea with this nice, object-oriented sounding phrase: The goal of the new model is to encapsulate state-specific logic in separate, state-related classes and methods As with many of the patterns already, the book illustrates this by giving a software design without state classes and then refactoring it using the State design pattern

The book’s example is based on a physical device that might occur in a fireworks factory setting The device is known as a carousel The carousel is a circulating storage rack which is enclosed and is accessed through a doorway The doorway is controlled with a button It is the doorway, and its state, and how the button works that are of particular interest

The functioning of the doorway and button can be summarized verbally as follows (this is a slightly more complete verbal summary than that given in the book) 1. If the doorway is closed, touching the button once will cause it to start opening 2. If the doorway is opening, touching the button (again) will cause it to start closing 3. If the door is open, it will stay open for 2 seconds and then automatically start closing

4. If the door is open and the button is touched during the 2 second interval, this will cause the doorway to stay open 5. If the door is open and the button has been touched to keep it open, touching the button again will cause it to start closing 6. If the doorway is closing, touching the button will cause it to start opening

If you analyze the situation, you find at least 4 states: closed, opening, closing, closed It turns out that given the actions, in a complete analysis there will also be a fifth state: stay open There are also transitions between states triggered by either touching the button or not touching the button

In situations like this, it is usually easiest to understand what’s going on with a diagram rather than a verbal description On the next overhead a state transition diagram is given for the carousel States are given as boxes with rounded corners Transitions are given as arrows, labeled with the action (or inaction) that triggers them

Challenge 22.1 Suppose that you open the door and place a material bin in the doorway. Is there a way to make the door begin closing without waiting for it to time out? Comment mode on: This question only really makes sense when you realize that point 5 of the verbal summary above isn’t given in the book

Solution 22.1 As the state machine shows, when the door is open, touching the one-touch button will take the door to the StayOpen state, and a second touch will start the door closing. Regardless of the shortcomings of any verbal description, the real lesson of the answer is this: In a state transition diagram you can easily look for a find a path from one state to another

The book now pursues a design that doesn’t use the State design pattern It proposes that the software have a Door class Implicit in this design is a carousel machine which can call methods on a door object

The Door class will have an int instance variable holding state The class will also have methods that affect the state Finally, the Door class will extend the Observable class so that it is suitable for use in a graphical application with listeners A simple UML diagram is shown on the following overhead

The book then gives some code showing how this might be implemented I am copying the code as given, even though I don’t care for switch/case statements (I find simple, nested if statements clearer and less error prone) On the next overhead the beginning part of the Doo class is given, showing how the states are defined

public class Door extends Observable { public final int CLOSED = -1; public final int OPENING = -2; public final int OPEN = -3; public final int CLOSING = -4; public final int STAYOPEN = -5; public int state = CLOSED; … }

The status() method in the Door class is sort of a combination get/toString method It doesn’t take an input parameter It returns the current state of a door However, it doesn’t return a numerical value It returns a String which describes the current state The code is given on the next overhead Notice that because of the dual nature of the method, it requires “if” logic

public String status() { switch(state) case OPENING: return “Opening”; case OPEN: return “Open”; case CLOSING: return “Closing”; case STAYOPEN: return “StayOpen”; default: return “Closed”; }

It is the touch() method that contains the fundamental logic for the Door class The method doesn’t take an input parameter What touching the button does depends entirely on the current state of the door Equally importantly, what touching the button does is change the state of the door The code is given on the next overhead This is the classic case of a state method that requires “if” logic

public void touch() { switch(state) case OPENING: case STAYOPEN: setState(CLOSING); break; case CLOSING: case CLOSED: setState(OPENING); case OPEN: setState(STAYOPEN); default: throw new Error(“Can’t happen.”); } /* Whoops! The book forgot to declare at the top that the method throws an exception. */

There is a setState() method instead of a simple assignment state = int value so that the observers can be notified The code for the setState() method is given on the next overhead

private void setState(int state) { this.state = state; setChanged(); notifyObservers(); }

Challenge 22.2 Write the code for the complete() and timeout() methods of the Door class

Solution 22.2 Your code should look something like: [See following overhead]

public void complete() { if(state == OPENING) setState(OPEN); else if(state == CLOSING) setState(CLOSED); } public void timeout() setState(CLOSING);

Refactoring to State Strictly speaking, there is nothing wrong with this design The instance variable, state, is accessible to all of the methods of the Door class However, within the Door class itself, the state instance variable serves as a “global” variable In particular, somewhat analogous if/then/else code occurs in two methods of the class, status() and touch()

Applying the State design pattern to “solve the problem”, the different states become classes The UML diagram for this is shown on the overhead following the next one When you see it, the solution will look more complex than the original problem to be solved

This doesn’t mean the pattern is bad It’s just a function of having to come up with an example simple enough to be easily explained Applying the pattern to such an example is overkill The UML diagram is on the next overhead

Observe now that each of the state classes has a touch() method This touch() method will not contain nested ifs It will only have to handle the single case where the door is in that state which is named by the class The code for the DoorClosed class which implements the DoorState abstract class is given on the next overhead

public class DoorClosed extends DoorState { public DoorClosed(Door2 door) super(door); } public void touch() door.setState(door.OPENING);

Note the logic of this design There is a single instance of each kind of state for a given door object Each of the individual state objects is constructed with an input parameter to the door it belongs to saved as a reference

I am not 100% happy with the book’s UML diagram because it doesn’t show the reference to a door as an instance variable in the DoorState abstract class However, it would have to be there because the code for the subclass constructor depends on it and the code for the touch() method relies on its existence

With this design, the code for the Door2 class also has to be changed The states of doors are no longer simple int values They are the individual instances of the state classes which are associated with a door The beginning of the code for Door2, where the states are defined, is given on the next overhead

public class Door2 extends Observable { public final DoorState CLOSED = new DoorClosed(this); public final DoorState CLOSING = new DoorClosing(this); public final DoorState OPEN = new DoorOpen(this); public final DoorState OPENING = new DoorOpening(this); public final DoorState STAYOPEN = new DoorStayOpen(this); private DoorState state = CLOSED; … }

The DoorState class is abstract The abstract method that it contains is touch() Each concrete state class has to implement the touch() method The DoorState class also has concrete methods that the subclasses inherit

The DoorState class also has a characteristic like an adapter class Other methods are included in it with bogus implementations The book refers to this is “stubbing them out” (I would say stubbing them in…) That means the concrete subclasses have the choice of implementing them if necessary, or not The code for the DoorState class is given on the next overhead

public abstract class DoorState { protected Door2 door; public abstract void touch(); public void complete() } public void timeout() public String status() String s = getClass().getName(); return s.substring(s.lasIndexOf(‘.’) + 1); public DoorState(Door2 door) this.door = door;

The book notes that the status() method is “much simpler” than the previous version That’s a matter of opinion The new version relies on the fact that the names of the state classes describe the state in question Reflection makes is possible to retrieve those names It seems that the rest of the method is based on retrieving only the last part of a multi-part dot-qualified name

The book now comes to the Door2 class In an overall design, the role of a door object hasn’t changed Touching the button means calling a method, touch(), on the door object However, the code for that method now makes a call to touch() on the state object that belongs to it

The logic of the other methods in the Door2 class is similar The code for these methods in the Door2 class is given on the next overhead

public class Door2 extends Observable { // variables and constructor public void touch() state.touch(); } public void complete() state.complete(); public void timeout() state.timeout(); public String status() return state.status(); protected void setState(DoorState state) this.state = state; setChanged(); notifyObservers();

The book points out that this design allows polymorphism to take on the role of nested if/else statements (This also came up in an earlier pattern) The point is this: which version of touch() is used in the following line of code depends on what the current state of the door is: state.touch();

Notice also the setState() method at the end of the Door2 class definition This method is called within the methods of the DoorState classes It is called on the reference to the door object that is passed to a state object when it’s constructed This is illustrated in the code on the following overhead

public class DoorOpen extends DoorState { public DoorOpen(Door2 door) super(door); } public void touch() door.setState(door.STAYOPEN); public void timeout() door.setState(door.CLOSING);

Challenge 22.3 Write the code for DoorClosing.java.

Your code should look something like: [See the next overhead]

public class DoorClosing extends DoorState { public DoorClosing(Door2 door) super(door); } public void touch() door.setState(door.OPENING); public void complete() door.setState(door.CLOSED);

Making States Constant The book mentions again that the basic model of the design just described is this: For each instance of a door, there will be a complete set of state objects Each of those state objects has a reference to the door they are connected with The methods of the state objects then update the door’s state

The book then considers alternatives It is worth noting that the book does not take the consideration of alternatives to full-scale code implementations The discussions remain in the realm of ideas and a UML diagram

The book refers to the first alternative as making the states static In other words, it should be possible to have just one instance of each kind of state (a singleton?) Then given a state, calling the touch() method on it, for example, would cause the resulting state to be returned

In such a design, the Door class could have a method like this: public void touch() { state = state.touch(); } By calling the state method on the current state, a new state is returned

The corresponding touch() method in the state class would look like this: public DoorState touch() { return DoorState.STAYOPEN; }

In this design the states don’t save references to doors Only one instance of each state would be needed, regardless of the number of doors in an application It becomes the door’s responsibility to manage all updates that might result from changes in state

The next alternative is somewhere between the previous two The states don’t hold references to doors as instance variables They also are not completely independent of the door(s) they work with The state methods take a reference to the door of interest and work with that without keeping it as an instance variable value

Challenge 22.4 Complete the class diagram in Figure 22.4 to show a design that lets DoorState objects be constants and that passes around a Door object during state transitions. [Diagram shown on next overhead]

Solution 22.4 Figure B.23 shows a reasonable diagram. [Shown on next overhead]

To review, there are three choices when using the State design pattern: Have the states hold references to the object of interest given to them at construction time Have the states receive references to the object of interest when transition methods are called, but not hold them Have the states be static—merely handing back the state that is transitioned to by a method call, leaving all details of updating to the object of interest

It is free choice which model to use The book suggests that the decision may be based on the “context” of an application, or esthetics The book also gives a reminder that for threaded code, it would be critical for the state transition methods to be synchronized

Summary In general, the state of an object depends on the values of all of its instance variables However, in some applications, the value of one instance variable is dominant In this case, implementation may be simplified by creating a hierarchy of state classes The logic for transitions between states can be implemented in the state classes

In practice, it may become apparent that this pattern is applicable because significant blocks of if/else code are repeated in an application The if/else code is replaced by polymorphism where the value of a state object determines which method implementation is called on it

The book states that the pattern simplifies your code by distributing an operation across a collection of classes that represent an object’s various states The simplification might be more apparent if it is described in this way: State specific behavior only has to be implemented once, in the class representing that particular state The logic doesn’t have to be duplicated at more than one point in the application

The End