27
AGGREGATE ENFORCER

DESCRIPTION

In general, classes are designed to carry related data and offer focused functionality. Sometimes an object may contain other objects as part of it. Such an object, which is a union of other objects, is called an aggregate object. For example, a computer is an Aggregate object that contains other objects such as a CPU unit and memory units. The Aggregate Enforcer pattern recommends that when an Aggregate object is constructed, it must be constructed in full. That means that when an Aggregate class is instantiated, all of its member variables representing the set of constituting objects must also be initialized. The idea is to make sure that an Aggregate object is created in full or is not created at all.

There are two types of aggregate relationships — aggregation and composition. In both of the relationships, an Aggregate object is composed of several constituting objects.

In the case of aggregation, the parts that make up the Aggregate object can exist meaningfully without the parent Aggregate object. Composition is a stronger form of aggregation. The set of constituting objects in a composition relationship with the parent Aggregate object cannot exist meaningfully on their own without the Aggregate object.

A member variable representing a constituting object can be initialized either at the time of creating the Aggregate object (early initialization) or on demand when there is a need to use the variable. Early initialization of constituting objects has the following advantages:

  • An Aggregate object is always treated as a union of constituting objects.
    That means an Aggregate object cannot exist without its constituting objects.
    Hence, it follows the semantics of an Aggregate object to construct the Aggregate object in full by initializing all of its constituting objects.
  • Early initialization reveals any problems with the construction of any of the constituting objects at the time of constructing the parent aggregate itself.
  • All other client objects and different member functions within the Aggregate object can assume that the member variables representing constituting objects are always fully initialized. This eliminates the need for unwanted conditional statements to check if a member variable is initialized.
i_Image1

Figure 27.1 Computer Class Representation as an Aggregate


EXAMPLE

Let us design an Aggregate class representation for a typical computer with the CPU class as its constituting part (Figure 27.1). For simplicity, let us consider single processor computers only.


Design Approach I (On-Demand Initialization)

The object variable cpu can be initialized only when it is needed.

From the Computer class design in Listing 27.1 it can be observed that whenever the cpu object reference variable is accessed, a check is made to ensure that the object reference variable is properly initialized. Since there is no guarantee that the cpu variable is initialized, this check is crucial to prevent potential runtime errors.


Design Approach II (Early Initialization)

Initializing the cpu object reference variable with in the constructor (Listing 27.2) eliminates the need for a check to make sure that this object reference variable is properly initialized.

This does eliminate the need for the null value checking. But it does not always force the initialization of the cpu member variable when the Aggregate Computer object is created. In other words, even though it helps in eliminating the need for the null value checking, it is not an absolute requirement to initialize the cpu variable to be able to create an instance of the Aggregate Computer class. The Computer class must be designed in such a way that it becomes mandatory to initialize the cpu variable in its constructor. In general, what is needed is a way to make it mandatory to initialize the set of member variables that represent the objects constituting the Aggregate object.


Design Approach III (Final Variables)

A slight modification to the way the member variable cpu is declared, as in Listing 27.3, will do the trick. In Java, declaring a member variable as final ensures that the variable gets initialized fully as part of the object constructor (Figure 27.2). The compiler does not compile a class that does not fully initialize all of its final member variables.


Listing 27.1 Computer Class (On-Demand Initialization)


public class Computer { 
   //Constituting Object 
   private CPU cpu; 
   private String name; 
   //Constructor 
   public Computer(String n) { 
     name = n; 
   } 
   public boolean start() { 
     //… 
     initCPU(); 
     System.out.println("CPU activated");
     return true; 
   } 
   public boolean executeTask() { 
     //… 
     initCPU(); 
     System.out.println("CPU is Executing the Task");
     return true; 
   } 
   public boolean stop() { 
     //… 
     initCPU(); 
     System.out.println("CPU is stopped");
     return true; 
   } 
   private void initCPU() { 
     if (cpu == null) { 
      cpu = new CPU("Intel");
     } 
   } 
} 
class CPU { 
  private String name; 
  public CPU(String n) { 
    name = n; 
  } 
}

Listing 27.2 Computer Class (Early Initialization)


public class Computer { 
  //Constituting Object 
  private CPU cpu; 
  private String name; 
  //Constructor 
  public Computer(String n) { 
    name = n; 
    cpu = new CPU("Intel");
  } 
  public boolean start() { 
    //… 
    System.out.println("CPU activated");
    return true; 
  } 
     … 
     … 
}

Because the member variable initialization is guaranteed, different methods can safely eliminate the check for variable initialization.

The example deals with the construction of a single, small object as part of the Aggregate object creation. Sometimes, an Aggregate object may be composed of a number of large, complex objects. This could make it extremely expensive to construct all of the constituting objects when the Aggregate object is created. In such cases, the Virtual Proxy pattern can be used to design a proxy corresponding to each of the constituting objects. These Proxy objects can be constructed in place of actual constituting objects, as part of the Aggregate object creation.


PRACTICE QUESTIONS

1. Design a class representation for a country, which contains its capital. Ensure that the aggregate entity country is constructed in full at the time of its creation.

2. A general hospital consists of different departments. Design a representation for this relationship. Ensure that all constituting department objects are initialized when the aggregate hospital object is created.


Listing 27.3 Computer Class: Revised


public class Computer { 
  //Constituting Object 
  private final CPU cpu; 
  private String name; 
  //Constructor 
  public Computer(String n) { 
    name = n; 
    cpu = new CPU("Intel");
  } 
  public boolean start() { 
    //… 
    System.out.println("CPU activated");
    return true; 
  } 
  public boolean executeTask() { 
    //… 
    System.out.println("CPU is Executing the Task");
    return true; 
  } 
  public boolean stop() { 
    //… 
    System.out.println("CPU is stopped");
    return true; 
  } 
} 
class CPU { 
  private String name; 
  public CPU(String n) { 
    name = n; 
  } 
}
i_Image1

Figure 27.2 Revised Computer Class Representation as an Aggregate

..................Content has been hidden....................

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