Design Pattrens1
Design Pattrens1
DESIGN
PATTERNS
class Namer {
public FirstFirst(String s) {
int i = s.lastIndexOf( " "); //find sep
space
if (i > 0) {
//left is first name
first = s.substring( 0, i).trim();
//right is last name
last =s.substring( i+1).trim( );
}
else {
first = “”; // put all in last name
last = s; // if no space
}}}
class NameFactory {
//returns an instance of LastFirst
or FirstFirst
//depending on whether a comma is
found
public Namer getNamer(String
entry) {
int i = entry.indexOf( ",");
//comma determines name order
if (i>0)
DesignPatterns 13
return new
LastFirst(entry) ; //return one
class
else
return new
FirstFirst(entry) ; //or the other
}}
/**
* This method returns the singleton
instance of this class.
DesignPatterns 18
* @return PerdiemDAO
*/
return INSTANCE;
}
}
4. Delegation pattern
5. Observer Pattern
Simply, the Observer pattern allows one
object (the observer) to watch another
(the subject). The Observer pattern
allows the subject and observer to form
a publish-subscribe relationship.
Through the Observer pattern,
observers can register to receive events
from the subject. When the subject
needs to inform its observers of an
event, it simply sends the event to each
observer.
Use the Observer pattern in any of the
following situations:
DesignPatterns 26
import java.util.ArrayList ;
import java.util.Iterator;
return null;
}
public void
addObserver( Observer o ) {
observers.add( o );
}
public void
removeObserver( Observer o ) {
observers.remove( o );
}
private void
notifyObservers( ) {
// loop through and
notify each observer
Iterator i =
observers.iterator( );
while( i.hasNext() ) {
Observer o =
( Observer ) i.next();
o.update( this )
;
}
}
}
DesignPatterns 30
import java.util.Iterator;
public
IntegerAdder( IntegerDataBag bag )
{
this.bag =
bag;
bag.addObserver( this
);
}
o ) {
if( o == bag ) {
System.out.print
ln( "The contents of the
IntegerDataBag have changed." );
int counter = 0;
Iterator i =
bag.iterator( );
while( i.hasNext
() ) {
Integer
integer = ( Integer ) i.next();
counter+=i
nteger. intValue( );
}
System.out.print
ln( "The new sum of the integers
is: " + counter );
} }}
import java.util.Iterator;
public
IntegerPrinter( IntegerDataBag bag
) {
this.bag =
bag;
bag.addObserver( this
);
}
System.out.println( "adding
another integer to the bag:" );
bag.add( i9 );
System.out.println( "");
System.out.println( "About
to remove an integer from the
bag:");
bag.remove( 0 );
DesignPatterns 35
}
}
The IntegerDataBag/ IntegerAdder/
IntegerPrinter is a simple example of
the Observer pattern. Within Java itself
there are a number of examples of the
Observer pattern: the AWT/Swing event
model, as well as the
java.util.Observer and
java.util.Observabl e interfaces
serve as examples.
6. Struts Patterns
Front Controller
The Front Controller pattern defines a
single component that is responsible for
processing application requests. A front
controller centralizes functions such as
view selection, security, and templating,
and applies them consistently across all
pages or views. Consequently, when the
behavior of these functions need to
change, only a small part of the
DesignPatterns 37
Dispatcher : A dispatcher is
responsible for view management and
navigation, managing the choice of the
next view to present to the user, and
providing the mechanism for vectoring
control to this resource. A dispatcher
can be encapsulated within a controller
or can be a separate component
working in coordination. The dispatcher
provides either a static dispatching to
the view or a more sophisticated
dynamic dispatching mechanism. The
dispatcher uses the RequestDispatcher
object (supported in the servlet
specification) and encapsulates some
additional processing.
Helper : A helper is responsible for
helping a view or controller complete its
processing. Thus, helpers have
numerous responsibilities, including
gathering data required by the view and
DesignPatterns 40
View
A view represents and displays
information to the client. The view
retrieves information from a model.
Helpers support views by encapsulating
and adapting the underlying data model
DesignPatterns 41
Command Pattern
A Command pattern is an object
behavioral pattern that allows us
to achieve complete decoupling
between the sender and the
receiver. (A sender is an object
that invokes an operation, and a
receiver is an object that receives
the request to execute a certain
operation. With decoupling, the
sender has no knowledge of the
Receiver's interface.) The term
request here refers to the
DesignPatterns 43
// CommandExample. java
import java.util.HashMap;
// ************ *********
********* ********* *********
********* ********* ******
/**
* CommandExample. java
*
* Provides a simple Command
Design Pattern Example.
*
* The example will show how to
use the Command Design Pattern
* by replacing conditional
control logic in a simulated M-V-C
Model
DesignPatterns 45
CommandExample.
log(1,"Simulated servlet request
received is: " +
exampleActionReques t);
CommandExample.
log(1,"Code will show " +
maxApproaches +
"
approaches as to how such a
command can be processed.") ;
for(int i=1;
i<=maxApproaches; i++) {
exampleServlet. doPost(i,
exampleActionReq uest);
} //endfor
CommandExample.
log(1,"End Command Design Pattern
example.");
} //endmain
// ============ =========
========= ========= =========
========= ========= =
public static void log(int
aLevel, String aMsg) {
DesignPatterns 47
boolean
showLogTraceToSyste mOut = true;
if(showLogTraceToSy stemOut) {
String
prefix = "";
if(aLevel
== 1) {
System.out.println( prefix +
aMsg);
} //endif
} //endmethod: log
} //endclass: CommandExample. java
DesignPatterns 48
// ************ *********
********* ********* *********
********* ********* ******
/**
* ExampleServlet. java
*
* Simulates a servlet in an M-V-C
Model 2 environment.
*
* @param action the desired
action the servlet is to perform.
*/
// ************ *********
********* ********* *********
********* ********* ******
class ExampleServlet {
private HashMap commandMap
= new HashMap();
// ============ =========
========= ========= =========
========= ========= =
DesignPatterns 49
public ExampleServlet( ) {
//-- Initialize
HashMap of possible ActionType
concrete objects
// ============ =========
========= ========= =========
========= ========= =
public void doPost(int
approachSolution, String action) {
switch
(approachSolution) {
case 1:
DesignPatterns 50
CommandExample. log(2,
performTask1( action);
break;
case 2:
CommandExample. log(2,
performTask2( action);
break;
case 3:
CommandExample. log(2,
performTask3( action);
break;
} //endswitch
DesignPatterns 51
} //endmethod: doPost
// ============ =========
========= ========= =========
========= ========= =
private void performTask1(
String action) {
//-- Process
business logic within conditional
statements
if( action.equalsIgnore
Case("create" ) ) {
CommandExample. log(3,
CommandExample. log(3,
} else
if( action.equalsIgnore
Case("update" ) ) {
CommandExample. log(3,
CommandExample. log(3,
// ============ =========
========= ========= =========
========= ========= =
private void performTask2(
String action) {
DesignPatterns 53
if( action.equalsIgnore
Case("create" ) ) {
cmd = new
ActionTypeCreate( );
} else
if( action.equalsIgnore
Case("replace" ) ) {
cmd = new
ActionTypeReplace( );
} else
if( action.equalsIgnore
Case("update" ) ) {
cmd = new
ActionTypeUpdate( );
} else
if( action.equalsIgnore
Case("delete" ) ) {
cmd = new
ActionTypeDelete( );
} //endif
DesignPatterns 54
cmd.execute( );
} //endmethod:
performTask2
// ============ =========
========= ========= =========
========= ========= =
private void performTask3(
String action) {
//-- Uses the
Command Design Pattern to
polymorphically
//-- execute
desired action
ActionType cmd =
(ActionType) commandMap.
get(action) ;
cmd.execute( );
} //endmethod:
performTask3
} //endclass: ExampleServlet
// ************ *********
********* ********* *********
********* ********* ******
abstract class ActionType {
DesignPatterns 55
// ************ *********
********* ********* *********
********* ********* ******
class ActionTypeCreate extends
ActionType {
public void execute() {
CommandExample.
log(3,
// ************ *********
********* ********* *********
********* ********* ******
class ActionTypeReplace extends
ActionType {
public void execute() {
CommandExample.
log(3,
DesignPatterns 56
// ************ *********
********* ********* *********
********* ********* ******
class ActionTypeUpdate extends
ActionType {
public void execute() {
CommandExample.
log(3,
// ************ *********
********* ********* *********
********* ********* ******
class ActionTypeDelete extends
ActionType {
public void execute() {
DesignPatterns 57
CommandExample.
log(3,
TestCommand. java
class Fan {
public void startRotate( )
{
System.out.println
( "Fan is rotating");
}
public void stopRotate() {
System.out.println
( "Fan is not rotating");
DesignPatterns 59
}
}
class Light {
public void turnOn( ) {
System.out.println
( "Light is on ");
}
public void turnOff( ) {
System.out.println
( "Light is off");
}
}
class Switch {
private Command UpCommand,
DownCommand;
public Switch( Command Up,
Command Down) {
UpCommand = Up; //
concrete Command registers itself
with the invoker
DownCommand =
Down;
}
void flipUp( ) { //
invoker calls back concrete
Command, which executes the
Command on the receiver
DesignPatterns 60
UpCommand
. execute ( ) ;
}
void flipDown( ) {
DownComman
d . execute ( );
}
}
class LightOnCommand implements
Command {
private Light myLight;
public LightOnCommand
( Light L) {
myLight = L;
}
public void execute( ) {
myLight .
turnOn( );
}
}
class LightOffCommand implements
Command {
private Light myLight;
public LightOffCommand
( Light L) {
myLight = L;
DesignPatterns 61
}
public void execute( ) {
myLight . turnOff(
);
}
}
class FanOnCommand implements
Command {
private Fan myFan;
public FanOnCommand ( Fan
F) {
myFan = F;
}
public void execute( ) {
myFan .
startRotate( );
}
}
class FanOffCommand implements
Command {
private Fan myFan;
myFan .
stopRotate( );
}
}
public class TestCommand {
public static void
main(String[ ] args) {
Light tes
tLight = new Light( );
LightOnCom
mand testLOC = new LightOnCommand(
testLight) ;
LightOffCo
mmand testLFC = new
LightOffCommand( testLight) ;
Switch
testSwitch = new
Switch( testLOC,testLFC) ;
testSwitch
.flipUp( );
testSwitch
.flipDown ( );
Fan
testFan = new Fan( );
FanOnComma
nd foc = new
FanOnCommand( testFan);
DesignPatterns 63
FanOffComm
and ffc = new
FanOffCommand( testFan);
Switch ts
= new Switch( foc,ffc);
ts.flipUp(
);
ts.flipDow
n( );
}
}
Command.java
public interface Command {
public abstract void
execute ( );
}
Notice in the code example above that
the Command pattern completely
decouples the object that invokes the
operation -- (Switch ) -- from the ones
having the knowledge to perform it --
Light and Fan. This gives us a lot of
flexibility: the object issuing a request
must know only how to issue it; it
doesn't need to know how the request
will be carried out.
DesignPatterns 64
7. DAO
The Data Access Object Pattern, also known
as the DAO pattern, abstracts the retrieval of
data from a data resource such as a
database. The concept is to "separate a data
resource's client interface from its data access
mechanism."
J2EE developers use the Data Access Object
(DAO) design pattern to separate low-level
data access logic from high-level business
logic. Implementing the DAO pattern involves
more than just writing data access code.
The problem with accessing data directly is
that the source of the data can change.
Consider, for example, that your application is
deployed in an environment that accesses an
DesignPatterns 65
SampleDAOException;
DesignPatterns 67
}
}
import java.sql.*;
conn.prepareStateme
nt( "INSERT INTO sample VALUES( ?,
?, ? )" );
ps.setLong( 1, id );
ps.setString( 2, name );
ps.setString( 3, data );
ps.executeUpdate( );
return new SampleModel( id,
name, data );
}
catch( SQLException e ) {
throw new SampleDAOException( e
);
}
}
?
}
import javax.naming.
NamingException;
import javax.naming.
InitialContext;
try {
InitialContext ic = new
InitialContext( );
String className =
( String )
ic.lookup( "SAMPLEDAO.Impl" );
DesignPatterns 75
dao = ( SampleDAO )
Class.forName( className ).newInst
ance( );
}
catch( NamingException ne ) {
throw new
SampleDAOException( ne );
}
catch( Exception se ) {
throw new
SampleDAOException( se );
}
return dao; } }
<remote>com.ks.myejb.
ejb.Sample</remote>
<ejb-class>com.ks.myejb.
ejb.SampleEJB</ejb-class>
<persistence-
type>Bean</persistence- type>
<prim-key-class>com.ks.myejb.
ejb.SamplePk</prim-key-class>
<reentrant>False</reentrant>
<env-entry>
<env-entry-
name>SAMPLEDAO.Impl</env-entry-
name>
<env-entry-
type>java.lang.String</env-entry-
type>
<env-entry-value>com.ks.myejb.
dao.SampleDAOJDB CImpl</env-
entry-value>
</env-entry>
...
</entry>
...
</enterprise- beans>
<ejb-jar>
DesignPatterns 78
Sample Code
Implementing the Session Facade
Consider a Professional Services
Application (PSA), where the workflow
related to entity beans (such as Project,
Resource) is encapsulated in
ProjectResourceMana gerSession,
implemented using the Session Facade
pattern. Example 8.15 shows the
interaction with Resource and Project
entity beans, as well as other business
components, like Value List Handlers
(see "Value List Handler" on page 354)
and Transfer Object Assemblers (see
DesignPatterns 84
import java.util.*;
import java.rmi.RemoteExce ption;
import javax.ejb.*;
import javax.naming. *;
import corepatterns. apps.psa.
core.*;
import corepatterns.
util.ServiceLoca tor;
import corepatterns.
util.ServiceLoca torException;
// default create
public void ejbCreate()
throws CreateException {
}
try {
// locate and connect to
entity beans
connectToEntities( resourceId,
projectId, ...);
} catch(...) {
// Handle exceptions
}
}
session facade to a
// different set of entity beans
using primary key
// values
public resetEntities( String
resourceId,
String projectId, ...)
throws PSAException {
connectToEntities( resourceId,
projectId, ...);
}
private ProjectHome
getProjectHome( )
throws ServiceLocatorExcep tion
{
return ServiceLocator.
getInstance( ).getHome(
"ProjectEntity" ,
ProjectHome. class);
}
// Method to encapsulate
workflow related
// to assigning a resource to a
project.
// It deals with Project and
Resource Entity beans
public void assignResourceToPro
ject(int numHours)
throws PSAException {
try {
if ((projectEntity == null)
||
(resourceEntity ==
null)) {
DesignPatterns 90
// SessionFacade not
connected to entities
throw new
PSAException( ...);
}
projectEntity.
addCommitment( commitment) ;
} catch(...) {
// Handle exceptions
}
}
public void
setResourceData( ResourceTO
resource)
throws ResourceException {
...
}
Collection blockoutTime)
throws RemoteException,
BlockoutTimeExcepti on {
...
}
public Collection
getResourceCommitme nts()
throws RemoteException,
ResourceException {
...
}
...
ServiceLocator.
getInstance( ).getHome(
"ProjectTOA" ,
ProjectTOAHome. class);
// Transfer Object Assembler
session bean
ProjectTOA projectTOA =
projectTOAHome.
create(.. .);
return
projectTOA.getData( ...);
} catch (...) {
// Handle / throw
exceptions
}
}
projectVLHHome =
(ProjectVLHHome)
ServiceLocator.
getInstance( ).getHome(
"ProjectListHandler ",
ProjectVLHHome.
class);
// Value List Handler
session bean
ProjectListHandler
projectListHandler =
projectVLHHome. create();
return projectListHandler.
getProjects(
start, end);
} catch (...) {
// Handle / throw
exceptions
}
}
...
public void
setSessionContext( SessionContext
ctx) {
this.context = ctx;
}
core.*;
public interface
ProjectResourceMana ger
extends EJBObject {
...
DesignPatterns 99
public ResourceTO
getResourceData( )
throws RemoteException,
ResourceException ;
public void
setResourceData( ResourceTO
resource)
throws RemoteException,
ResourceException ;
public ResourceTO
createNewResource( ResourceTO
resource)
throws ResourceException ;
public void
addBlockoutTime( Collection
blockoutTime)
throws RemoteException,
BlockoutTimeExce ption ;
public void
updateBlockoutTime( Collection
blockoutTime)
throws RemoteException,
BlockoutTimeExce ption ;
DesignPatterns 100
public Collection
getResourceCommitme nts()
throws RemoteException,
ResourceException;
public void
setProjectData( ProjectTO project)
throws RemoteException,
ProjectException ;
public ProjectTO
createNewProject( ProjectTO
project)
throws RemoteException,
ProjectException ;
...
public ProjectCTO
getProjectDetailsDa ta()
throws RemoteException,
DesignPatterns 101
PSAException ;
public Collection
getProjectsList( Date start,
Date end) throws
RemoteException, PSAException ;
...
}
import javax.ejb.EJBHome;
import java.rmi.RemoteExce ption;
import corepatterns. apps.psa.
core.ResourceExc eption;
import javax.ejb.*;
public interface
ProjectResourceMana gerHome
extends EJBHome {
DesignPatterns 102
9. Service Locator
Enterprise applications require a way to
look up the service objects that provide
access to distributed components.
JavaTM 2 Platform, Enterprise Edition
(J2EE) applications use Java Naming
and Directory Interface (JNDI) to look
up enterprise bean home interfaces,
Java Message Service (JMS)
components, data sources, connections,
and connection factories. Repetitious
lookup code makes code difficult to read
DesignPatterns 103
Service Locator
The Service Locator abstracts the API
lookup (naming) services, vendor
dependencies, lookup complexities, and
business object creation, and provides a
simple interface to clients. This reduces
the client's complexity. In addition, the
same client or other clients can reuse
the Service Locator.
InitialContext
The InitialContext object is the start
point in the lookup and creation
process.
Service providers provide the context
object, which varies depending on the
type of
business object provided by the Service
Locator's lookup and creation service. A
Service Locator that provides services
for multiple types of business objects
(such
as enterprise beans, JMS components,
and so forth) utilizes multiple types of
DesignPatterns 107
ServiceFactory
BusinessService
Pattern Details
DesignPatterns 109
static {
try {
me = new ServiceLocator( );
} catch(ServiceLocato
rException se) {
DesignPatterns 110
System.err.println( se);
se.printStackTrace( System.err) ;
}
}
private ServiceLocator( ) throws
ServiceLocatorExcep tion {
try {
ic = new InitialContext( );
cache = Collections.
synchronizedMap( new HashMap());
} catch (NamingException ne) {
throw new
ServiceLocatorExcep tion(ne);
}
}
• getString()
The getRemoteHome( ) and
getLocalHome( ) are used to obtain an
EJBHome object for the specific object
either remotely or locally (in the same
JVM), respectively. The next four
methods are used for accessing JMS
resources and the getDataSource( )
method returns a JDBC Data Source.
The final three methods load
environment entries that are defined in
your deployment descriptors; this is a
mechanism that you can use to
customize the behavior of your J2EE
application at runtime.
Listing 2 shows the implementation of
the getRemoteHome( ) method.
Listing 2. ServiceLocator getRemoteHome( )
method implementation
public EJBHome
getRemoteHome( String
jndiHomeName, Class className)
DesignPatterns 113
return home;
}
From listing 2 you can see the code first
checks to see if the requested EJBHome
has already been loaded into the cache;
if not it loads it through its cached
InitialContext instance and stores it
in the cache. The remaining methods
are similarly implemented, and I
encourage you to look through the Pet
Store source code for more details.
Summary
The Service Locator Pattern is used to
abstract application server details from
JNDI lookups, centralize all access to
JNDI resources, and improve
performance by caching resources and a
reference to the JNDI server itself. The
Java PetStore application makes use of
this pattern and should be referenced
for more implementation details.
DesignPatterns 115
.
__,_._,___