Patterns in Java: A Catalog of Reusable Design Patterns Illustrated with UML with CD-ROM

Overview

A goldmine of timesaving Java Patterns--and how to make them work for you.

The godsend for which programmers and developers have been waiting is here: a comprehensive guide to using Java and Design Patterns together. Featuring complete coverage of the patterns that can occur in any project's development, Java guru Mark Grand looks at all of the re-usable patterns already circulating in the community, introduces several new patterns, and clearly demonstrates how to write your own...

See more details below
Available through our Marketplace sellers.
Other sellers (Paperback)
  • All (34) from $1.99   
  • New (2) from $45.00   
  • Used (32) from $1.99   
Close
Sort by
Page 1 of 1
Showing All
Note: Marketplace items are not eligible for any BN.com coupons and promotions
$45.00
Seller since 2013

Feedback rating:

(39)

Condition:

New — never opened or used in original packaging.

Like New — packaging may have been opened. A "Like New" item is suitable to give as a gift.

Very Good — may have minor signs of wear on packaging but item works perfectly and has no damage.

Good — item is in good condition but packaging may have signs of shelf wear/aging or torn packaging. All specific defects should be noted in the Comments section associated with each item.

Acceptable — item is in working order but may show signs of wear such as scratches or torn packaging. All specific defects should be noted in the Comments section associated with each item.

Used — An item that has been opened and may show signs of wear. All specific defects should be noted in the Comments section associated with each item.

Refurbished — A used item that has been renewed or updated and verified to be in proper working condition. Not necessarily completed by the original manufacturer.

New
Brand new.

Ships from: acton, MA

Usually ships in 1-2 business days

  • Standard, 48 States
$50.00
Seller since 2013

Feedback rating:

(39)

Condition: New
Brand new.

Ships from: acton, MA

Usually ships in 1-2 business days

  • Standard, 48 States
Page 1 of 1
Showing All
Close
Sort by
Sending request ...

Overview

A goldmine of timesaving Java Patterns--and how to make them work for you.

The godsend for which programmers and developers have been waiting is here: a comprehensive guide to using Java and Design Patterns together. Featuring complete coverage of the patterns that can occur in any project's development, Java guru Mark Grand looks at all of the re-usable patterns already circulating in the community, introduces several new patterns, and clearly demonstrates how to write your own Java patterns in UML. Patterns in Java is a timely response to the growing emphasis on design in object-oriented projects, smoothly guiding programmers through the early, error-prone stages of development. The book also features invaluable case studies readers can follow and learn from as they do their own work and, best of all, includes over 50 different Java Patterns with examples and complete code.

CD-ROM contains over 50 Design Patterns in Java.


Geared toward beginner to intermediate programmers, this guide focuses on Java design patterns. It explores UML, fundamental design patterns, creational patterns and partitioning patterns. Complete with CD-ROM, it reviews structural patterns, behavioral patterns and concurrency patterns.

Read More Show Less

Editorial Reviews

Bill Carmada
Through patterns, developers are able to systematize the wisdom gained through trial and error, so that others can benefit without making the same mistakes. UML offers an ideal way to communicate design patterns precisely and concisely. Patterns in Java, Volume 1 brings them all together, delivering a comprehensive catalog of 41 design patterns specifically for Java. Think of it as a blueprint for the early, error-prone stages of development, helping you build designs that are more elegant-and far easier to reuse.

Replete with Java source code and real-world scenarios, this book covers virtually every aspect of object-oriented design. Top Java consultant Mark Grand starts with five "fundamental" patterns you can apply across-the-board. Next, Grand introduces "creational" patterns that guide you in creating objects; "partitioning" patterns for organizing complex actors and concepts into multiple classes; "structural" patterns to optimize interactions amongst objects; and "concurrency" patterns to manage shared resources. He also provides eleven powerful "behavioral" patterns.

If you're one of the many programmers who recognize the benefits of careful up-front design but haven't actually gotten around to mastering patterns or UML, this is the resource you've been waiting for. You almost can't help but succeed!

Bill Carmada @ Cyberian Express

Booknews
Presents 41 design patterns complete with Java source code and a UML diagram. Provides an introduction to software patterns, an overview of UML, a chapter on the software life cycle, and several patterns of different types: behavioral, structural, concurrency, creational, fundamental, and partitioning. The CD-ROM contains Java code for the patterns, trial versions of Together from Object International, Rational Rose 98 from Rational Software, System Architect from Popkin Software, and OptimizeIt from Intuitive Systems. Annotation c. by Book News, Inc., Portland, Or.
Read More Show Less

Product Details

  • ISBN-13: 9780471258391
  • Publisher: Wiley, John & Sons, Incorporated
  • Publication date: 9/28/1998
  • Series: Patterns in Java Series
  • Edition description: 2nd Edition
  • Edition number: 1
  • Pages: 480
  • Product dimensions: 7.47 (w) x 9.16 (h) x 1.05 (d)

Meet the Author


Mark Grand is a consultant specializing in Java and objectoriented techniques. He has been an instructor for Sun''s Java training programs. He is also the author of Java Language Reference and Java Fundamental Classes Reference.

Read More Show Less

Read an Excerpt


Chapter 4: Fundamental Design Patterns

Delegation: When not to use inheritance (53)
Interface (61)
Immutable (67)
Marker Interface (73)
Proxy (79)

The patterns in this chapter are the most fundamental and important design patterns to know. You will find these patterns used extensively in other design patterns.

SYNOPSIS Delegation is a way to extend and reuse the functionality of a class by writing an additional class with added functionality that uses instances of the original class to provide the original functionality.

CONTEXT Inheritance is a common way to extend and reuse the functionality of a class. Delegation is a more general way for extending a class's behavior that involves a class calling another class's methods rather than inheriting them. Inheritance is inappropriate for many situations that delegations are appropriate for.
For example, inheritance is useful for capturing "is-a-kind-of" relationships because these types of relationships are very static in nature. However, "is-a-role-played-by" relationships are awkward to model by inheritance. Instances of a class can play multiple roles. Let's look at an example of an airline reservation system. This airline reservation system includes such roles as passenger, ticket selling agent, and flight crew. It's possible to represent this as a class called Person that has subclasses corresponding to these roles, as shown in Figure 4.1.
The problem with the diagram depicted in Figure 4.1 is that the same person can fill more than one of these roles. A person who is normally part of a flight crew can also be a passenger. Some airlines occasionally float the flight crew to the ticket counter. This means that the same person can fill any combination of these roles. To model this situation, you need 7 subclasses for Person, as shown in Figure 4.2. The number of subclasses needed increases exponentially with the number of roles. Therefore, you need 63 subclasses to model 6 roles.
A more serious problem is that the same person can play different combinations of roles at different times. Inheritance is a static relationship that does not change over time. Using inheritance necessitates using multiple objects to represent the same person in order to capture changes in role.

On the other hand, it's possible to represent persons in different
roles using delegation without having any of those problems, as shown in
Figure 4.3.

FORCES If you find that an object needs to be a different subclass of a class at different
times, then it should not be a subclass of that class in the first place.
If an object is created as an instance of a class, it will always be an
instance of that class. On the other hand, an object can delegate behavior
to different objects at different times.

If you find that a class attempts to hide a method or variable inherited from a superclass from other classes, then that class should not inherit from that subclass. There is no way to effectively hide methods or variables that are inherited from a superclass. On the other hand, it is possible for an object to use the methods and variables of another object while ensuring that it is the only object that has access to the other object. Declaring a class that is related to a program's problem domain as a subclass of a utility class is usually not a good idea for two reasons:

1. When you declare that a class is a subclass of a class such as Vector or Hashtable, you run the risk that these classes that you do not control will change in an incompatible way in the future. Though it's a low risk, there is usually no corresponding benefit to offset it.
2. When people write a problem-domain-specific class as a subclass of a utility class, the intent is usually to use the functionality of the utility class to implement problem-domain-specific functionality. The problem is that it weakens the encapsulation of the problem domain class's implementation.

Client classes that use the problem domain class can be written in a way that assumes the problem domain class is a subclass of the utility class. If the implementation of the problem domain changes in a way that results in its having a different super-class those client classes that rely on its original superclass will break.

An even more serious problem is that client classes can call the public methods of the utility superclass, which defeats its encapsulation.

Some inappropriate uses of inheritance are so common that they can be classified as AntiPatterns. In particular, subclassing utility classes and using inheritance to model roles are common design flaws. Many or possibly most reuse situations and extensions of a class are not appropriately done through inheritance.
By determining its superclass, a class's declaration determines the behavior that a class inherits from its superclass. Inheritance is not useful when the behavior that a class builds on is determined at runtime.

