1 / 4

Matters of State

Matters of State (Java Report 5(6), June 2000).

Kevlin
Download Presentation

Matters of State

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Patterns in Java Kevlin He n n ey/kevlin@ curbralan.com Matters of state I have state, simple behavior, and transparent identity. Objects with significant identity typically re p re s e n t the load-bearing stru c t u res in a system, such as per- sistent data and graphical objects. They are also typi- cally objects with significant life cycles that re s p o n d to method calls quite diff e re n t l y, depending on what general state or mode their content re p resents. Objects that do not have significant identity tend to have less D E N T I T Y, STATE, AND behavior can typify an object. For example, value objects1 , 2—used for re p resenting simple pieces of information in a system, such as dates, strings, and quantities— sion that this is the only solution style possible for object life cycles; i.e., it is “a state pattern” not “t h e state pattern ” . * St ate An ato my. Although often presented as a sin- gle pattern, many have re c o g n i z e d5that there is a g reat deal more to implementing such a collabora- tion than can be elegantly captured in a single pat- t e rn. A pattern that covers a great deal of complexity or describes a number of implementation altern a- tives can often be opened up to reveal a more in- volved decision stru c t u re better re p resented thro u g h a pattern language. P a t t e rn languages combine a number of pattern s into a coherent whole, connecting them together t h rough a set of decisions, with one pattern eff e c t i v e- ly completing another.1, 2A pattern that plays a ro l e in a language does not belong exclusively to that lan- guage: It may be used to resolve similar problems in other pattern languages and contexts. i n t e resting life cycles. A stateless service object has no state and there f o re no life cycle; a value-based object tends to have either a trivial life cycle model or no life cycle model (e.g., I m mu t a b le Va l u e1, 2) . The life cycle of an object can be modeled in UML using a Harel s t a t e c h a rt .3S t a t e c h a rt di- agrams can tell developers The Pat te rn s. A pattern language describes how to build a system or an aspect of a system. This art i c l e looks at the O b je c ts for States p a t t e rn from a Java perspective. It shows a fragment of a pro t o l a n g u a g e (i.e., a work in pro g ress), focusing specifically on how the mode of the object is re p resented—as opposed to, s a y, how its transitions are managed. Figure 1 depicts the basic flo w, showing that once O b je c ts for States has been selected we have an either/or decision as to how to best re p resent the objects housing the actual delegated behavior. Stateful Obje c t and S t a t e less Obje c t have applica- bility outside this context, e.g., in considering the statefulness (or otherwise) of a transactional middle t i e r. They are here woven into the language thro u g h common links and a shared example. The pattern s a re described using a simple i n t e n t - p ro b l e m - s o l u t i o n - e x a m p l e f o rm, with a simplified example. a lot about the behavior of objects over time, and un- like many conventional class models, the move to code is far from trivial. Java offers features that sim- plify the implementation of object life cycle models. Ge n e ral Pat te rn O b je c ts for States is a general-purpose (as opposed to d o m a i n - s p e c i fic) pattern4that can be used to move f rom a documented state model to a practical im- plementation. It demonstrates a classic use of del- egation into a class hierarc h y. Note that the name O b je c ts for States is used here in pre f e rence to its common name of S t a t e, as this is both a more accu- rate description of its stru c t u re —S t a t e d e s c r i b e s b road intent, whereas O b je c ts for States d e s c r i b e s s t ru c t u re—and does not give the reader the impre s- *Unfortunately, I have seen the havoc this misconception can wreak on a system: Every single statechart was converted un- questioningly into an implementation of “t h e State” pattern. Pat- t e rns solve particular problems well; if applied inappro p r i a t e l y they reduce rather than increase communication and under- standing. A clear name counts for a lot. Kevlin He n n ey is an indepe n d e nt co n s u l t a nt and trainer based in the UK. 1 2 6 Java ™Report | J UNE 2000 ht t p : / / w w w. j ava re po rt. co m

  2. Patterns in Java/Kevlin He n n ey Objects for S t a t e s Allow an object to alter its behavior s i g n i f i c a n t l y b y delegating state- based behavior to a separate object. ther a Stateful Obje c t or a S t a t e less Obje c t. The transition to a diff e rent state means replacement of the behavior object by another of a diff e rent class. Poly- morphism replaces the explicit conditional lookup. Tr a n- sitions between states can be managed either by the behavioral mode objects themselves or by a centralized mechanism such as a table lookup. To move with confidence from an existing design that uses a type switch of some kind to one that takes advan- tage of O b je c ts for States, the Replace Type Code Wi t h State/Strategy re f a c t o r i n g6can be applied. The separa- tion and increased messaging through forw a rding meth- ods means that this design is not suitable for distribution; i.e., mode objects should live in the same process as their context objects. Fi g u re 1.The Objects for Statesp a t te rn and the co n s t ru ction of its re p re s e n t a t i o n . Pro b l e m . H o w can an object sig- n i ficantly change its behavior, depending on its intern a l state, without h a rd w i red multipart conditional code? The temptation is to use a flag internal to the object and in each method to switch to the correct behavior accord i n g l y. This c reates long and complex m e t h o d s . I t b e c o m e s d i ffic u l t to locate the behavior for a particular mode, and harder still to modify the behavioral model corre c t l y. Ex a m p l e. Consider the life cycle for a simple clock shown in Figure 2. Leaving aside the issue of transitions and time updates, a tempting procedural implementation can be seen in Listing 1. Such a contro l - flow-based approach is e rror prone and scatters the state-based behavior acro s s many methods. Using O b je c ts for States t u rns the basic stru c t u re inside out through delegation. All behavior relevant to a part i c u- lar mode is encapsulated in an object and the entire selec- tion is expressed through p o l y m o r p h i s m (see Figure 3). So l u t i o n . Separate the behavior from the main class, which holds the context, into a separate class hierarc h y, w h e re each class re p resents the behavior in a part i c u l a r state. The context object—the instance of the main class with which the client communicates—aggregates an ob- ject that is used to re p resent the behavior in one of its modes. Method calls on the context are forw a rded to the mode object; responsibility for implementing behavior in a particular state is there f o re delegated and localized. This behavioral mode object can be implemented as ei- Stateful Object Allow a behavioral object that is separate from the data object on which it operates access to that data by pro v i d i n g a field with a re f e rence back to it. LISTING 1. Implementation of the clock’s life cycle using a fla g and explicit switching. public class Clo c k { public sy nc h ronized void change Mo de() ... public sy nc h ronized void inc re me nt ( ) { s w i tc h ( mo de ) { case displaying T i me : t h row new Exc e p t i o n ( “ C h a nge mo de to change time ” ) ; b re a k ; case setting Ho u rs : + + ho u rs ; b re a k ; case setting M i nu t e s : + + m i nu t e s ; b re a k ; } } public sy nc h ronized void cancel() ... . . . p r i vate static final int displaying T i me = 0; p r i vate static final int setting Ho u rs p r i vate static final int setting M i nutes = 2; p r i vate int ho u rs, minu t e s ; p r i vate int mo de = setting Ho u rs ; } Pro b l e m . Given a separation of behavior from the state that the behavior operates on, so that the state is one ob- ject and the behavior in another, what is the simplest and most direct design for the behavioral class? The separa- tion means that whereas the behavior and data were pre- viously in the same object—and there f o re the behavior could act directly on it—the behavior can no longer di- rectly manipulate the data. So l u t i o n . Implement the behavioral class so that an in- stance has access to the contents of the object on which it operates. Because of the knowledge of its context, it has state of its own. At any one time, a behavior object is ded- icated to a single context object. = 1; Figure 2.Statechart representing the life cycle of a simple clock object. 1 2 8 Java ™Report | J UNE 2000 ht t p : / / w w w. j ava re po rt. co m

  3. Kevlin He n n ey/Patterns in Java The simplest and most direct approach is to use inner classes so that the context object’s state is implicitly visible to the behavior classes. Altern a t i v e l y, an explicit back re f- e rence from the behavior object to the context object can be d e fined, with either raw access to the data—through pack- age or class-level visibility—or via additional query and m o d i fier methods. This retains the separation between behavior and the data of interest, but means that a behavioral object is now tied to a single data object at a time. This can lead to increased object creation and collection costs, espe- cially if the behavior object is changed for another and the previous object is discarded rather than cached. If this is significant, implementing the behavioral mode object as a S t a t e less Obje c t re p resents an altern a t i v e . Fi g u re 3.Re p resentation of the clock state model using O b j e c t s for States. havior in another, what design for the behavioral class min- imizes object creation and collection costs? A Stateful Ob- je c t is simple to implement and manage, but can lead to i n c reased object numbers and reduced perf o rmance if the objects are created and discarded fre q u e n t l y. Ex a m p l e. Implementing the clock class with a S t a t e f u l O b je c t for the mode leads to Listing 2. An improvement in the creation/collection perf o rmance of the program would be to preinstantiate all the re q u i red mode objects for an object and cache them in an arr a y. So l u t i o n . Implement the behavioral class so that it has no data in it whatsoever. The context object is now passed in as an argument to each of the delegated meth- ods of the behavioral objects. The simplest approach that Stateless Object Allow a behavioral object that is separate from the data ob - ject on which it operates access to that data by passing a re f e rence back to it as an argument with each method call. LISTING 3. Pro b l e m . Given a separation of behavior from the state it operates on, so that the state is in one object and the be- Implementation of the clock’s life cycle using a Stateless Object for the mode. public class Clo c k { public sy nc h ronized void change Mo de ( ) { mo de. c h a nge Mo de(this); } public sy nc h ronized void inc re me nt ( ) { mo de. i nc re me nt(this); } public sy nc h ronized void canc e l ( ) { mo de. c a ncel(this); } p r i vate int e r face Mo de { void change Mo de ( C lock cont ex t ) ; void inc re me nt ( C lock cont ex t ) ; void canc e l ( C lock cont ex t ) ; } p r i vate static class Displaying T i me imple me nts Mo de ... p r i vate static abstract class Setting T i me imple me nts Mo de . . . p r i vate static class Setting Ho u rs ex t e nds Setting T i me ... p r i vate static class Setting M i nutes ex t e nds Setting T i me { public void change Mo de ( C lock cont ex t ) { cont ex t . mo de = displaying T i me; } public void inc re me nt ( C lock cont ex t ) { ++cont ex t . m i nutes; } } p r i vate int ho u rs, minu t e s ; p r i vate Mo de mo de = setting Ho u rs ; p r i vate static final Mo de d i s p l a y i ng T i me = new Displaying T i me ( ) , s e t t i ng Ho u rs = new Setting Ho u rs ( ) , s e t t i ng M i nutes = new Setting M i nu t e s ( ) ; } LISTING 2. Implementation of the clock’s life cycle using a Stateful Object for the mode. public class Clo c k { public sy nc h ronized void change Mo de() { mo de. c h a nge Mo de(); } public sy nc h ronized void inc re me nt() { mo de. i nc re me nt(); } public sy nc h ronized void cancel() { mo de. c a ncel(); } p r i vate int e r face Mo de { void change Mo de ( ) ; void inc re me nt ( ) ; void canc e l ( ) ; } p r i vate class Displaying T i me imple me nts Mo de ... p r i vate abstract class Setting T i me imple me nts Mo de { public void cancel() { mo de = new Displaying T i me(); } } p r i vate class Setting Ho u rs ex t e nds Setting T i me ... p r i vate class Setting M i nutes ex t e nds Setting T i me { public void change Mo de() { mo de = new Displaying T i me(); } public void inc re me nt() { ++minutes; } } p r i vate int ho u rs, minu t e s ; p r i vate Mo de mo de = new Setting Ho u rs ( ) ; } 1 2 9 J UNE 2000 |Java ™Report ht t p : / / w w w. j ava re po rt. co m

  4. Patterns in Java/Kevlin He n n ey allows behavioral objects to see the encapsulated content of the context objects is to declare them as s t a t i c t o p - l e v- el classes in the context class. Altern a t i v e l y, package-lev- el visibility or additional query and modifier methods must be pro v i d e d . Such behavioral objects are stateless, so they may be t reated as F l y we i g ht4objects that can be shared transpar- ently among all instances of the context class. The ab- sence of state also means that they are implicitly t h readsafe, and there f o re need no synchronization. Giv- en that only a single instance of a behavioral class is ever re q u i red, S i ng le to n4can be used to good effect when the definition of the behavioral class is outside the context class. Otherwise, S i ng le to n is overkill where p r i vate static data would suffic e . The entire selection of behavior is now expressed pure- ly through polymorphism and callbacks on a separate ob- ject, and the state now resides only in the context object. If the behavioral model is quite stable, the V i s i to r p a t t e rn may be used to put all the behavioral code back into the context object, with the behavioral mode object doing se- lection only and calling the relevant method on the con- text object to do all of the work. However, although this is sometimes an option, it can make the implementation un- wieldy for large state models: The context class suff e r s method explosion. Ex a m p l e.Implementing the clock class with a S t a t e less Ob- je c t for the mode leads to Listing 3. Co n c l u s i o n A common pattern for implementing object life cycle mod- els can be expressed in terms of other more granular pat- t e rns. They may be linked together in a language; i.e., the main pattern can be said to c o n t a i n or be completed by t h e other patterns. In this article, the focus was on the re p re- sentation of the O b je c ts for States p a t t e rn in Java, as opposed to a more detailed view of the whole pattern .5 The Stateful Obje c t and S t a t e less Obje c t p a t t e rns assist in the realization of O b je c ts For States, but are not tied exclu- sively to it: The issues raised and resolutions given can be found in many object systems whether local or distributed, (e.g., EJB). I Re fe re n ce s 1 . H e n n e y, K., “Patterns of value,” Java Report , Vol. 5, No. 2, Feb. 2000, pp. 64–68. 2 .H e n n e y, K., “Value added,” Java Report , Vol. 5, No. 4, Apr. 2000, pp. 74–82. 3 . Rumbaugh, J., I. Jacobson, and G. Booch, The Unified Mod - eling Language Reference Manual, Addison–We s l e y, 1999. 4 . Gamma, E. et al., Design Patterns: Elements of Reusable Ob - ject-Oriented Software, Addison–We s l e y, 1995. 5 . Dyson, P. and Anderson, B. “State Patterns,” P a t t e rn Lan - guages of Program Design 3, R. Martin, D. Riehle, and F. Buschmann, Eds., Addison–We s l e y, 1998. 6 .F o w l e r, M., Refactoring: Improving the Design of Existing C o d e, Addison–We s l e y, 1999. 1 3 0 Java ™Report | J UNE 2000 ht t p : / / w w w. j ava re po rt. co m

More Related