8
IMMUTABLE OBJECT

This pattern was previously described in Grand98.


DESCRIPTION

In general, classes in an application are designed to carry data and have behavior. Sometimes a class may be designed in such a way that its instances can be used just as carriers of related data without any specific behavior. Such classes can be called data model classes and instances of such classes ar e referred to as data objects. For example, consider the Employee class in Figure 8.1 and Listing 8.1.


Employee
firstName:String
lastName:String
SSN:String
address:String
car:Car
________________________________
getFirstName():String
getLastName():String
getSSN():String
getAddress():String
getCar():Car
setFirstName(fname:String)
setLastName(lname:String)
setSSN(ssn:String)
setAddress(addr:String)
setCar(c:Car)
save():boolean
delete():boolean
isValid():boolean
update():boolean

Figure 8.1 Employee Representation


Listing 8.1 Employee Class

public class Employee { 
   //State 
   private String firstName; 
   private String lastName; 
   private String SSN; 
   private String address; 
   private Car car; 
    //Constructor 
   public Employee(String fn, String ln, String ssn, 
                   String addr, Car c) { 
     firstName = fn; 
     lastName = ln; 
     SSN = ssn; 
     address = addr; 
     car = c; 
   } 
   //Behavior 
   public boolean save() { 
     //… 
     return true; 
   } 
   public boolean isValid() { 
     //… 
     return true; 
   } 
   public boolean update() { 
     //… 
     return true; 
   }
   
   //Setters 
   public void setFirstName(String fname) { 
     firstName = fname; 
   } 
   public void setLastName(String lname) { 
     lastName = lname; 
   } 
   public void setSSN(String ssn) { 
     SSN = ssn; 
   } 
   public void setCar(Car c) { 
     car = c; 
   } 
   public void setAddress(String addr) { 
     address = addr; 
   } 
   //Getters 
   public String getFirstName() { 
     return firstName; 
   } 
   public String getLastName() { 
     return lastName; 
   } 
   public String getSSN() { 
     return SSN; 
   } 
   public Car getCar() { 
     return car; 
   } 
   public String getAddress() { 
     return address; 
   } 
}

Instances of the Employee class above have both the data and the behavior. The corresponding data model class can be designed as in Figure 8.2 and Listing 8.2 without any behavior.

In a typical application scenario, several client objects may simultaneously access instances of such data model classes. This could lead to problems if changes to the state of a data object are not coordinated properly. The Immutable Object pattern can be used to ensure that the concurrent access to a data object by several client objects does not result in any problem. The Immutable Object pattern accomplishes this without involving the overhead of synchronizing the methods to access the object data.


EmployeeModel
firstName:String
lastName:String
SSN:String
address:String
car:Car
________________________
getFirstName():String
getLastName():String
getSSN():String
getAddress():String
getCar():Car
setFirstName(fname:String)
setLastName(lname:String)
setSSN(ssn:String)
setAddress(addr:String)
setCar(c:Car)

Figure 8.2 EmployeeModel Class


Listing 8.2 EmployeeModel Class

public class EmployeeModel { 
   //State 
   private String firstName; 
   private String lastName; 
   private String SSN; 
   private String address; 
   private Car car; 
   //Constructor 
   public EmployeeModel(String fn, String ln, String ssn, 
      String addr, Car c) { 
    firstName = fn; 
    lastName = ln; 
    SSN = ssn; 
    address = addr; 
    car = c; 
   } 
   //Setters 
   public void setFirstName(String fname) { 
     firstName = fname; 
   } 
   public void setLastName(String lname) { 
     lastName = lname; 
   } 
   public void setSSN(String ssn) { 
     SSN = ssn; 
   } 
   public void setCar(Car c) { 
     car = c; 
   } 
   public void setAddress(String addr) { 
     address = addr; 
   } 
   //Getters 
   public String getFirstName() { 
     return firstName; 
   } 
   public String getLastName() { 
     return lastName; 
   } 
   public String getSSN() { 
     return SSN; 
   } 
   public Car getCar() { 
     return car; 
   } 
   public String getAddress() { 
     return address; 
   } 
}

Applying the Immutable Object pattern, the data model class can be designed in such a way that the data carried by an instance of the data model class remains unchanged over its entire lifetime. That means the instances of the data model class become immutable.

In general, concurrent access to an object creates problems when one thread can change data while a different thread is reading the same data. The fact that the data of an immutable object cannot be modified makes it automatically thread-safe and eliminates any concurrent access related problems.

Though using the Immutable Object pattern opens up an application for all kinds of performance tuning tricks, it must be noted that designing an object as immutable is an important decision. Every now and then it turns out that objects that were once thought of as immutables are in fact mutable, which could result in difficult implementation changes.


EXAMPLE

As an example, let us redesign the EmployeeModel class to make it immutable by applying the following changes.

  1. All instance variables (state) must be set in the constructor alone. No other method should be provided to modify the state of the object. The constructor is automatically thread-safe and hence does not lead to problems.
  2. It may be possible to override class methods to modify the state. In order to prevent this, declare the class as final. Declaring a class as final does not allow the class to be extended further.
  3. All instance variables should be declared final so that they can be set only once, inside the constructor.
  4. If any of the instance variables contain a reference to an object, the corresponding getter method should return a copy of the object it refers to, but not the actual object itself.

Figure 8.3 and Listing 8.3 show the resulting immutable version of the EmployeeModel class.

The immutable version of the EmployeeModel objects can safely be used in a multithreaded environment.


PRACTICE QUESTIONS

1. Design an immutable class that contains the line styles and colors used in a given image.

2. Design an immutable class to carry the data related to a company such as the company address, phone, fax, company name and other details.

i_Image1

Figure 8.3 EmployeeModel Class: Immutable Version


Listing 8.3 EmployeeModel Class: Immutable Version

public final class EmployeeModel { 
   //State 
   private final String firstName; 
   private final String lastName; 
   private final String SSN; 
   private final String address; 
   private final Car car; 
   //Constructor 
   public EmployeeModel(String fn, String ln, String ssn, 
     String addr, Car c) { 
    firstName = fn; 
    lastName = ln; 
    SSN = ssn; 
    address = addr; 
    car = c; 
   } 
   //Getters 
   public String getFirstName() { 
     return firstName; 
   } 
   public String getLastName() { 
     return lastName; 
   } 
   public String getSSN() { 
     return SSN; 
   } 
   public Car getCar() { 
     //return a copy of the car object 
     return (Car) car.clone(); 
   } 
   public String getAddress() { 
     return address; 
   } 
}
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.145.105.105