SOLUTION Delegation is a way to reuse and extend class behavior. It works by writing a new class that incorporates the functionality of the original class by using an instance of the original class and calling its methods, as shown in Figure 4.4. The diagram in Figure 4.4 shows that a class that is in a Delegator role uses a class in the Delegate role.
Delegation is more general purpose than inheritance. Any extension to a class that can be accomplished by inheritance can also be accomplished by delegation.

CONSEQUENCES Delegation can be used without the problems that accompany inheritance. Another advantage of delegation is that it is easy to compose behavior at runtime.
The main disadvantage of delegation is that it is less structured than inheritance. Relationships between classes built using delegation are less obvious than those built with inheritance. Here are some strategies for improving the clarity of delegation-based relationships:

Use consistent naming schemes to refer to objects in a particular role. For example, if multiple classes delegate the creation of widget objects, the role of the delegate object becomes more obvious if all of the classes that delegate that operation refer to delegate objects through a variable called widgetFactory.
You can always clarify the purpose of a delegation by writing comments.
Follow the Don't Talk to Strangers pattern (described in Volume 2). It states that if a class without a delegation only has an indirect association with another class, then the delegation should be indirect. Do not directly delegate behavior to an indirectly associated class that provides the behavior. Instead, delegate it to a directly associated class and have that class delegate the behavior to the class that provides the behavior. This simplifies the overall design by minimizing the number of associations between objects.
Use well-known design and coding patterns. A person reading code that uses delegation will be more likely to understand the role that the objects play if the roles are part of a well-known pattern or a pattern that recurs frequently in your program.

Note that it's possible and advantageous to use all of these strategies at the
same time.

IMPLEMENTATION The implementation of delegation is very straightforward. It simply involves the acquisition of a reference to an instance of the class to which you want to delegate and call its methods.

JAVA API USAGE The Java API is full of examples of delegation. It's the basis for Java's delegation event model. In that model, event source objects send events to event listener objects. Event source objects don't generally decide what to do with an event. Instead they delegate the responsibility for processing the event to listener objects.

CODE EXAMPLE For an example of delegation, we look at another part of an airline reservation system. Suppose the reservation system is responsible for keeping track of checked pieces of luggage. We can expect this part of the system to include classes to represent a flight segment,* a luggage compartment, and pieces of luggage, as shown in Figure 4.5.
In Figure 4.5, the FlightSegment class has a method called checkLuggage that checks a piece of luggage onto a flight. The flight class delegates that operation to an instance of the LuggageCompartment class. Another common use for delegation is to implement a collection. Consider the class diagram in Figure 4.6. A class such as LuggageCompartment that maintains a collection of other objects normally delegates that collection to another object such as an instance of java. util. Vector. Because implementing a collection with delegation is so common, the separate collection class is usually omitted from design drawings.
Here are code fragments that implement the design shown in Figures 4.5 and 4.6. First, let's look at the FlightSegment class that delegates the checkLuggage operation to the LuggageCompartment class:

class FlightSegment {
...
LuggageCompartment luggage;
...
void checkLuggage( Luggage piece) throws LuggageException {
luggage. checkLuggage( piece);
}
// checkLuggage( Luggage)
} // class FlightSegment

Here is the LuggageCompartment class that delegates the collection
of pieces of luggage to the Vector class:

class LuggageCompartment {
...
// The pieces of luggage in this LuggageCompartment
private Vector pieces = new Vector();
...
void checkLuggage( Luggage piece) throws LuggageException {
...
pieces. addElement( piece);
}
// checkLuggage( Luggage)
} // class LuggageCompartment

<%%>FlightSegment 1: checkLuggage( ) :LuggageCompartment 1.1: checkLuggage( )

*A flight segment is a portion of a trip that you take on an airline without changing planes.

RELATED PATTERNS Almost every other pattern uses delegation. Some of the patterns that rely most clearly on delegation are the Decorator pattern and the Proxy pattern.

SYNOPSIS Keep a class that uses data and services provided by instances of other classes independent of those classes by having it access those instances through an interface.

CONTEXT Suppose that you are writing an application to manage the purchase of goods for a business. Among the entities your program needs information about are vendors, freight companies, receiving locations, and billing locations. One thing these entities have in common is that they all have street addresses. These street addresses appear in different parts of the user interface. You want to have a class that can display and edit street addresses. This will ensure that you can reuse it wherever there is an address in the user interface. Let's call that class AddressPanel.
You want AddressPanel objects to be able to retrieve and set address information in a separate data object. That raises the question of what instances of the AddressPanel class can assume about the class of the data objects that will be with them. Clearly, you should use different classes to represent vendors, freight companies, and the like. If you program in a language like C++ that supports multiple inheritance, you can arrange for the data objects that instances of AddressPanel use to inherit from an address class in addition to the other classes they inherit from. If you program in a language like Java that uses a single inheritance object model, then you must explore other solutions.
You can solve the problem by creating an address interface. Then instances of the AddressPanel class simply require data objects that implement the address interface. They can then call the accessor methods declared by the interface and set the object's address information. Using the indirection that the interface provides, instances of the AddressPanel are able to call the methods of the data object without knowing what class it belongs to. Figure 4.7 is a class diagram that shows these relationships.

FORCES n If the instances of a class must use another object and that object is assumed to belong to a particular class, then the reusability of the class is compromised.
Suppose that instances of a class use other objects and all that they require of those objects is that they implement certain methods. You can limit the class's dependency to just this requirement by defining an interface that has just those methods and designing the class to use the interface.

SOLUTION To avoid the coupling of classes because one uses the other, make the usage indirect through an interface. Figure 4.8 shows this organization. Here are the roles that these classes and the interface play.

Client The Client class uses other classes that implement the IndirectionIF interface.

IndirectionIF The IndirectionIF interface provides the indirection that keeps the Client class independent of the class that is in the Service role.

CONSEQUENCES Applying the Interface pattern keeps a class that needs a service from another class from being coupled to any specific class. Like any other indirection, the Interface pattern can make a program more difficult to understand.

IMPLEMENTATION Implementation of the Interface pattern is straightforward: Define an interface to provide a service, write client classes to access the service through the interface, and write classes that provide the service to implement the interface.

JAVA API USAGE The Java API defines the interface java. io. FilenameFilter. That interface declares a method that you can use to decide if a named file is included in a collection. The Java API also defines the java. awt .FileDialog class that can use a FilenameFilter object to filter the files that it displays. You can pass the list method of the java. io. File class a FilenameFilter object to filter the files that it puts in the array that it returns.

CODE EXAMPLE The example for the Interface pattern is the AddressPanel class and AddressIF interface discussed under the Context heading. Here is code for the AddressPanel class:

class AddressPanel extends Panel {
private AddressIF data; // Data object

...
/**
* Save the contents of the TextFields into the data object.
*/
public void save() {
if (data != null) {
data. setAddress1( address1Field. getText());
...
data. setPostalCode( postalCodeField. getText());
} // if data
} // save()
} // class AddressPanel

Notice that the Interface pattern only manifests itself in the fact that the AddressPanel class declares its data instance variable as an interface type.
The heart of the Interface pattern is the interface that provides the indirection between the client class and the service class. Here is the code for the AddressIF interface that provides that indirection for the
AddressPanel class:

public interface AddressIF {
public String getAddress1();
public void setAddress1( String address1);
...
public String getPostalCode() ;
public void setPostalCode( String PostalCode);
}
// interface AddressIF

The interface simply declares the methods required for the needed service. Finally, here is code for the service class. The only impact that the Interface pattern has on the class is that it implements the AddressIF interface.

class ReceivingLocation extends Facility implements AddressIF{
private String address1;
private String postalCode;
...
public String getAddress1() { return address1; }
public void setAddress1( String address1) {
this. address1 = address1;
}
...
public String getPostalCode() { return postalCode; }
public void setPostalCode( String postalCode) {
this. postalCode = postalCode;

} // setPostalCode( String)
} // class ReceivingLocation

RELATED PATTERNS
Delegation
The Delegation and Interface patterns are often used together.

Many other patterns use the Interface pattern.

The Immutable pattern is fundamental in a different sense from the other patterns presented in this chapter. The Immutable pattern is considered fundamental because the more appropriate places you use it, the more robust and maintainable your programs will be.

SYNOPSIS The Immutable pattern increases the robustness of objects that share references to the same object and reduces the overhead of concurrent access to an object. It accomplishes this by forbidding any of an object's state information to change after the object is constructed. The Immutable pattern also avoids the need to synchronize multiple threads of execution that share an object.

CONTEXT The Immutable pattern is useful in a great variety of contexts. What these contexts have in common is that they use instances of a class that are shared by multiple objects and whose states are fetched more often than changed.
In situations where multiple objects share access to the same object, a problem can arise if changes to the shared object are not properly coordinated between the objects that share it. That can require careful programming that is easy to get wrong. If the changes to and fetches of the shared object's state are done asynchronously, then, in addition to the greater likelihood of bugs, correctly functioning code will have the over-head of synchronizing the accesses to the shared object's state. The Immutable pattern avoids these problems. It organizes a class so that the state information of its instances never changes after they are constructed.

