- •Table of Content
- •Why We Wrote This Book
- •What This Book Is About
- •Who Should Read This Book
- •Conventions Used
- •Figure 1. Example class diagram
- •How This Book Is Organized
- •How to Use This Book
- •Companion Web Site
- •Acknowledgments
- •Why Patterns?
- •History of the Patterns Movement
- •Basic Concepts in Patterns
- •Software Abstraction and Reuse
- •Summary
- •Chapter 1. Creational Patterns
- •Introduction to Creational Patterns
- •Abstract Factory
- •Pattern Properties
- •Purpose
- •Introduction
- •Applicability
- •Description
- •Implementation
- •Figure 1.1. Abstract Factory class diagram
- •Benefits and Drawbacks
- •Pattern Variants
- •Related Patterns
- •Example
- •Example 1.1 AddressFactory.java
- •Example 1.2 Address.java
- •Example 1.3 PhoneNumber.java
- •Example 1.4 USAddressFactory.java
- •Example 1.5 USAddress.java
- •Example 1.6 USPhoneNumber.java
- •Example 1.7 FrenchAddressFactory.java
- •Example 1.8 FrenchAddress.java
- •Example 1.9 FrenchPhoneNumber.java
- •Builder
- •Pattern Properties
- •Purpose
- •Introduction
- •Applicability
- •Description
- •Implementation
- •Figure 1.2. Builder class diagram
- •Benefits and Drawbacks
- •Pattern Variants
- •Related Patterns
- •Example
- •Example 1.10 AppointmentBuilder.java
- •Example 1.11 Appointment.java
- •Example 1.12 Scheduler.java
- •Example 1.13 MeetingBuilder.java
- •Factory Method
- •Pattern Properties
- •Purpose
- •Introduction
- •Applicability
- •Description
- •Implementation
- •Figure 1.3. Factory Method class diagram
- •Benefits and Drawbacks
- •Pattern Variants
- •Related Patterns
- •Example
- •Example 1.14 Editable.java
- •Example 1.15 ItemEditor.java
- •Example 1.16 Contact.java
- •Prototype
- •Pattern Properties
- •Purpose
- •Introduction
- •Applicability
- •Description
- •Implementation
- •Figure 1.4. Prototype class diagram
- •Benefits and Drawbacks
- •Figure 1.5. Example of Prototype use
- •Pattern Variants
- •Example 1.17 Copy constructor
- •Related Patterns
- •Example
- •Example 1.18 Copyable.java
- •Example 1.19 Address.java
- •Singleton
- •Pattern Properties
- •Purpose
- •Introduction
- •Applicability
- •Description
- •Implementation
- •Figure 1.6. Singleton class diagram
- •Benefits and Drawbacks
- •Pattern Variants
- •Related Patterns
- •Example
- •Example 1.20 HistoryList.java
- •Introduction to Behavioral Patterns
- •Chain of Responsibility
- •Pattern Properties
- •Purpose
- •Introduction
- •Applicability
- •Description
- •Figure 2.1. Chain of Responsibility sequence diagram
- •Implementation
- •Figure 2.2. Chain of Responsibility class diagram
- •Benefits and Drawbacks
- •Pattern Variants
- •Related Patterns
- •Example
- •Example 2.1 ProjectItem.java
- •Example 2.2 Project.java
- •Example 2.3 Task.java
- •Command
- •Pattern Properties
- •Purpose
- •Introduction
- •Applicability
- •Description
- •Figure 2.3. Sequence diagram for invocation of Command
- •Implementation
- •Figure 2.4. Command class diagram
- •Benefits and Drawbacks
- •Pattern Variants
- •Figure 2.5. Class diagram showing both the undo and MacroCommand variant
- •Related Patterns
- •Example
- •Example 2.4 Command.java
- •Example 2.5 UndoableCommand.java
- •Example 2.6 Appointment.java
- •Example 2.7 ChangeLocationCommand.java
- •Interpreter
- •Pattern Properties
- •Purpose
- •Introduction
- •Applicability
- •Description
- •Implementation
- •Figure 2.6. Interpreter class diagram
- •Benefits and Drawbacks
- •Pattern Variants
- •Related Patterns
- •Example
- •Example 2.8 Expression.java
- •Example 2.9 ConstantExpression.java
- •Example 2.10 VariableExpression.java
- •Example 2.11 CompoundExpression.java
- •Example 2.12 AndExpression.java
- •Example 2.13 OrExpression.java
- •Example 2.14 ComparisonExpression.java
- •Example 2.15 EqualsExpression.java
- •Example 2.16 ContainsExpression.java
- •Example 2.17 Context.java
- •Example 2.18 ContactList.java
- •Iterator
- •Pattern Properties
- •Purpose
- •Introduction
- •Applicability
- •Description
- •Implementation
- •Figure 2.7. Iterator class diagram
- •Benefits and Drawbacks
- •Pattern Variants
- •Related Patterns
- •Example
- •Example 2.19 Iterating.java
- •Example 2.20 ToDoList.java
- •Example 2.21 ToDoListCollection.java
- •Example 2.22 ToDoListCollectionImpl.java
- •Example 2.23 ToDoListImpl.java
- •Example 2.24 ListPrinter.java
- •Mediator
- •Pattern Properties
- •Purpose
- •Introduction
- •Applicability
- •Description
- •Implementation
- •Figure 2.8. Mediator class diagram
- •Benefits and Drawbacks
- •Pattern Variants
- •Related Patterns
- •Example
- •Example 2.25 MediatorGui.java
- •Example 2.26 ContactDisplayPanel.java
- •Example 2.27 ContactSelectorPanel.java
- •Example 2.28 ContactEditorPanel.java
- •Example 2.29 ContactMediator.java
- •Example 2.30 ContactMediatorImpl.java
- •Memento
- •Pattern Properties
- •Purpose
- •Introduction
- •Applicability
- •Description
- •Implementation
- •Figure 2.9. Memento class diagram
- •Benefits and Drawbacks
- •Pattern Variants
- •Related Patterns
- •Example
- •Example 2.31 AddressBook.java
- •Pattern Properties
- •Purpose
- •Introduction
- •Applicability
- •Description
- •Implementation
- •Figure 2.10. Observable class diagram
- •Benefits and Drawbacks
- •Pattern Variants
- •Related Patterns
- •Example
- •Example 2.32 TaskChangeObservable.java
- •Example 2.33 TaskChangeObserver.java
- •Example 2.34 ObserverGui.java
- •Example 2.35 TaskEditorPanel.java
- •Example 2.36 TaskHistoryPanel.java
- •Example 2.37 TaskSelectorPanel.java
- •State
- •Pattern Properties
- •Purpose
- •Introduction
- •Applicability
- •Description
- •Figure 2.11. State transition diagram for a door
- •Implementation
- •Figure 2.12. State class diagram
- •Benefits and Drawbacks
- •Pattern Variants
- •Related Patterns
- •Example
- •Figure 2.13. State transition diagram for a file
- •Example 2.38 State.java
- •Example 2.39 CalendarEditor.java
- •Example 2.40 StateGui.java
- •Strategy
- •Pattern Properties
- •Purpose
- •Introduction
- •Applicability
- •Description
- •Benefits and Drawbacks
- •Implementation
- •Figure 2.14. Strategy class diagram
- •Pattern Variants
- •Related Patterns
- •Example
- •Example 2.41 ContactList.java
- •Example 2.42 SummarizingStrategy.java
- •Example 2.43 NameSummarizer.java
- •Example 2.44 OrganizationSummarizer.java
- •Visitor
- •Pattern Properties
- •Purpose
- •Introduction
- •Applicability
- •Description
- •Implementation
- •Figure 2.15. Visitor class diagram
- •Benefits and Drawbacks
- •Pattern Variants
- •Related Patterns
- •Example
- •Example 2.45 ProjectItem.java
- •Example 2.46 Deliverable.java
- •Example 2.47 DependentTask.java
- •Example 2.48 Project.java
- •Example 2.49 Task.java
- •Example 2.50 ProjectVisitor.java
- •Example 2.51 ProjectCostVisitor.java
- •Template Method
- •Pattern Properties
- •Purpose
- •Introduction
- •Applicability
- •Description
- •Implementation
- •Figure 2.16. Template Method class diagram
- •Benefits and Drawbacks
- •Pattern Variants
- •Related Patterns
- •Example
- •Example 2.52 ProjectItem.java
- •Example 2.53 Deliverable.java
- •Example 2.54 Task.java
- •Introduction to Structural Patterns
- •Adapter
- •Pattern Properties
- •Purpose
- •Introduction
- •Applicability
- •Description
- •Implementation
- •Figure 3.1. Adapter class diagram interface
- •Figure 3.2. Sequence diagram for action mapping
- •Benefits and Drawbacks
- •Pattern Variants
- •Related Patterns
- •Example
- •Example 3.1 Chovnatlh.java
- •Example 3.3 Contact.java
- •Example 3.4 ContactAdapter.java
- •Bridge
- •Pattern Properties
- •Purpose
- •Introduction
- •Applicability
- •Description
- •Comparison of Inheritance Pattern and Bridge Pattern
- •Implementation
- •Figure 3.3. Bridge class diagram
- •Benefits and Drawbacks
- •Pattern Variants
- •Related Patterns
- •Example
- •Example 3.5 ListImpl.java
- •Example 3.6 OrderedListImpl.java
- •Example 3.7 BaseList.java
- •Example 3.8 NumberedList.java
- •Composite
- •Pattern Properties
- •Purpose
- •Introduction
- •Applicability
- •Description
- •Implementation
- •Figure 3.4. Composite class diagram
- •Benefits and Drawbacks
- •Pattern Variants
- •Related Patterns
- •Example
- •Figure 3.5. Composite class diagram for the code example
- •Example 3.9 ProjectItem.java
- •Example 3.10 Deliverable.java
- •Example 3.11 Project.java
- •Example 3.12 Project.java
- •Example 3.13 Task.java
- •Decorator
- •Pattern Properties
- •Purpose
- •Introduction
- •Applicability
- •Description
- •Implementation
- •Figure 3.6. Decorator class diagram
- •Benefits and Drawbacks
- •Pattern Variants
- •Related Patterns
- •Example
- •Example 3.14 ProjectItem.java
- •Example 3.15 Deliverable.java
- •Example 3.16 Task.java
- •Example 3.17 ProjectDecorator.java
- •Example 3.18 DependentProjectItem.java
- •Example 3.19 SupportedProjectItem.java
- •Facade
- •Pattern Properties
- •Purpose
- •Introduction
- •Applicability
- •Description
- •Implementation
- •Figure 3.7. Facade object diagram
- •Pattern Variants
- •Related Patterns
- •Example
- •Example 3.20 InternationalizationWizard.java
- •Example 3.21 Currency.java
- •Example 3.22 InternationalizedText.java
- •Example 3.23 PhoneNumber.java
- •Example 3.24 Nation.java
- •Flyweight
- •Pattern Properties
- •Purpose
- •Introduction
- •Applicability
- •Description
- •Implementation
- •Figure 3.8. Flyweight class diagram
- •Benefits and Drawbacks
- •Pattern Variants
- •Related Patterns
- •Example
- •Example 3.25 State.java
- •Example 3.26 CleanState.java
- •Example 3.27 DirtyState.java
- •Example 3.28 StateFactory.java
- •Half-Object Plus Protocol (HOPP)
- •Pattern Properties
- •Purpose
- •Introduction
- •Applicability
- •Description
- •Implementation
- •Figure 3.9. HOPP class diagram
- •Benefits and Drawbacks
- •Pattern Variants
- •Related Patterns
- •Example
- •Example 3.29 Calendar.java
- •Example 3.30 CalendarImpl.java
- •Example 3.31 CalendarHOPP.java
- •Proxy
- •Pattern Properties
- •Purpose
- •Introduction
- •Applicability
- •Description
- •Implementation
- •Figure 3.10. Proxy class diagram
- •Benefits and Drawbacks
- •Pattern Variants
- •Related Patterns
- •Example
- •Example 3.32 AddressBook.java
- •Example 3.33 AddressBookProxy.java
- •Example 3.34 AddressBookImpl.java
- •Introduction to System Patterns
- •Model-View-Controller (MVC)
- •Pattern Properties
- •Purpose
- •Introduction
- •Applicability
- •Description
- •Implementation
- •Figure 4.1. MVC component diagram
- •Benefits and Drawbacks
- •Pattern Variants
- •Related Patterns
- •Example
- •Example 4.1 ContactModel.java
- •Example 4.2 ContactView.java
- •Example 4.3 ContactDisplayView.java
- •Example 4.4 ContactEditView.java
- •Example 4.5 ContactEditController.java
- •Session
- •Pattern Properties
- •Purpose
- •Introduction
- •Applicability
- •Description
- •Stateful and Stateless Communication
- •Applications Often Require Stateful Communication
- •Session Pattern and Stateful Communication
- •Real-World Stateful Communication
- •Implementation
- •Benefits and Drawbacks
- •Pattern Variants
- •Related Patterns
- •Example
- •Figure 4.2. Session component for a client-matching session
- •Figure 4.3. Session component for server-maintained sessions
- •Figure 4.4. Session tracker
- •Example 4.6 SessionClient.java
- •Example 4.7 SessionServer.java
- •Example 4.8 SessionServerImpl.java
- •Example 4.9 SessionServerDelegate.java
- •Worker Thread
- •Pattern Properties
- •Purpose
- •Introduction
- •Applicability
- •Description
- •Implementation
- •Figure 4.5. Worker Thread class diagram
- •Benefits and Drawbacks
- •Pattern Variants
- •Related Patterns
- •Example
- •Example 4.10 Queue.java
- •Example 4.11 RunnableTask.java
- •Example 4.12 ConcreteQueue.java
- •Example 4.13 AddressRetriever.java
- •Example 4.14 ContractRetriever.java
- •Callback
- •Pattern Properties
- •Purpose
- •Introduction
- •Applicability
- •Description
- •Implementation
- •Figure 4.6. Callback component diagram
- •Figure 4.7. Callback sequence diagram
- •Benefits and Drawbacks
- •Pattern Variants
- •Related Patterns
- •Example
- •Example 4.15 CallbackServer.java
- •Example 4.16 CallbackServerImpl.java
- •Example 4.17 CallbackServerDelegate.java
- •Example 4.18 CallbackClient.java
- •Example 4.19 CallbackClientImpl.java
- •Successive Update
- •Pattern Properties
- •Purpose
- •Introduction
- •Applicability
- •Description
- •Client Pull
- •Figure 4.8. Successive Update sequence diagram (client pull)
- •Server Push
- •Figure 4.9. Successive Update sequence diagram (server push)
- •Implementation
- •Benefits and Drawbacks
- •Pattern Variants
- •Related Patterns
- •Example
- •Example 4.20 PullClient.java
- •Example 4.21 ClientPullRequester.java
- •Example 4.22 ClientPullServer.java
- •Example 4.23 ClientPullServerImpl.java
- •Example 4.24 UpdateServerDelegate.java
- •Pattern Properties
- •Purpose
- •Introduction
- •Applicability
- •Description
- •Implementation
- •Figure 4.10. Router class diagram
- •Benefits and Drawbacks
- •Pattern Variants
- •Related Patterns
- •Example
- •Example 4.25 Message.java
- •Example 4.26 InputChannel.java
- •Example 4.27 OutputChannel.java
- •Example 4.28 Router.java
- •Transaction
- •Pattern Properties
- •Purpose
- •Introduction
- •Applicability
- •Description
- •Implementation
- •Figure 4.11. Transaction class diagram
- •Benefits and Drawbacks
- •Pattern Variants
- •Related Patterns
- •Example
- •Example 4.29 AppointmentTransactionParticipant.java
- •Example 4.30 AppointmentBook.java
- •Chapter 5. Introduction to Java Programming Language Patterns
- •Event Handling
- •Packages
- •Overview
- •Pattern Use
- •JavaBeans
- •Packages
- •Overview
- •AWT and Swing – The Graphical User Interface APIs
- •Packages
- •Common Features
- •The AWT Architectural Model
- •Benefits
- •Drawbacks
- •The Swing Architectural Model
- •General Pattern Use
- •Pattern Use in AWT
- •Pattern Use in Swing
- •Collections Framework
- •Packages
- •Description
- •Example 6.1 Collections class and threadsafe versions of collections
- •Pattern Use
- •Input-Output (I/O)
- •Packages
- •Description
- •Example 6.2 Streams in Java
- •Pattern Use
- •Reflection
- •Packages
- •Overview
- •Example 6.3 Using instances of unknown origin
- •Pattern Use
- •Java Naming and Directory Interface (JNDI)
- •Packages
- •Description
- •Example 7.1 Using JNDI
- •Pattern Use
- •JDBC
- •Packages
- •Overview
- •Example 7.2 Obtaining results from a database
- •Pattern Use
- •Packages
- •Overview
- •Pattern Use
- •CORBA
- •Packages
- •Overview
- •Java and CORBA
- •Pattern Use
- •Jini
- •Packages
- •Description
- •Lookup Service
- •Distributed Events
- •Pattern Use
- •Java 2, Enterprise Edition (J2EE)
- •Overview
- •Core J2EE Concepts
- •J2EE Tiers
- •Core Technical Concepts
- •Core Component Technologies
- •Communication and the Connector Technologies
- •Main J2EE Resources
- •Component Patterns
- •Servlets and JSPs
- •Packages
- •Overview
- •Main API Elements
- •Life Cycle
- •JavaServer Pages
- •Pattern Use
- •Enterprise JavaBeans
- •Packages
- •Description
- •General Pattern Use
- •Connector Pattern Use: Factory Method
- •Architectural Pattern Use
- •System Requirements
- •Creational Pattern Code Examples
- •Example A.1 AddressFactory.java
- •Example A.2 Address.java
- •Example A.3 PhoneNumber.java
- •Example A.4 USAddressFactory.java
- •Example A.5 USAddress.java
- •Example A.6 USPhoneNumber.java
- •Example A.7 FrenchAddressFactory.java
- •Example A.8 FrenchAddress.java
- •Example A.9 FrenchPhoneNumber.java
- •Example A.10 RunPattern.java
- •Example A.11 AppointmentBuilder.java
- •Example A.12 Appointment.java
- •Example A.13 Scheduler.java
- •Example A.14 MeetingBuilder.java
- •Example A.15 InformationRequiredException.java
- •Example A.16 Location.java
- •Example A.17 LocationImpl.java
- •Example A.18 Contact.java
- •Example A.19 ContactImpl.java
- •Example A.20 RunPattern.java
- •Example A.21 Editable.java
- •Example A.22 ItemEditor.java
- •Example A.23 Contact.java
- •Example A.24 EditorGui.java
- •Example A.25 RunPattern.java
- •Example A.26 Copyable.java
- •Example A.27 Address.java
- •Example A.28 RunPattern.java
- •Example A.29 HistoryList.java
- •Example A.30 SingletonGUI.java
- •Example A.31 RunPattern.java
- •Behavioral Pattern Code Examples
- •Example A.32 ProjectItem.java
- •Example A.33 Project.java
- •Example A.34 Task.java
- •Example A.35 Contact.java
- •Example A.36 ContactImpl.java
- •Example A.37 DataCreator.java
- •Example A.38 DataRetriever.java
- •Example A.39 RunPattern.java
- •Example A.40 Command.java
- •Example A.41 UndoableCommand.java
- •Example A.42 Appointment.java
- •Example A.43 ChangeLocationCommand.java
- •Example A.44 CommandGui.java
- •Example A.45 LocationEditor.java
- •Example A.46 Contact.java
- •Example A.47 ContactImpl.java
- •Example A.48 Location.java
- •Example A.49 LocationImpl.java
- •Example A.50 RunPattern.java
- •Example A.51 Expression.java
- •Example A.52 ConstantExpression.java
- •Example A.53 VariableExpression.java
- •Example A.54 CompoundExpression.java
- •Example A.55 AndExpression.java
- •Example A.56 OrExpression.java
- •Example A.57 ComparisonExpression.java
- •Example A.58 EqualsExpression.java
- •Example A.59 ContainsExpression.java
- •Example A.60 Context.java
- •Example A.61 ContactList.java
- •Example A.62 Contact.java
- •Example A.63 ContactImpl.java
- •Example A.64 RunPattern.java
- •Example A.65 Iterating.java
- •Example A.66 ToDoList.java
- •Example A.67 ToDoListCollection.java
- •Example A.68 ToDoListCollectionImpl.java
- •Example A.69 ToDoListImpl.java
- •Example A.70 ListPrinter.java
- •Example A.71 DataCreator.java
- •Example A.72 DataRetriever.java
- •Example A.73 RunPattern.java
- •Example A.74 MediatorGui.java
- •Example A.75 ContactDisplayPanel.java
- •Example A.76 ContactSelectorPanel.java
- •Example A.77 ContactEditorPanel.java
- •Example A.78 ContactMediator.java
- •Example A.79 ContactMediatorImpl.java
- •Example A.80 Contact.java
- •Example A.81 ContactImpl.java
- •Example A.82 RunPattern.java
- •Example A.83 AddressBook.java
- •Example A.84 Address.java
- •Example A.85 AddressImpl.java
- •Example A.86 Contact.java
- •Example A.87 ContactImpl.java
- •Example A.88 RunPattern.java
- •Example A.89 TaskChangeObservable.java
- •Example A.90 TaskChangeObserver.java
- •Example A.91 ObserverGui.java
- •Example A.92 TaskEditorPanel.java
- •Example A.93 TaskHistoryPanel.java
- •Example A.94 TaskSelectorPanel.java
- •Example A.95 Task.java
- •Example A.96 RunPattern.java
- •Figure A.1. State transition diagram for a file
- •Example A.97 State.java
- •Example A.98 CalendarEditor.java
- •Example A.99 StateGui.java
- •Example A.100 Appointment.java
- •Example A.101 Contact.java
- •Example A.102 ContactImpl.java
- •Example A.103 Location.java
- •Example A.104 LocationImpl.java
- •Example A.105 DataCreator.java
- •Example A.106 FileLoader.java
- •Example A.107 RunPattern.java
- •Example A.108 ContactList.java
- •Example A.109 SummarizingStrategy.java
- •Example A.110 NameSummarizer.java
- •Example A.111 OrganizationSummarizer.java
- •Example A.112 Contact.java
- •Example A.113 ContactImpl.java
- •Example A.114 DataCreator.java
- •Example A.115 DataRetriever.java
- •Example A.116 RunPattern.java
- •Example A.117 ProjectItem.java
- •Example A.118 Deliverable.java
- •Example A.119 DependentTask.java
- •Example A.120 Project.java
- •Example A.121 Task.java
- •Example A.122 ProjectVisitor.java
- •Example A.123 ProjectCostVisitor.java
- •Example A.124 Contact.java
- •Example A.125 ContactImpl.java
- •Example A.126 DataCreator.java
- •Example A.127 DataRetriever.java
- •Example A.128 RunPattern.java
- •Example A.129 ProjectItem.java
- •Example A.130 Deliverable.java
- •Example A.131 Task.java
- •Example A.132 RunPattern.java
- •Structural Pattern Code Examples
- •Example A.133 Chovnatlh.java
- •Example A.134 ChovnatlhImpl.java
- •Example A.135 Contact.java
- •Example A.136 ContactAdapter.java
- •Example A.137 Contact.java
- •Example A.138 ListImpl.java
- •Example A.139 OrderedListImpl.java
- •Example A.140 BaseList.java
- •Example A.141 NumberedList.java
- •Example A.142 OrnamentedList.java
- •Example A.143 RunPattern.java
- •Example A.144 ProjectItem.java
- •Example A.145 Deliverable.java
- •Example A.146 Project.java
- •Example A.147 Project.java
- •Example A.148 Task.java
- •Example A.149 Contact.java
- •Example A.150 ContactImpl.java
- •Example A.151 DataCreator.java
- •Example A.152 DataRetriever.java
- •Example A.153 RunPattern.java
- •Example A.154 ProjectItem.java
- •Example A.155 Deliverable.java
- •Example A.156 Task.java
- •Example A.157 ProjectDecorator.java
- •Example A.158 DependentProjectItem.java
- •Example A.159 SupportedProjectItem.java
- •Example A.160 Contact.java
- •Example A.161 ContactImpl.java
- •Example A.162 RunPattern.java
- •Example A.163 InternationalizationWizard.java
- •Example A.164 Currency.java
- •Example A.165 InternationalizedText.java
- •Example A.166 PhoneNumber.java
- •Example A.167 Nation.java
- •Example A.168 FacadeGui.java
- •Example A.169 DataCreator.java
- •Example A.170 RunPattern.java
- •Example A.171 State.java
- •Example A.172 CleanState.java
- •Example A.173 DirtyState.java
- •Example A.174 StateFactory.java
- •Example A.175 ManagedList.java
- •Example A.176 Address.java
- •Example A.177 AddressImpl.java
- •Example A.178 Contact.java
- •Example A.179 ContactImpl.java
- •Example A.180 RunPattern.java
- •Example A.181 Calendar.java
- •Example A.182 CalendarImpl.java
- •Example A.183 CalendarHOPP.java
- •Example A.184 Appointment.java
- •Example A.185 Contact.java
- •Example A.186 ContactImpl.java
- •Example A.187 Location.java
- •Example A.188 LocationImpl.java
- •Example A.189 FileLoader.java
- •Example A.190 RunPattern.java
- •Example A.191 AddressBook.java
- •Example A.192 AddressBookProxy.java
- •Example A.193 AddressBookImpl.java
- •Example A.194 FileLoader.java
- •Example A.195 Address.java
- •Example A.196 AddressImpl.java
- •Example A.197 DataCreator.java
- •Example A.198 RunPattern.java
- •System Pattern Code Examples
- •Example A.199 ContactModel.java
- •Example A.200 ContactView.java
- •Example A.201 ContactDisplayView.java
- •Example A.202 ContactEditView.java
- •Example A.203 ContactEditController.java
- •Example A.204 RunPattern.java
- •Example A.205 SessionClient.java
- •Example A.206 SessionServer.java
- •Example A.207 SessionServerImpl.java
- •Example A.208 SessionServerDelegate.java
- •Example A.209 SessionException.java
- •Example A.210 Address.java
- •Example A.211 AddressImpl.java
- •Example A.212 Contact.java
- •Example A.213 ContactImpl.java
- •Example A.214 RunPattern.java
- •Example A.215 Queue.java
- •Example A.216 RunnableTask.java
- •Example A.217 ConcreteQueue.java
- •Example A.218 AddressRetriever.java
- •Example A.219 ContractRetriever.java
- •Example A.220 ServerDataStore.java
- •Example A.221 ServerDataStoreImpl.java
- •Example A.222 Address.java
- •Example A.223 AddressImpl.java
- •Example A.224 Contact.java
- •Example A.225 ContactImpl.java
- •Example A.226 RunPattern.java
- •Example A.227 CallbackServer.java
- •Example A.228 CallbackServerImpl.java
- •Example A.229 CallbackServerDelegate.java
- •Example A.230 CallbackClient.java
- •Example A.231 CallbackClientImpl.java
- •Example A.232 Project.java
- •Example A.233 ProjectItem.java
- •Example A.234 Task.java
- •Example A.235 RunPattern.java
- •Example A.236 PullClient.java
- •Example A.237 ClientPullRequester.java
- •Example A.238 ClientPullServer.java
- •Example A.239 ClientPullServerImpl.java
- •Example A.240 UpdateServerDelegate.java
- •Example A.241 Task.java
- •Example A.242 TaskImpl.java
- •Example A.243 UpdateException.java
- •Example A.244 RunPattern.java
- •Example A.245 Message.java
- •Example A.246 InputChannel.java
- •Example A.247 OutputChannel.java
- •Example A.248 Router.java
- •Example A.249 InputKey.java
- •Example A.250 RouterClient.java
- •Example A.251 Receiver.java
- •Example A.252 RouterGui.java
- •Example A.253 RunPattern.java
- •Example A.254 AppointmentTransactionParticipant.java
- •Example A.255 AppointmentBook.java
- •Example A.256 TransactionException.java
- •Example A.257 Appointment.java
- •Example A.258 AppointmentImpl.java
- •Example A.259 Contact.java
- •Example A.260 ContactImpl.java
- •Example A.261 Location.java
- •Example A.262 LocationImpl.java
- •Example A.263 RunPattern.java
- •Appendix B.
- •Pattern Origins
- •Creational Patterns
- •Behavioral Patterns
- •Structural Patterns
- •System Patterns
- •[Bloch01]
- •[Coplien]
- •[DPCS]
- •[Fowler00]
- •[Jini01]
Successive Update
The example code shows a simple client pull solution for the Personal Information Manager. Clients use the server to centralize information about tasks they are working on. Each client stays up-to-date by periodically requesting updates from the server.
In the sample code, the PullClient class retrieves a task for a client. Its responsibility is to locate the RMI server so that it can request tasks on a regular basis.
Example A.236 PullClient.java
1.import java.net.MalformedURLException;
2.import java.rmi.Naming;
3.import java.rmi.NotBoundException;
4.import java.rmi.RemoteException;
5.import java.util.Date;
6.public class PullClient{
7.private static final String UPDATE_SERVER_SERVICE_NAME = "updateServer";
8.private static final String UPDATE_SERVER_MACHINE_NAME = "localhost";
9.private ClientPullServer updateServer;
10.private ClientPullRequester requester;
11.private Task updatedTask;
12.private String clientName;
13.
14.public PullClient(String newClientName){
15.clientName = newClientName;
16.try{
17. String url = "//" + UPDATE_SERVER_MACHINE_NAME + "/" + UPDATE_SERVER_SERVICE_NAME; 18. updateServer = (ClientPullServer)Naming.lookup(url);
19.}
20.catch (RemoteException exc){}
21.catch (NotBoundException exc){}
22.catch (MalformedURLException exc){}
23.catch (ClassCastException exc){}
24.}
25.
26.public void requestTask(String taskID){
27.requester = new ClientPullRequester(this, updateServer, taskID);
28.}
29.
30.public void updateTask(Task task){
31.requester.updateTask(task);
32.}
33.
34.public Task getUpdatedTask(){
35.return updatedTask;
36.}
37.
38.public void setUpdatedTask(Task task){
39.updatedTask = task;
40.System.out.println(clientName + ": received updated task: " + task);
41.}
42.
43.public String toString(){
44.return clientName;
45.}
46.}
When the client wants to receive updates on a task, it calls the method requestTask on the PullClient. The PullClient object creates a worker thread (see “ Worker Thread ” on page 517), which is the ClientPullRequester object. This object resides on the client, and regularly issues a request to the server for updated task information.
Example A.237 ClientPullRequester.java
1.import java.rmi.RemoteException;
2.public class ClientPullRequester implements Runnable{
3.private static final int DEFAULT_POLLING_INTERVAL = 10000;
4.private Thread processingThread;
5.private PullClient parent;
6.private ClientPullServer updateServer;
7.private String taskID;
8.private boolean shutdown;
9.private Task currentTask = new TaskImpl();
349
10. private int pollingInterval = DEFAULT_POLLING_INTERVAL; 11.
12.public ClientPullRequester(PullClient newParent, ClientPullServer newUpdateServer,
13. String newTaskID){
14.parent = newParent;
15.taskID = newTaskID;
16.updateServer = newUpdateServer;
17.processingThread = new Thread(this);
18.processingThread.start();
19.}
20.
21.public void run(){
22.while (!isShutdown()){
23. |
try{ |
24. |
currentTask = updateServer.getTask(taskID, currentTask.getLastEditDate()); |
25. |
parent.setUpdatedTask(currentTask); |
26. |
} |
27. |
catch (RemoteException exc){ } |
28. |
catch (UpdateException exc){ |
29. |
System.out.println(" " + parent + ": " + exc.getMessage()); |
30. |
} |
31. |
try{ |
32. |
Thread.sleep(pollingInterval); |
33. |
} |
34. |
catch (InterruptedException exc){ } |
35.}
36.}
38.public void updateTask(Task changedTask){
39.try{
40. updateServer.updateTask(taskID, changedTask);
41.}
42.catch (RemoteException exc){ }
43.catch (UpdateException exc){
44. System.out.println(" " + parent + ": " + exc.getMessage());
45.}
46.}
48.public int getPollingInterval(){ return pollingInterval; }
49.public boolean isShutdown(){ return shutdown; }
50.
51.public void setPollingInterval(int newPollingInterval){ pollingInterval =
newPollingInterval; }
52.public void setShutdown(boolean isShutdown){ shutdown = isShutdown; }
53.}
The RMI server's behavior is defined by the ClientPullServer interface and managed by the ClientPullServerImpl class. Two methods allow clients to interact with a server, getTask and updateTask.
Example A.238 ClientPullServer.java
1.import java.rmi.Remote;
2.import java.rmi.RemoteException;
3.import java.util.Date;
4.public interface ClientPullServer extends Remote{
5.public Task getTask(String taskID, Date lastUpdate) throws RemoteException,
UpdateException;
6.public void updateTask(String taskID, Task updatedTask) throws RemoteException,
UpdateException;
7.}
Example A.239 ClientPullServerImpl.java
1.import java.util.Date;
2.import java.rmi.Naming;
3.import java.rmi.server.UnicastRemoteObject;
4.public class ClientPullServerImpl implements ClientPullServer{
5.private static final String UPDATE_SERVER_SERVICE_NAME = "updateServer";
6.public ClientPullServerImpl(){
7.try {
8. |
UnicastRemoteObject.exportObject(this); |
9. |
Naming.rebind(UPDATE_SERVER_SERVICE_NAME, this); |
10.}
11.catch (Exception exc){
12.System.err.println("Error using RMI to register the ClientPullServerImpl " + exc);
13.}
14.}
15.
350
16.public Task getTask(String taskID, Date lastUpdate) throws UpdateException{
17.return UpdateServerDelegate.getTask(taskID, lastUpdate);
18.}
19.
20.public void updateTask(String taskID, Task updatedTask) throws UpdateException{
21.UpdateServerDelegate.updateTask(taskID, updatedTask);
22.}
23.}
The class UpdateServerDelegate performs the server-side behavior for ClientPullServerImpl. Specifically, it retrieves Task objects, and ensures that up-to-date copies of Tasks are provided to clients by comparing the last update Date.
Example A.240 UpdateServerDelegate.java
1.import java.util.Date;
2.import java.util.HashMap;
3.public class UpdateServerDelegate{
4.private static HashMap tasks = new HashMap();
6.public static Task getTask(String taskID, Date lastUpdate) throws UpdateException{
7.if (tasks.containsKey(taskID)){
8. |
Task storedTask = (Task)tasks.get(taskID); |
9. |
if (storedTask.getLastEditDate().after(lastUpdate)){ |
10. |
return storedTask; |
11. |
} |
12. |
else{ |
13. |
throw new UpdateException("Task " + taskID + " does not need to be updated", |
|
UpdateException.TASK_UNCHANGED); |
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.}
}
}
else{
return loadNewTask(taskID);
}
}
public static void updateTask(String taskID, Task task) throws UpdateException{
if (tasks.containsKey(taskID)){ |
Y |
||||
|
|
|
|
|
L |
if (task.getLastEditDate().equals(((Task)tasks.get(taskID)). getLastEditDate())){ |
|||||
|
((TaskImpl)task).setLastEditDate(new Date()); |
||||
} |
tasks.put(taskID, task); |
F |
|||
else{ |
|
A |
|
||
E |
M |
||||
|
throw new UpdateException("Task " + taskID + " data must be refreshed before |
||||
|
|
T |
|
|
|
editing", Update xception.TASK_OUT_OF_DATE);
}
}
}
private static Task loadNewTask(String taskID){
Task newTask = new TaskImpl(taskID, "", new Date(), null); tasks.put(taskID, newTask);
return newTask;
}
Any problems encountered during the periodic client pull operations are represented by the UpdateException class. The Task interface and TaskImpl class represent the business elements of the example.
Example A.241 Task.java
1.import java.util.Date;
2.import java.io.Serializable;
3.import java.util.ArrayList;
4.public interface Task extends Serializable{
5.public String getTaskID();
6.public Date getLastEditDate();
7.public String getTaskName();
8.public String getTaskDetails();
9.public ArrayList getSubTasks();
10. |
|
public void setTaskName(String newName); |
11. |
|
|
12. |
|
public void setTaskDetails(String |
13. |
|
public void addSubTask(Task |
14. |
|
public void removeSubTask(Task |
15. |
} |
TEAM FLY PRESENTS |
|
351
Example A.242 TaskImpl.java
1.import java.util.Date;
2.import java.io.Serializable;
3.import java.util.ArrayList;
4.public class TaskImpl implements Task{
5.private String taskID;
6.private Date lastEditDate;
7.private String taskName;
8.private String taskDetails;
9.private ArrayList subTasks = new ArrayList();
11.public TaskImpl(){
12.lastEditDate = new Date();
13.taskName = "";
14.taskDetails = "";
15.}
16.public TaskImpl(String newTaskName, String newTaskDetails,
17.Date newEditDate, ArrayList newSubTasks){
18.lastEditDate = newEditDate;
19.taskName = newTaskName;
20.taskDetails = newTaskDetails;
21.if (newSubTasks != null){ subTasks = newSubTasks; }
22.}
23.
24.public String getTaskID(){
25.return taskID;
26.}
27.public Date getLastEditDate(){ return lastEditDate; }
28.public String getTaskName(){ return taskName; }
29.public String getTaskDetails(){ return taskDetails; }
30.public ArrayList getSubTasks(){ return subTasks; }
32.public void setLastEditDate(Date newDate){
33.if (newDate.after(lastEditDate)){
34. lastEditDate = newDate;
35.}
36.}
37.public void setTaskName(String newName){ taskName = newName; }
38.public void setTaskDetails(String newDetails){ taskDetails = newDetails; }
39.public void addSubTask(Task task){
40.if (!subTasks.contains(task)){
41. subTasks.add(task);
42.}
43.}
44.public void removeSubTask(Task task){
45.subTasks.remove(task);
46.}
47.
48.public String toString(){
49.return taskName + " " + taskDetails;
50.}
51.}
Example A.243 UpdateException.java
1.public class UpdateException extends Exception{
2.public static final int TASK_UNCHANGED = 1;
3.public static final int TASK_OUT_OF_DATE = 2;
4.private int errorCode;
5.
6.public UpdateException(String cause, int newErrorCode){
7.super(cause);
8.errorCode = newErrorCode;
9.}
10.public UpdateException(String cause){ super(cause); }
11.
12.public int getErrorCode(){ return errorCode; }
13.}
RunPattern demonstrates how updates of a Task can be propagated to multiple clients. The main method creates a ClientPullServer and two PullClient objects. Both clients are used to request a common Task, then one of the PullClients makes an update to the Task. The change is reflected in the other client as its worker thread, the ClientPullRequester, polls the server for changes.
Example A.244 RunPattern.java
1. import java.io.IOException;
352
2.public class RunPattern{
3.public static void main(String [] arguments){
4.System.out.println("Example for the SuccessiveUpdate pattern");
5.System.out.println("This code provides a basic demonstration");
6.System.out.println(" of how the client pull form of this pattern");
7.System.out.println(" could be applied.");
8.System.out.println("In this case, a change made by a client to a");
9.System.out.println(" central Task object is subsequently retrieved");
10.System.out.println(" and displayed by another client.");
11.
12.System.out.println("Running the RMI compiler (rmic)");
13.System.out.println();
14.try{
15. Process p1 = Runtime.getRuntime().exec("rmic ClientPullServerImpl");
16. p1.waitFor();
17.}
18.catch (IOException exc){
19. System.err.println("Unable to run rmic utility. Exiting application.");
20. System.exit(1);
21.}
22.catch (InterruptedException exc){
23. |
System.err.println("Threading problems encountered while using the rmic utility."); |
24. |
} |
25. |
|
26.System.out.println("Starting the rmiregistry");
27.System.out.println();
28.Process rmiProcess = null;
29.try{
30. rmiProcess = Runtime.getRuntime().exec("rmiregistry");
31. Thread.sleep(15000);
32.}
33.catch (IOException exc){
34. System.err.println("Unable to start the rmiregistry. Exiting application.");
35. System.exit(1);
36.}
37.catch (InterruptedException exc){
38. |
System.err.println("Threading problems encountered when starting the rmiregistry."); |
39. |
} |
40. |
|
41.System.out.println("Creating the ClientPullServer and two PullClient objects");
42.ClientPullServer server = new ClientPullServerImpl();
43.PullClient clientOne = new PullClient("Thing I");
44.PullClient clientTwo = new PullClient("Thing II");
45.clientOne.requestTask("First work step");
46.clientTwo.requestTask("First work step");
47.
48.try{
49. Thread.sleep(10000);
50.}
51.catch (InterruptedException exc){ }
53.Task task = clientOne.getUpdatedTask();
54.task.setTaskDetails("Trial for task update");
55.clientOne.updateTask(task);
56.
57.Task newTask = clientTwo.getUpdatedTask();
58.newTask.setTaskDetails("New details string");
59.clientTwo.updateTask(newTask);
60.
61.
62.}
63.}
353