Suppose that you are writing a game program that involves the placement
and occasional movement of objects on a playing field. In the course
of designing the classes for that program, you decide that you want to use
immutable objects to represent the position of objects on the playing field.
The organization of a class for modeling a position that way might look
like Figure 4.9.
In Figure 4.9, a class called Position has x and y values associated with its instances. The class has a constructor that specifies the x and y values. It also has methods to fetch the x and y values associated with its instances. Last, it has a method that creates a new Position object that is given an x and y offset from an existing position. It does not have any methods to modify its own x or y value.

FORCES n Your program uses instances of a class that are passive in nature. The instances don't ever need to change their own state. The instances of that class are used by multiple other objects. n Correctly coordinating changes to the state information of an object used by multiple other objects is difficult and bug prone, even if the changes are sequential and not concurrent. When the state of such an object changes, all the objects that use it may need to be informed. Also, when multiple objects use an object, they may attempt to change its state in inconsistent ways. n
If access to a shared object's state information involves multiple threads and modifications of its state information, then the threads that access the state information must be synchronized in order to ensure consistency. n
The overhead of synchronizing the threads may add an unacceptable overhead to accessing the shared object's state information.

SOLUTION To avoid having to manage the propagation and synchronization of changes to the state information of objects used by multiple other objects, make the shared objects immutable, disallowing any changes to their state after they are constructed. You can accomplish that by not including any methods, other than constructors, in their class that modify state information. You can organize such a class like that shown in Figure 4.10.
Notice that the class has accessor methods to retrieve state information but not to set it.

CONSEQUENCES Since the state of immutable objects never changes, there is no need to write code to manage such changes. Also, there is no need to synchronize threads that access immutable objects.
Operations that would otherwise have changed the state of an object must create a new object. Mutable objects do not incur this overhead.

IMPLEMENTATION There are two concerns to be aware of when you implement the Immutable pattern:
1. No method, other than a constructor, should modify the values of a class's instance variables.
2. Any method that computes new state information must store that information in a new instance of the same class, rather than modify the existing object's state.

One possible, unexpected detail for implementing the Immutable pattern is that it usually does not involve the declaration of variables with the final modifier. The values of final instance variables are normally provided from within their class. However, the values of an immutable object's instance variables normally are provided by another class that instantiates the object.
A common variation on the Immutable pattern is called the Read Only Object. The Immutable pattern cannot be used if there is even one other class that needs to modify instances of a class after they are created. To get most of the robustness that the Immutable pattern provides, you can define a read-only interface that most other classes can use to access the class's instances. The class diagram in Figure 4.11 shows the organization for Read Only Object.
In the Read Only Object diagram, the Foo class has accessor methods to retrieve and set the values of its attributes. The ReadOnlyFooIF interface has the same get methods as the Foo class, which implements the interface. The interface does not include any of the Foo class's set methods.
Some clients of the Foo class, such as the MutatorClient class, use the Foo class directly and call its set methods. Other classes, such as the Client class, access the Foo class indirectly through the ReadOnlyFooIF interface. Classes that access the Foo class through the ReadOnlyFooIF interface are not able to access its set methods.

JAVA API USAGE Instances of the String class are immutable. The sequence of characters
that a String object represents is determined when it is constructed. The
String class does not provide any methods to change the sequence of
characters represented by a String object. Methods of the String class, such as toLowerCase and substring, that compute a new sequence of characters return the new sequence of characters in a new String object.

CODE EXAMPLE Here is what the declaration for the Position class described under the Context heading looks like:
class Position {
private int x;
private int y;

public Position( int x, int y) {
this. x = x;
this. y = y;
}
// Position( int, int)

public int getX() { return x; }
public int getY() { return y; }
public Position offset( int xOffset, int yOffset) {
return new Position( x+ xOffset, y+ yOffset);
}
// offset( int, int)
} // class Position

RELATED PATTERNS
Single Threaded Execution
The Single Threaded Execution pattern is the pattern most frequently used to coordinate access by multiple threads to a shared object. The Immutable pattern can be used to avoid the need for the Single Threaded Execution pattern or any other kind of access coordination.
The Marker Interface pattern occurs rarely outside of utility classes. However, it's included in this chapter because it takes advantage of the fundamental nature of class declarations.

SYNOPSIS The Marker Interface pattern uses interfaces that declare no methods or variables to indicate semantic attributes of a class. It works particularly well with utility classes that must determine something about objects with-out assuming they are an instance of any particular class.

CONTEXT Java's Object class defines a method called equals that takes an argument that can be a reference to any object. Since Java's Object class is the ultimate superclass of all other classes in Java, all other classes inherit the equals method from the Object class. The implementation of equals provided by the Object class returns true if the object passed to it is the same object as the object it's associated with. Classes that want their instances considered equal if they contain the same values override the equals method appropriately.
Container objects, such as java. util. Vector, call an object's equals method when performing a search of their contents to find an object that is equal to a given object. Such searches might call an object's equals method for each object in the container objects. This is wasteful in those cases where the object searched for belongs to a class that does not override the equals method. It's faster to use the == operator to determine if two objects are the same object instead of calling the Object class's implementation of the equals method. If the container class is able to determine that the object searched for belongs to a class that does not override the equals method, then it can use the == operator instead of calling equals. The problem with this approach is that there is no way to determine if an arbitrary object's class overrides the equals method.
It is possible to provide container classes with a hint to let them know that it's correct to use the == operator for an equality test on instances of a class. You can define an interface called EqualByIdentity that declares no methods or variables. You can then write container classes to assume that if a class implements EqualByIdentity, then the equality comparison is done with the == operator.
An interface that does not declare methods or variables and is used to indicate attributes of classes that implement them is said to be a marker interface.

FORCES n Utility classes may need to know something about the intended use of an object's class without relying on an object being an instance of a particular class.

Classes can implement any number of interfaces

It's possible to determine if an object's class implements a known interface without relying on the object being an instance of any particular class.

SOLUTION When a utility class needs to determine if another class's instances are included in a classification without the utility class knowing of other classes, it can determine if other classes implement a marker interface. As stated previously, a marker interface is an interface that does not declare any methods or variables. You declare that a class implements a marker interface to indicate that it belongs to the classification associated with the marker interface.
These relationships are shown in Figure 4.12.
Figure 4.13 shows a diagram that contains a marker interface called
MarkerIF. There is a class called Marked that implements MarkerIF and a class called Unmarked that doesn't. There is also a utility class called Utility that is aware of the MarkerIF interface. Instances of UtilityClass receive calls to their operation1 method. The parameter passed to that method can be an object that implements or does not implement MarkerIF.

CONSEQUENCES Instances of utility classes are able to make inferences about objects passed to their methods without depending on the objects to be instances of any particular class.
The relationship between the utility class and the marker interface is transparent to all other classes except for those classes that implement the interface.

IMPLEMENTATION The essence of the Marker Interface pattern is that an object that either does or does not implement a marker interface is passed to a method of a utility class. The formal parameter that corresponds to that object is typically declared as Object. It is sometimes appropriate to declare that formal parameter to be a more specialized class.
It is also possible to use an interface that declares methods in the Marker Interface method. In such cases, the interface used as a marker interface usually extends an interface that declares methods.
Declaring that a class implements a marker interface implies that the class is included in the classification implied by the interface. It also implies that all subclasses of that class are included in the classification. If there is any possibility that someone will declare a subclass that does not fit the classification, then you should take measures to prevent that from happening. Such measures might include declaring the class final to prevent it from being subclassed, or its equals method to be final to prevent it from being overridden.

JAVA API USAGE A class indicates that its instances may be serialized by implementing the Serializable interface. Instances of the ObjectOutputstream class write objects as a stream of bytes that an instance of the ObjectInputStream class can read and turn back into an object. The conversion of an object to a stream of bytes is called serialization. There are a number of reasons why instances of some classes should not be serialized. Because of that, the ObjectOutputstream class refuses to serialize objects unless their class implements the Serializable interface to indicate that its serialization is allowed.

CODE EXAMPLE For an example of an application of the Marker Interface pattern, see the following class that implements a linked list data structure. At the bottom of the listing, you will see methods called find, findEq, and findEquals. The purpose of all three methods is to find a LinkedList node that refers to a specified object. The find method is the only one of the three that is public. The findEq method performs the necessary equality tests using the == operator. The findEquals method performs the necessary equality tests using the equals method of the object being searched for. The find method decides which of the other two methods to call by determining if the object to search for implements the marker interface EqualByIdentity.

public class LinkedList implements Cloneable, java. io. Serializable {
...
/**
* Find an object in a linked list that is equal to the given
* object. Equality is normally determined by calling the given
* object's equals method. However, if the given object
* implements the EqualByIdentity interface, then equality will be
* determined by the == operator.
*/

public LinkedList find( Object target) {
if (target == null || target instanceof EqualByIdentity)
return findEq( target);
else
return findEquals( target);
} // find( Object)

/**
* Find an object in a linked list that is equal to the given
* object. Equality is determined by the == operator.
*/
private synchronized LinkedList findEq( Object target) {
...
} // find( Object)

/**
* Find an object in a linked list that is equal to the given
* object. Equality is determined by calling the given
* object's equals method.
*/
private synchronized LinkedList findEquals( Object target) {
...
} // find( Object)
} // class LinkedList

RELATED PATTERNS
Snapshot
The Marker Interface pattern is used by the Snapshot pattern to allow serialization of objects.
SYNOPSIS Proxy is a very general pattern that occurs in many other patterns, but never by itself in its pure form. The Proxy pattern forces method calls to an object to occur indirectly through a proxy object that acts as a surrogate for the other object, delegating method calls to that object. Classes for proxy objects are declared in a way that usually eliminates client objects' awareness that they are dealing with a proxy.

CONTEXT A proxy object is an object that receives method calls on behalf of another object. Client objects call the proxy object's methods. The proxy object's methods do not directly provide the service that its clients expect. Instead, the proxy object's methods call the methods of the object that provides the actual service. Figure 4.14 shows a diagram of that structure.
Though a Proxy object's methods don't directly provide the service that its clients expect, the Proxy object provides some management of those services. Proxy objects generally share a common interface or superclass with the service-providing object. That makes it possible for client objects to be unaware that they are calling the methods of a proxy object rather than the methods of the actual service-providing object. Transparent management of another object's services is the basic reason for using a proxy.
There are many different types of service management that a proxy can be used to provide. Some of the more important ones are documented elsewhere in this book as patterns in their own right. Here are some of the more common uses for proxies:

A proxy makes a method that can take a long time to complete appear to return immediately.
nA proxy creates the illusion that an object that exists on a different machine is an ordinary local object. This kind of proxy is called a remote proxy. It is used by Remote Method Invocation (RMI). n
A proxy controls access to a service-providing object. This kind of proxy is called an access proxy. A proxy creates the illusion that a service object exists before it actually
does. This can be useful if a service object is expensive to create and its services are not needed. This use of proxies is documented as the Virtual Proxy pattern.

FORCES It is not possible for a service-providing object to provide a service at a time or place that is convenient. n
Gaining visibility to an object is nontrivial and you want to hide that complexity.
Access to a service-providing object must be controlled without adding complexity to the service-providing object or coupling the service to the access control policy.
The management of a service should be provided in a way that is as transparent as possible to the clients of that service.

SOLUTION Transparent management of a service-providing object can be accomplished by forcing all access to the service-providing object through a proxy object. In order for the management to be transparent, the proxy object and the service-providing object must either be instances of a common super-class or implement a common interface, as shown in Figure 4.15.
By referring to the superclass or interface that is common to both the proxy and service providing classes, client classes avoid having to care which is the actual class that they refer to at run time.
Figure 4.15 does not show any details for implementing any particular service management policy. However, the Proxy pattern is not very useful unless it implements some particular service management policy. The Proxy pattern is so commonly used with some service management policies that the combinations are described elsewhere as patterns in their own right.

CONSEQUENCES The service provided by a service-providing object is managed in a manner transparent to that object and its clients.
Unless the use of proxies introduces new failure modes, there is normally no need for the code of client classes to reflect the use of proxies.

IMPLEMENTATION Without any specific management policy, the implementation of the Proxy pattern simply involves creating a class that shares a common superclass or interface with a service-providing class and delegates operations to instances of the service-providing class.

CODE EXAMPLE The Proxy pattern is not useful in its pure form. It must be combined with a service management behavior to accomplish anything useful. The example for the Proxy pattern uses proxies to defer an expensive operation until it is actually needed. If the operation is not needed, the operation is never performed.
The example is a subclass of java. util. Hashtable that is functionally equivalent to Hashtable. The difference is the way that it handles the clone operation. A Hashtable object's clone method returns a new Hashtable object that contains all the same things as the original Hashtable object. Cloning a Hashtable is an expensive operation. One of the more common reasons for cloning an object like a Hashtable is to avoid holding a lock on the object for a long time when all that is desired is to fetch multiple key-value pairs. In a multithreaded program, to ensure that a Hashtable is in a consistent state when you are fetching key-value pairs from it, you can use a synchronized method to obtain exclusive access to the Hashtable. While that is going on, other threads will wait to gain access to the same Hashtable, which may be unacceptable. In some other cases it may not be possible to retain exclusive access. An example of that is the Enumeration object returned by the Hashtable class's elements object.
Cloning a Hashtable prior to fetching values out of it is a defensive measure. Cloning the Hashtable avoids the need to obtain a synchronization lock on a Hashtable beyond the time that it takes for the clone operation to complete. When you have a freshly cloned copy of a Hashtable, you can be sure that no other thread has access to the copy. Since no other thread has access to the copy, you will be able to fetch key-value pairs from the copy without any interference with other threads.
If, after you clone a Hashtable, there is no subsequent modification to the original Hashtable, then the time and memory spent in creating the clone was wasted. The point of this example is to avoid that waste. It does this by delaying the cloning of a Hashtable until a modification to it actually occurs.
The main class in the example is LargeHashtable. Instances of LargeHashtable are a copy-on-write proxy for a Hashtable object. When a proxy's clone method is called, it returns a copy of the proxy but does not copy the Hashtable object. At this point, both the original and the copy of the proxy refer to the same Hashtable object. When either of the proxies is asked to modify the Hashtable, they recognize that they are using a shared Hashtable and clone the Hashtable before they make the modification.

The way the proxies know that they are working with a shared Hashtable object is that the Hashtable object that the proxies work with is an instance of a private subclass of Hashtable called ReferenceCountedHashTable. A ReferenceCountedHashTable object keeps a count of how many proxies refer to it.

public class LargeHashtable extends Hashtable {
// The ReferenceCountedHashTable that this is a proxy for.
private ReferenceCountedHashTable theHashTable;

...
public LargeHashtable() {
theHashTable = new ReferenceCountedHashTable();
} // constructor()

/**
* Return the number of key-value pairs in this hashtable.
*/
public int size() {
return theHashTable. size();
}
// size()
...
/**
* Return the value associated with the specified key in this
* Hashtable.
*/
public synchronized Object get( Object key) {
return theHashTable. get( key);
}
// get( key)

/**
* Add the given key-value pair to this Hashtable.
*/
public synchronized Object put( Object key, Object value) {
copyOnWrite();
return theHashTable. put( key, value);
}
// put( key, value)
...
/**
* Return a copy of this proxy that accesses the same Hashtable as this
* proxy. The first attempt for either to modify the
* contents of the Hashtable results in that proxy accessing a
* modified clone of the original Hashtable.
*/
public synchronized Object clone() {
Object copy = super. clone();
theHashTable. addProxy();
return copy;
}
// clone()

/**
* This method is called before modifying the underlying
* Hashtable. If it
* is being shared, then this method clones it.
*/
private void copyOnWrite() {
if (theHashTable. getProxyCount() > 1) {
// Synchronize on the original Hashtable to allow
// consistent recovery on error.
synchronized (theHashTable) {

theHashTable. removeProxy();
try {
theHashTable
= (ReferenceCountedHashTable)
theHashTable. clone();
} catch (Throwable e) {
theHashTable. addProxy();
} // try
}
// synchronized
} // if proxyCount
} // copyOnWrite()
...
private class ReferenceCountedHashTable extends Hashtable {
private int proxyCount = 1;
...
public ReferenceCountedHashTable() {
super();
} // constructor()
/**
* Return a copy of this object with proxyCount set to 1.
*/
public synchronized Object clone() {
ReferenceCountedHashTable copy;
copy = (ReferenceCountedHashTable) super. clone();
copy. proxyCount = 1;
return copy;
}
// clone()

/**
* Return the number of proxies using this object.
*/
synchronized int getProxyCount() {
return proxyCount;
}
// getProxyCount()

/**
* Increment the number of proxies using this object by one.
*/
synchronized void addProxy() {
proxyCount++;
}
// addProxy()

/**
* Decrement the number of proxies using this object by one.
*/
synchronized void removeProxy() {
proxyCount--;
}
// removeProxy()
} // class ReferenceCountedHashTable
} // class LargeHashtable

RELATED PATTERNS
Access Proxy
The Access Proxy pattern uses a proxy to enforce a security policy on access to a service-providing object. Access Proxy is not documented in this work.

Broker The Proxy pattern is sometimes used with the Broker pattern to provide a transparent way of forwarding service requests to a service object selected by the Broker/ Proxy object. The Broker pattern is not documented in this work.

Facade The facade pattern uses a single object as a front end to a set of interrelated objects.

Remote Proxy The Remote Proxy pattern uses a proxy to hide the fact that a service object is located on a different machine from the client objects that want to use it. The Remote Proxy pattern is not documented in this work.

Virtual Proxy This pattern uses a proxy to create the illusion that a service- providing object exists before it has actually been created. It is useful if the object is expensive to create and its services may not be needed. The copy-on-write proxy discussed under the "Code Example" heading for the Proxy pattern is a kind of virtual proxy.

Decorator The Decorator pattern is structurally similar to the Proxy pattern in that it forces access to a service-providing object to be done indirectly through another object. The difference is a matter of intent. Instead of trying to manage the service, the indirection object in some way enhances the service.

Chapter 7

Read More Show Less

Table of Contents

Introduction to Software Patterns.
Overview of UML.
The Software Life Cycle.
Fundamental Design Patterns.
Creational Patterns.
Partitioning Patterns.
Structural Patterns.
Behavioral Patterns.
Concurrency Patterns.
Bibliography.
Appendix.
Index.
Read More Show Less

First Chapter

Patterns of Java, Volume 1

Mark Grand ISBN: 0471258393

Note: The Figures and/or Tables mentioned in this sample chapter do not appear on the Web. C H A P T E R 4
Fundamental Design Patterns

Delegation: When not to use inheritance (53)
Interface (61)
Immutable (67)
Marker Interface (73)
Proxy (79)

The patterns in this chapter are the most fundamental and important design patterns to know. You will find these patterns used extensively in other design patterns.

SYNOPSIS Delegation is a way to extend and reuse the functionality of a class by writing an additional class with added functionality that uses instances of the original class to provide the original functionality.

CONTEXT Inheritance is a common way to extend and reuse the functionality of a class. Delegation is a more general way for extending a class's behavior that involves a class calling another class's methods rather than inheriting them. Inheritance is inappropriate for many situations that delegations are appropriate for.
For example, inheritance is useful for capturing "is-a-kind-of" relationships because these types of relationships are very static in nature. However, "is-a-role-played-by" relationships are awkward to model by inheritance. Instances of a class can play multiple roles. Let's look at an example of an airline reservation system. This airline reservation system includes such roles as passenger, ticket selling agent, and flight crew. It's possible to represent this as a class called Person that has subclasses corresponding to these roles, as shown in Figure 4.1.
The problem with the diagram depicted in Figure 4.1 is that the same person can fill more than one of these roles. A person who is normally part of a flight crew can also be a passenger. Some airlines occasionally float the flight crew to the ticket counter. This means that the same person can fill any combination of these roles. To model this situation, you need 7 subclasses for Person, as shown in Figure 4.2. The number of subclasses needed increases exponentially with the number of roles. Therefore, you need 63 subclasses to model 6 roles.
A more serious problem is that the same person can play different combinations of roles at different times. Inheritance is a static relationship that does not change over time. Using inheritance necessitates using multiple objects to represent the same person in order to capture changes in role.

On the other hand, it's possible to represent persons in different
roles using delegation without having any of those problems, as shown in
Figure 4.3.

FORCES If you find that an object needs to be a different subclass of a class at different
times, then it should not be a subclass of that class in the first place.
If an object is created as an instance of a class, it will always be an
instance of that class. On the other hand, an object can delegate behavior
to different objects at different times.

If you find that a class attempts to hide a method or variable inherited from a superclass from other classes, then that class should not inherit from that subclass. There is no way to effectively hide methods or variables that are inherited from a superclass. On the other hand, it is possible for an object to use the methods and variables of another object while ensuring that it is the only object that has access to the other object. Declaring a class that is related to a program's problem domain as a subclass of a utility class is usually not a good idea for two reasons:

1. When you declare that a class is a subclass of a class such as Vector or Hashtable, you run the risk that these classes that you do not control will change in an incompatible way in the future. Though it's a low risk, there is usually no corresponding benefit to offset it.
2. When people write a problem-domain-specific class as a subclass of a utility class, the intent is usually to use the functionality of the utility class to implement problem-domain-specific functionality. The problem is that it weakens the encapsulation of the problem domain class's implementation.

Client classes that use the problem domain class can be written in a way that assumes the problem domain class is a subclass of the utility class. If the implementation of the problem domain changes in a way that results in its having a different super-class those client classes that rely on its original superclass will break.

An even more serious problem is that client classes can call the public methods of the utility superclass, which defeats its encapsulation.

Some inappropriate uses of inheritance are so common that they can be classified as AntiPatterns. In particular, subclassing utility classes and using inheritance to model roles are common design flaws. Many or possibly most reuse situations and extensions of a class are not appropriately done through inheritance.
By determining its superclass, a class's declaration determines the behavior that a class inherits from its superclass. Inheritance is not useful when the behavior that a class builds on is determined at runtime.

SOLUTION Delegation is a way to reuse and extend class behavior. It works by writing a new class that incorporates the functionality of the original class by using an instance of the original class and calling its methods, as shown in Figure 4.4. The diagram in Figure 4.4 shows that a class that is in a Delegator role uses a class in the Delegate role.
Delegation is more general purpose than inheritance. Any extension to a class that can be accomplished by inheritance can also be accomplished by delegation.

CONSEQUENCES Delegation can be used without the problems that accompany inheritance. Another advantage of delegation is that it is easy to compose behavior at runtime.
The main disadvantage of delegation is that it is less structured than inheritance. Relationships between classes built using delegation are less obvious than those built with inheritance. Here are some strategies for improving the clarity of delegation-based relationships:

Use consistent naming schemes to refer to objects in a particular role. For example, if multiple classes delegate the creation of widget objects, the role of the delegate object becomes more obvious if all of the classes that delegate that operation refer to delegate objects through a variable called widgetFactory.
You can always clarify the purpose of a delegation by writing comments.
Follow the Don't Talk to Strangers pattern (described in Volume 2). It states that if a class without a delegation only has an indirect association with another class, then the delegation should be indirect. Do not directly delegate behavior to an indirectly associated class that provides the behavior. Instead, delegate it to a directly associated class and have that class delegate the behavior to the class that provides the behavior. This simplifies the overall design by minimizing the number of associations between objects.
Use well-known design and coding patterns. A person reading code that uses delegation will be more likely to understand the role that the objects play if the roles are part of a well-known pattern or a pattern that recurs frequently in your program.

Note that it's possible and advantageous to use all of these strategies at the
same time.

IMPLEMENTATION The implementation of delegation is very straightforward. It simply involves the acquisition of a reference to an instance of the class to which you want to delegate and call its methods.

JAVA API USAGE The Java API is full of examples of delegation. It's the basis for Java's delegation event model. In that model, event source objects send events to event listener objects. Event source objects don't generally decide what to do with an event. Instead they delegate the responsibility for processing the event to listener objects.

CODE EXAMPLE For an example of delegation, we look at another part of an airline reservation system. Suppose the reservation system is responsible for keeping track of checked pieces of luggage. We can expect this part of the system to include classes to represent a flight segment,* a luggage compartment, and pieces of luggage, as shown in Figure 4.5.
In Figure 4.5, the FlightSegment class has a method called checkLuggage that checks a piece of luggage onto a flight. The flight class delegates that operation to an instance of the LuggageCompartment class. Another common use for delegation is to implement a collection. Consider the class diagram in Figure 4.6. A class such as LuggageCompartment that maintains a collection of other objects normally delegates that collection to another object such as an instance of java. util. Vector. Because implementing a collection with delegation is so common, the separate collection class is usually omitted from design drawings.
Here are code fragments that implement the design shown in Figures 4.5 and 4.6. First, let's look at the FlightSegment class that delegates the checkLuggage operation to the LuggageCompartment class:

class FlightSegment {
...
LuggageCompartment luggage;
...
void checkLuggage( Luggage piece) throws LuggageException {
luggage. checkLuggage( piece);
}
// checkLuggage( Luggage)
} // class FlightSegment

Here is the LuggageCompartment class that delegates the collection
of pieces of luggage to the Vector class:

class LuggageCompartment {
...
// The pieces of luggage in this LuggageCompartment
private Vector pieces = new Vector();
...
void checkLuggage( Luggage piece) throws LuggageException {
...
pieces. addElement( piece);
}
// checkLuggage( Luggage)
} // class LuggageCompartment

:FlightSegment 1: checkLuggage( ) :LuggageCompartment 1.1: checkLuggage( )

*A flight segment is a portion of a trip that you take on an airline without changing planes.

RELATED PATTERNS Almost every other pattern uses delegation. Some of the patterns that rely most clearly on delegation are the Decorator pattern and the Proxy pattern.

SYNOPSIS Keep a class that uses data and services provided by instances of other classes independent of those classes by having it access those instances through an interface.

CONTEXT Suppose that you are writing an application to manage the purchase of goods for a business. Among the entities your program needs information about are vendors, freight companies, receiving locations, and billing locations. One thing these entities have in common is that they all have street addresses. These street addresses appear in different parts of the user interface. You want to have a class that can display and edit street addresses. This will ensure that you can reuse it wherever there is an address in the user interface. Let's call that class AddressPanel.
You want AddressPanel objects to be able to retrieve and set address information in a separate data object. That raises the question of what instances of the AddressPanel class can assume about the class of the data objects that will be with them. Clearly, you should use different classes to represent vendors, freight companies, and the like. If you program in a language like C++ that supports multiple inheritance, you can arrange for the data objects that instances of AddressPanel use to inherit from an address class in addition to the other classes they inherit from. If you program in a language like Java that uses a single inheritance object model, then you must explore other solutions.
You can solve the problem by creating an address interface. Then instances of the AddressPanel class simply require data objects that implement the address interface. They can then call the accessor methods declared by the interface and set the object's address information. Using the indirection that the interface provides, instances of the AddressPanel are able to call the methods of the data object without knowing what class it belongs to. Figure 4.7 is a class diagram that shows these relationships.

FORCES n If the instances of a class must use another object and that object is assumed to belong to a particular class, then the reusability of the class is compromised.
Suppose that instances of a class use other objects and all that they require of those objects is that they implement certain methods. You can limit the class's dependency to just this requirement by defining an interface that has just those methods and designing the class to use the interface.

SOLUTION To avoid the coupling of classes because one uses the other, make the usage indirect through an interface. Figure 4.8 shows this organization. Here are the roles that these classes and the interface play.

Client The Client class uses other classes that implement the IndirectionIF interface.

IndirectionIF The IndirectionIF interface provides the indirection that keeps the Client class independent of the class that is in the Service role.

CONSEQUENCES Applying the Interface pattern keeps a class that needs a service from another class from being coupled to any specific class. Like any other indirection, the Interface pattern can make a program more difficult to understand.

IMPLEMENTATION Implementation of the Interface pattern is straightforward: Define an interface to provide a service, write client classes to access the service through the interface, and write classes that provide the service to implement the interface.

JAVA API USAGE The Java API defines the interface java. io. FilenameFilter. That interface declares a method that you can use to decide if a named file is included in a collection. The Java API also defines the java. awt .FileDialog class that can use a FilenameFilter object to filter the files that it displays. You can pass the list method of the java. io. File class a FilenameFilter object to filter the files that it puts in the array that it returns.

CODE EXAMPLE The example for the Interface pattern is the AddressPanel class and AddressIF interface discussed under the Context heading. Here is code for the AddressPanel class:

class AddressPanel extends Panel {
private AddressIF data; // Data object

...
/**
* Save the contents of the TextFields into the data object.
*/
public void save() {
if (data != null) {
data. setAddress1( address1Field. getText());
...
data. setPostalCode( postalCodeField. getText());
} // if data
} // save()
} // class AddressPanel

Notice that the Interface pattern only manifests itself in the fact that the AddressPanel class declares its data instance variable as an interface type.
The heart of the Interface pattern is the interface that provides the indirection between the client class and the service class. Here is the code for the AddressIF interface that provides that indirection for the
AddressPanel class:

public interface AddressIF {
public String getAddress1();
public void setAddress1( String address1);
...
public String getPostalCode() ;
public void setPostalCode( String PostalCode);
}
// interface AddressIF

The interface simply declares the methods required for the needed service. Finally, here is code for the service class. The only impact that the Interface pattern has on the class is that it implements the AddressIF interface.

class ReceivingLocation extends Facility implements AddressIF{
private String address1;
private String postalCode;
...
public String getAddress1() { return address1; }
public void setAddress1( String address1) {
this. address1 = address1;
}
...
public String getPostalCode() { return postalCode; }
public void setPostalCode( String postalCode) {
this. postalCode = postalCode;

} // setPostalCode( String)
} // class ReceivingLocation

RELATED PATTERNS
Delegation
The Delegation and Interface patterns are often used together.

Many other patterns use the Interface pattern.

The Immutable pattern is fundamental in a different sense from the other patterns presented in this chapter. The Immutable pattern is considered fundamental because the more appropriate places you use it, the more robust and maintainable your programs will be.

SYNOPSIS The Immutable pattern increases the robustness of objects that share references to the same object and reduces the overhead of concurrent access to an object. It accomplishes this by forbidding any of an object's state information to change after the object is constructed. The Immutable pattern also avoids the need to synchronize multiple threads of execution that share an object.

CONTEXT The Immutable pattern is useful in a great variety of contexts. What these contexts have in common is that they use instances of a class that are shared by multiple objects and whose states are fetched more often than changed.
In situations where multiple objects share access to the same object, a problem can arise if changes to the shared object are not properly coordinated between the objects that share it. That can require careful programming that is easy to get wrong. If the changes to and fetches of the shared object's state are done asynchronously, then, in addition to the greater likelihood of bugs, correctly functioning code will have the over-head of synchronizing the accesses to the shared object's state. The Immutable pattern avoids these problems. It organizes a class so that the state information of its instances never changes after they are constructed.

Suppose that you are writing a game program that involves the placement
and occasional movement of objects on a playing field. In the course
of designing the classes for that program, you decide that you want to use
immutable objects to represent the position of objects on the playing field.
The organization of a class for modeling a position that way might look
like Figure 4.9.
In Figure 4.9, a class called Position has x and y values associated with its instances. The class has a constructor that specifies the x and y values. It also has methods to fetch the x and y values associated with its instances. Last, it has a method that creates a new Position object that is given an x and y offset from an existing position. It does not have any methods to modify its own x or y value.

FORCES n Your program uses instances of a class that are passive in nature. The instances don't ever need to change their own state. The instances of that class are used by multiple other objects. n Correctly coordinating changes to the state information of an object used by multiple other objects is difficult and bug prone, even if the changes are sequential and not concurrent. When the state of such an object changes, all the objects that use it may need to be informed. Also, when multiple objects use an object, they may attempt to change its state in inconsistent ways. n
If access to a shared object's state information involves multiple threads and modifications of its state information, then the threads that access the state information must be synchronized in order to ensure consistency. n
The overhead of synchronizing the threads may add an unacceptable overhead to accessing the shared object's state information.

SOLUTION To avoid having to manage the propagation and synchronization of changes to the state information of objects used by multiple other objects, make the shared objects immutable, disallowing any changes to their state after they are constructed. You can accomplish that by not including any methods, other than constructors, in their class that modify state information. You can organize such a class like that shown in Figure 4.10.
Notice that the class has accessor methods to retrieve state information but not to set it.

CONSEQUENCES Since the state of immutable objects never changes, there is no need to write code to manage such changes. Also, there is no need to synchronize threads that access immutable objects.
Operations that would otherwise have changed the state of an object must create a new object. Mutable objects do not incur this overhead.

IMPLEMENTATION There are two concerns to be aware of when you implement the Immutable pattern:
1. No method, other than a constructor, should modify the values of a class's instance variables.
2. Any method that computes new state information must store that information in a new instance of the same class, rather than modify the existing object's state.

One possible, unexpected detail for implementing the Immutable pattern is that it usually does not involve the declaration of variables with the final modifier. The values of final instance variables are normally provided from within their class. However, the values of an immutable object's instance variables normally are provided by another class that instantiates the object.
A common variation on the Immutable pattern is called the Read Only Object. The Immutable pattern cannot be used if there is even one other class that needs to modify instances of a class after they are created. To get most of the robustness that the Immutable pattern provides, you can define a read-only interface that most other classes can use to access the class's instances. The class diagram in Figure 4.11 shows the organization for Read Only Object.
In the Read Only Object diagram, the Foo class has accessor methods to retrieve and set the values of its attributes. The ReadOnlyFooIF interface has the same get methods as the Foo class, which implements the interface. The interface does not include any of the Foo class's set methods.
Some clients of the Foo class, such as the MutatorClient class, use the Foo class directly and call its set methods. Other classes, such as the Client class, access the Foo class indirectly through the ReadOnlyFooIF interface. Classes that access the Foo class through the ReadOnlyFooIF interface are not able to access its set methods.

JAVA API USAGE Instances of the String class are immutable. The sequence of characters
that a String object represents is determined when it is constructed. The
String class does not provide any methods to change the sequence of
characters represented by a String object. Methods of the String class, such as toLowerCase and substring, that compute a new sequence of characters return the new sequence of characters in a new String object.

CODE EXAMPLE Here is what the declaration for the Position class described under the Context heading looks like:
class Position {
private int x;
private int y;

public Position( int x, int y) {
this. x = x;
this. y = y;
}
// Position( int, int)

public int getX() { return x; }
public int getY() { return y; }
public Position offset( int xOffset, int yOffset) {
return new Position( x+ xOffset, y+ yOffset);
}
// offset( int, int)
} // class Position

RELATED PATTERNS
Single Threaded Execution
The Single Threaded Execution pattern is the pattern most frequently used to coordinate access by multiple threads to a shared object. The Immutable pattern can be used to avoid the need for the Single Threaded Execution pattern or any other kind of access coordination.
The Marker Interface pattern occurs rarely outside of utility classes. However, it's included in this chapter because it takes advantage of the fundamental nature of class declarations.

SYNOPSIS The Marker Interface pattern uses interfaces that declare no methods or variables to indicate semantic attributes of a class. It works particularly well with utility classes that must determine something about objects with-out assuming they are an instance of any particular class.

CONTEXT Java's Object class defines a method called equals that takes an argument that can be a reference to any object. Since Java's Object class is the ultimate superclass of all other classes in Java, all other classes inherit the equals method from the Object class. The implementation of equals provided by the Object class returns true if the object passed to it is the same object as the object it's associated with. Classes that want their instances considered equal if they contain the same values override the equals method appropriately.
Container objects, such as java. util. Vector, call an object's equals method when performing a search of their contents to find an object that is equal to a given object. Such searches might call an object's equals method for each object in the container objects. This is wasteful in those cases where the object searched for belongs to a class that does not override the equals method. It's faster to use the == operator to determine if two objects are the same object instead of calling the Object class's implementation of the equals method. If the container class is able to determine that the object searched for belongs to a class that does not override the equals method, then it can use the == operator instead of calling equals. The problem with this approach is that there is no way to determine if an arbitrary object's class overrides the equals method.
It is possible to provide container classes with a hint to let them know that it's correct to use the == operator for an equality test on instances of a class. You can define an interface called EqualByIdentity that declares no methods or variables. You can then write container classes to assume that if a class implements EqualByIdentity, then the equality comparison is done with the == operator.
An interface that does not declare methods or variables and is used to indicate attributes of classes that implement them is said to be a marker interface.

FORCES n Utility classes may need to know something about the intended use of an object's class without relying on an object being an instance of a particular class.

Classes can implement any number of interfaces

It's possible to determine if an object's class implements a known interface without relying on the object being an instance of any particular class.

SOLUTION When a utility class needs to determine if another class's instances are included in a classification without the utility class knowing of other classes, it can determine if other classes implement a marker interface. As stated previously, a marker interface is an interface that does not declare any methods or variables. You declare that a class implements a marker interface to indicate that it belongs to the classification associated with the marker interface.
These relationships are shown in Figure 4.12.
Figure 4.13 shows a diagram that contains a marker interface called
MarkerIF. There is a class called Marked that implements MarkerIF and a class called Unmarked that doesn't. There is also a utility class called Utility that is aware of the MarkerIF interface. Instances of UtilityClass receive calls to their operation1 method. The parameter passed to that method can be an object that implements or does not implement MarkerIF.

CONSEQUENCES Instances of utility classes are able to make inferences about objects passed to their methods without depending on the objects to be instances of any particular class.
The relationship between the utility class and the marker interface is transparent to all other classes except for those classes that implement the interface.

IMPLEMENTATION The essence of the Marker Interface pattern is that an object that either does or does not implement a marker interface is passed to a method of a utility class. The formal parameter that corresponds to that object is typically declared as Object. It is sometimes appropriate to declare that formal parameter to be a more specialized class.
It is also possible to use an interface that declares methods in the Marker Interface method. In such cases, the interface used as a marker interface usually extends an interface that declares methods.
Declaring that a class implements a marker interface implies that the class is included in the classification implied by the interface. It also implies that all subclasses of that class are included in the classification. If there is any possibility that someone will declare a subclass that does not fit the classification, then you should take measures to prevent that from happening. Such measures might include declaring the class final to prevent it from being subclassed, or its equals method to be final to prevent it from being overridden.

JAVA API USAGE A class indicates that its instances may be serialized by implementing the Serializable interface. Instances of the ObjectOutputstream class write objects as a stream of bytes that an instance of the ObjectInputStream class can read and turn back into an object. The conversion of an object to a stream of bytes is called serialization. There are a number of reasons why instances of some classes should not be serialized. Because of that, the ObjectOutputstream class refuses to serialize objects unless their class implements the Serializable interface to indicate that its serialization is allowed.

CODE EXAMPLE For an example of an application of the Marker Interface pattern, see the following class that implements a linked list data structure. At the bottom of the listing, you will see methods called find, findEq, and findEquals. The purpose of all three methods is to find a LinkedList node that refers to a specified object. The find method is the only one of the three that is public. The findEq method performs the necessary equality tests using the == operator. The findEquals method performs the necessary equality tests using the equals method of the object being searched for. The find method decides which of the other two methods to call by determining if the object to search for implements the marker interface EqualByIdentity.

public class LinkedList implements Cloneable, java. io. Serializable {
...
/**
* Find an object in a linked list that is equal to the given
* object. Equality is normally determined by calling the given
* object's equals method. However, if the given object
* implements the EqualByIdentity interface, then equality will be
* determined by the == operator.
*/

public LinkedList find( Object target) {
if (target == null || target instanceof EqualByIdentity)
return findEq( target);
else
return findEquals( target);
} // find( Object)

/**
* Find an object in a linked list that is equal to the given
* object. Equality is determined by the == operator.
*/
private synchronized LinkedList findEq( Object target) {
...
} // find( Object)

/**
* Find an object in a linked list that is equal to the given
* object. Equality is determined by calling the given
* object's equals method.
*/
private synchronized LinkedList findEquals( Object target) {
...
} // find( Object)
} // class LinkedList

RELATED PATTERNS
Snapshot
The Marker Interface pattern is used by the Snapshot pattern to allow serialization of objects.
SYNOPSIS Proxy is a very general pattern that occurs in many other patterns, but never by itself in its pure form. The Proxy pattern forces method calls to an object to occur indirectly through a proxy object that acts as a surrogate for the other object, delegating method calls to that object. Classes for proxy objects are declared in a way that usually eliminates client objects' awareness that they are dealing with a proxy.

CONTEXT A proxy object is an object that receives method calls on behalf of another object. Client objects call the proxy object's methods. The proxy object's methods do not directly provide the service that its clients expect. Instead, the proxy object's methods call the methods of the object that provides the actual service. Figure 4.14 shows a diagram of that structure.
Though a Proxy object's methods don't directly provide the service that its clients expect, the Proxy object provides some management of those services. Proxy objects generally share a common interface or superclass with the service-providing object. That makes it possible for client objects to be unaware that they are calling the methods of a proxy object rather than the methods of the actual service-providing object. Transparent management of another object's services is the basic reason for using a proxy.
There are many different types of service management that a proxy can be used to provide. Some of the more important ones are documented elsewhere in this book as patterns in their own right. Here are some of the more common uses for proxies:

A proxy makes a method that can take a long time to complete appear to return immediately.
nA proxy creates the illusion that an object that exists on a different machine is an ordinary local object. This kind of proxy is called a remote proxy. It is used by Remote Method Invocation (RMI). n
A proxy controls access to a service-providing object. This kind of proxy is called an access proxy. A proxy creates the illusion that a service object exists before it actually
does. This can be useful if a service object is expensive to create and its services are not needed. This use of proxies is documented as the Virtual Proxy pattern.

FORCES It is not possible for a service-providing object to provide a service at a time or place that is convenient. n
Gaining visibility to an object is nontrivial and you want to hide that complexity.
Access to a service-providing object must be controlled without adding complexity to the service-providing object or coupling the service to the access control policy.
The management of a service should be provided in a way that is as transparent as possible to the clients of that service.

SOLUTION Transparent management of a service-providing object can be accomplished by forcing all access to the service-providing object through a proxy object. In order for the management to be transparent, the proxy object and the service-providing object must either be instances of a common super-class or implement a common interface, as shown in Figure 4.15.
By referring to the superclass or interface that is common to both the proxy and service providing classes, client classes avoid having to care which is the actual class that they refer to at run time.
Figure 4.15 does not show any details for implementing any particular service management policy. However, the Proxy pattern is not very useful unless it implements some particular service management policy. The Proxy pattern is so commonly used with some service management policies that the combinations are described elsewhere as patterns in their own right.

CONSEQUENCES The service provided by a service-providing object is managed in a manner transparent to that object and its clients.
Unless the use of proxies introduces new failure modes, there is normally no need for the code of client classes to reflect the use of proxies.

IMPLEMENTATION Without any specific management policy, the implementation of the Proxy pattern simply involves creating a class that shares a common superclass or interface with a service-providing class and delegates operations to instances of the service-providing class.

CODE EXAMPLE The Proxy pattern is not useful in its pure form. It must be combined with a service management behavior to accomplish anything useful. The example for the Proxy pattern uses proxies to defer an expensive operation until it is actually needed. If the operation is not needed, the operation is never performed.
The example is a subclass of java. util. Hashtable that is functionally equivalent to Hashtable. The difference is the way that it handles the clone operation. A Hashtable object's clone method returns a new Hashtable object that contains all the same things as the original Hashtable object. Cloning a Hashtable is an expensive operation. One of the more common reasons for cloning an object like a Hashtable is to avoid holding a lock on the object for a long time when all that is desired is to fetch multiple key-value pairs. In a multithreaded program, to ensure that a Hashtable is in a consistent state when you are fetching key-value pairs from it, you can use a synchronized method to obtain exclusive access to the Hashtable. While that is going on, other threads will wait to gain access to the same Hashtable, which may be unacceptable. In some other cases it may not be possible to retain exclusive access. An example of that is the Enumeration object returned by the Hashtable class's elements object.
Cloning a Hashtable prior to fetching values out of it is a defensive measure. Cloning the Hashtable avoids the need to obtain a synchronization lock on a Hashtable beyond the time that it takes for the clone operation to complete. When you have a freshly cloned copy of a Hashtable, you can be sure that no other thread has access to the copy. Since no other thread has access to the copy, you will be able to fetch key-value pairs from the copy without any interference with other threads.
If, after you clone a Hashtable, there is no subsequent modification to the original Hashtable, then the time and memory spent in creating the clone was wasted. The point of this example is to avoid that waste. It does this by delaying the cloning of a Hashtable until a modification to it actually occurs.
The main class in the example is LargeHashtable. Instances of LargeHashtable are a copy-on-write proxy for a Hashtable object. When a proxy's clone method is called, it returns a copy of the proxy but does not copy the Hashtable object. At this point, both the original and the copy of the proxy refer to the same Hashtable object. When either of the proxies is asked to modify the Hashtable, they recognize that they are using a shared Hashtable and clone the Hashtable before they make the modification.

The way the proxies know that they are working with a shared Hashtable object is that the Hashtable object that the proxies work with is an instance of a private subclass of Hashtable called ReferenceCountedHashTable. A ReferenceCountedHashTable object keeps a count of how many proxies refer to it.

public class LargeHashtable extends Hashtable {
// The ReferenceCountedHashTable that this is a proxy for.
private ReferenceCountedHashTable theHashTable;

...
public LargeHashtable() {
theHashTable = new ReferenceCountedHashTable();
} // constructor()

/**
* Return the number of key-value pairs in this hashtable.
*/
public int size() {
return theHashTable. size();
}
// size()
...
/**
* Return the value associated with the specified key in this
* Hashtable.
*/
public synchronized Object get( Object key) {
return theHashTable. get( key);
}
// get( key)

/**
* Add the given key-value pair to this Hashtable.
*/
public synchronized Object put( Object key, Object value) {
copyOnWrite();
return theHashTable. put( key, value);
}
// put( key, value)
...
/**
* Return a copy of this proxy that accesses the same Hashtable as this
* proxy. The first attempt for either to modify the
* contents of the Hashtable results in that proxy accessing a
* modified clone of the original Hashtable.
*/
public synchronized Object clone() {
Object copy = super. clone();
theHashTable. addProxy();
return copy;
}
// clone()

/**
* This method is called before modifying the underlying
* Hashtable. If it
* is being shared, then this method clones it.
*/
private void copyOnWrite() {
if (theHashTable. getProxyCount() > 1) {
// Synchronize on the original Hashtable to allow
// consistent recovery on error.
synchronized (theHashTable) {

theHashTable. removeProxy();
try {
theHashTable
= (ReferenceCountedHashTable)
theHashTable. clone();
} catch (Throwable e) {
theHashTable. addProxy();
} // try
}
// synchronized
} // if proxyCount
} // copyOnWrite()
...
private class ReferenceCountedHashTable extends Hashtable {
private int proxyCount = 1;
...
public ReferenceCountedHashTable() {
super();
} // constructor()
/**
* Return a copy of this object with proxyCount set to 1.
*/
public synchronized Object clone() {
ReferenceCountedHashTable copy;
copy = (ReferenceCountedHashTable) super. clone();
copy. proxyCount = 1;
return copy;
}
// clone()

/**
* Return the number of proxies using this object.
*/
synchronized int getProxyCount() {
return proxyCount;
}
// getProxyCount()

/**
* Increment the number of proxies using this object by one.
*/
synchronized void addProxy() {
proxyCount++;
}
// addProxy()

/**
* Decrement the number of proxies using this object by one.
*/
synchronized void removeProxy() {
proxyCount--;
}
// removeProxy()
} // class ReferenceCountedHashTable
} // class LargeHashtable

RELATED PATTERNS
Access Proxy
The Access Proxy pattern uses a proxy to enforce a security policy on access to a service-providing object. Access Proxy is not documented in this work.

Broker The Proxy pattern is sometimes used with the Broker pattern to provide a transparent way of forwarding service requests to a service object selected by the Broker/ Proxy object. The Broker pattern is not documented in this work.

Facade The facade pattern uses a single object as a front end to a set of interrelated objects.

Remote Proxy The Remote Proxy pattern uses a proxy to hide the fact that a service object is located on a different machine from the client objects that want to use it. The Remote Proxy pattern is not documented in this work.

Virtual Proxy This pattern uses a proxy to create the illusion that a service- providing object exists before it has actually been created. It is useful if the object is expensive to create and its services may not be needed. The copy-on-write proxy discussed under the "Code Example" heading for the Proxy pattern is a kind of virtual proxy.

Decorator The Decorator pattern is structurally similar to the Proxy pattern in that it forces access to a service-providing object to be done indirectly through another object. The difference is a matter of intent. Instead of trying to manage the service, the indirection object in some way enhances the service.

Chapter 7

Read More Show Less

Customer Reviews

Be the first to write a review
( 0 )
Rating Distribution

5 Star

(0)

4 Star

(0)

3 Star

(0)

2 Star

(0)

1 Star

(0)

Your Rating:

Your Name: Create a Pen Name or

Barnes & Noble.com Review Rules

Our reader reviews allow you to share your comments on titles you liked, or didn't, with others. By submitting an online review, you are representing to Barnes & Noble.com that all information contained in your review is original and accurate in all respects, and that the submission of such content by you and the posting of such content by Barnes & Noble.com does not and will not violate the rights of any third party. Please follow the rules below to help ensure that your review can be posted.

Reviews by Our Customers Under the Age of 13

We highly value and respect everyone's opinion concerning the titles we offer. However, we cannot allow persons under the age of 13 to have accounts at BN.com or to post customer reviews. Please see our Terms of Use for more details.

What to exclude from your review:

Please do not write about reviews, commentary, or information posted on the product page. If you see any errors in the information on the product page, please send us an email.

Reviews should not contain any of the following:

  • - HTML tags, profanity, obscenities, vulgarities, or comments that defame anyone
  • - Time-sensitive information such as tour dates, signings, lectures, etc.
  • - Single-word reviews. Other people will read your review to discover why you liked or didn't like the title. Be descriptive.
  • - Comments focusing on the author or that may ruin the ending for others
  • - Phone numbers, addresses, URLs
  • - Pricing and availability information or alternative ordering information
  • - Advertisements or commercial solicitation

Reminder:

  • - By submitting a review, you grant to Barnes & Noble.com and its sublicensees the royalty-free, perpetual, irrevocable right and license to use the review in accordance with the Barnes & Noble.com Terms of Use.
  • - Barnes & Noble.com reserves the right not to post any review -- particularly those that do not follow the terms and conditions of these Rules. Barnes & Noble.com also reserves the right to remove any review at any time without notice.
  • - See Terms of Use for other conditions and disclaimers.
Search for Products You'd Like to Recommend

Recommend other products that relate to your review. Just search for them below and share!

Create a Pen Name

Your Pen Name is your unique identity on BN.com. It will appear on the reviews you write and other website activities. Your Pen Name cannot be edited, changed or deleted once submitted.

 
Your Pen Name can be any combination of alphanumeric characters (plus - and _), and must be at least two characters long.

Continue Anonymously
Sort by: Showing all of 3 Customer Reviews
  • Anonymous

    Posted January 16, 2002

    Not recommend

    This book is hard to understand. He should have used more simple language and more straight forward logical. GOF's book is much easier to understand.

    Was this review helpful? Yes  No   Report this review
  • Anonymous

    Posted March 13, 2001

    Not a good place to start!!

    This is not a very good place to start and the code is not actually what the design says and is misleading. I would suggest to start with the GoF's book.

    Was this review helpful? Yes  No   Report this review
  • Anonymous

    Posted June 10, 2000

    Better than Cats

    This book was better than the broadway musical cats. I loved it.

    Was this review helpful? Yes  No   Report this review
Sort by: Showing all of 3 Customer Reviews

If you find inappropriate content, please report it to Barnes & Noble
Why is this product inappropriate?
Comments (optional)