Saturday, October 17, 2009

Patterns - 040: Behavioral Patterns ( State )


Patterns - 039: Behavioral Patterns ( Interpreter )



In general, languages are made up of a set of grammar rules. Different sentences can be constructed by following these grammar rules.

Sometimes an application may need to process repeated occurrences of similar requests that are a combination of a set of grammar rules.These requests are distinct but are similar in the sense that they are all composed using the same set of rules.

In such cases, instead of treating every distinct combination of rules as a separate case, it may be beneficial for the application to have the ability to interpret a generic combination of rules.

The Interpreter pattern can be used to design this ability in an application so that other applications and users can specify operations using a simple language defined by a set of grammar rules.


Applying the Interpreter pattern:

  • A class hierarchy can be designed to represent the set of grammar rules with every class in the hierarchy representing a separate grammar rule.
  • An Interpreter module can be designed to interpret the sentences constructed using the class hierarchy designed above and carry out the necessary operations.

A language with extensive, complex grammar rules requires a large number of classes. The Interpreter pattern works best when the grammar is simple. Having a simple grammar avoids the need to have many classes corresponding to the complex set of rules involved, which are hard to manage and maintain.


Example

Let us build a calculator application that evaluates a given arithmetic expression. For simplicity, let us consider only add, multiply and subtract operations.

The Interpreter pattern can be applied in two stages:
  • Define a representation for the set of rules that make up the grammar for arithmetic expressions.
  • Design an interpreter that makes use of the classes that represent different arithmetic grammar rules to understand and evaluate a given arithmetic expression.
Arithmetic Expressions – Grammar


  • ArithmeticExpression::= ConstantExpression | AddExpression |MultiplyExpression | SubtractExpression
  • ConstantExpression::= Integer/Double Value
  • AddExpression::= ArithmeticExpression ‘+’ ArithmeticExpression
  • MultiplyExpression::= ArithmeticExpression ‘*’ ArithmeticExpression
  • SubtractExpression::= ArithmeticExpression ‘-’ ArithmeticExpression
Class Hierarchy Representing Grammar Rules for Arithmetic Expressions

( Figure 34.1 )

See the additional notes for Post order and algorithms


Tuesday, October 13, 2009

Patterns - 038: Behavioral Patterns ( Observer )



The Observer pattern is useful for designing a consistent communication model between a set of dependent objects and an object that they are dependent on.

This allows the dependent objects to have their state synchronized with the object that they are dependent on.

The set of dependent objects are referred to as observers and the object that they are dependent on is referred to as the subject.

In order to accomplish this, the Observer pattern suggests a publisher-subscriber model leading to a clear boundary between the set of Observer objects and the Subject object.

Whenever the subject undergoes a change in its state, it notifies all of its
registered observers.

An observer can register or subscribe with multiple subjects.

Whenever an observer does not wish to be notified any further, it unregistered itself with the subject.

For this mechanism to work:
  • The subject should provide an interface for registering and unregistering for change notifications.
  • One of the following two must be true:
  1. – In the pull model — The subject should provide an interface that enables observers to query the subject for the required state information to update their state.
  2. – In the push model — The subject should send the state information that the observers may be interested in.
  • Observers should provide an interface for receiving notifications from the subject.

(Figure 33.1)

From this class diagram it can be seen that:
  • All subjects are expected to provide implementation for an interface similar to the Observable interface.
  • All observers are expected to have an interface similar to the Observer interface.
Several variations can be thought of while applying the Observer pattern, leading to different types of subject-observers such as observers that are interested only in specific types of changes in the subject.


Example

Let us build a sales reporting application for the management of a store with multiple departments.

Upon selecting a department, two types of reports are to be displayed:
  • – Monthly report — A list of all transactions for the current month for the selected department.
  • – YTD sales chart — A chart showing the year-to-date sales for the selected department by month.
Whenever a different department is selected, both of the reports should be refreshed with the data for the currently selected department.

Let us define three classes with the stated functionality as in follwing Table


ClassRoleFunctionality

ReportManager

Subject

Displays the necessary UI for the user to select a department.
Maintains the user selected department in an instance variable.
MonthlyReportObserver
Displays the monthly report for the selected department.

YTDChart

Observer

Displays the YTD sales chart for the selected department.


Observable Interface and Its Implementer


(Figure 33.2 )

Observer Class Hierarchy

(Figure 33.4 )

Example Application: Class Association

(Figure 33.5)
ReportManager User Interface

(Figure 33.3)
Logical Flow

  1. Using the ReportManager user interface whenever a user selects a particular department and clicks on the OK button, the ReportManager undergoes a change in its internal state (i.e., the value of its instance variable department changes).
  2. As soon as the new state is set, the ReportManager invokes the refreshData(Observable) method on both the curr ently registered MonthlyReport and the YTDChart objects.
  3. As part of refreshData method, both the report objects:a. Check to make sure that the subject that invoked the refreshData method is in fact the same Subject instance they have registered with. This is to prevent the observers from responding to unintended calls.b. Query the ReportManager for its current state using the getDepartment method.c. Retrieve appropriate data from the data file for display.

Monday, October 12, 2009

Patterns - 037: Behavioral Patterns ( Memento )



The state of an object can be defined as the values of its properties or attributes at any given point of time. The Memento patter n is useful for designing a
mechanism to capture and store the state of an object so that subsequently, when needed, the object can be put back to this (previous) state.

This is more like an undo operation.

The Memento pattern can be used to accomplish this without exposing the object’s internal structure.

The object whose state needs to be captured is referred to as the
originator.

When a client wants to save the state of the originator, it requests the current state from the originator. The originator stores all those attributes that are required for restoring its state in a separate object referred to as a
Memento and returns it to the client.

A Memento object must hide the originator variable values from all objects except the originator. In other words, it should protect its internal state against access by objects other than the originator.

Example

Let us consider one application where customer data needs to be moved from a flat file to a relational database.

Let us consider three attributes — first name, last name and the credit-cardinformation in the flat file.

Whenever an invalid customer record is found, the process stops and prompts the user to correct the data and restart the process.

When the user restarts the process, the conversion process state is restored from the Memento object and the process resumes from where it stopped, instead of starting from the beginning of the source data file.


Storing the Memento in the memory is not an option in this case. The Memento needs to be stored to persistent media instead.

Instead of storing valid customer records in a relational database, the application generates a text file consisting of SQL insert statements.

DataConverter (Originator)

The DataConverter class is the implementer of the data conversion process.

ID
The instance variable ID constitutes the state of the DataConverter. It represents the customer ID of the last successfully processed customer record.

(Figure 32.1)

Memento
The Memento class is defined as an inner class within the DataConverter. The Memento is defined with its constructor and other methods as private.

In Java, a class can access the private members of its inner classes.


The DataConverter will be able to access these methods while they remain inaccessible to other objects. Because the state of the DataConverter needs to be preserved even after the application ends, the Memento object needs to be serialized to a file. Hence the Memento is designed to implement the java.io.Serializable interface to identify itself as a Serializable class.


In Java, a Serializable class must:
  • III Explicitly specify nonserializable attributes using the transient keyword
  • III Implement the java.io.Serializable interface
  • III Have access to the first zero argument constructor of its first non-Serializable super class

The client DCClient uses a helper MementoHandler object to serialize this Memento instance to a file. Once the data is corrected and the client DCClient is run again:
  • The client DCClient invokes the getMemento method on the MementoHandler requesting it for the stored Memento object.
  • The MementoHandler deserializes the previously serialized Mementoobject from the file and returns it to the client.
  • The client passes it to the DataConverter as an argument to its setMemento method. The DataConverter puts itself back to the state stored in the memento and resumes with the data conversion process from where it stopped during the previous run.

(Figure 32.2)

(Figure 32.3)



public class DCClient {

  public static void main(String[] args) {
      MementoHandler objMementoHandler = new MementoHandler();
      DataConverter objConverter = new DataConverter();

      objConverter.setMemento(objMementoHandler.getMemento());

      if (!(objConverter.process())) {
          System.out.println("Description: Invalid data - " +
                  "Process Stopped");
          System.out.println("Please correct the Data and " +
                  "Run the Application Again");
          objMementoHandler.setMemento(
                  objConverter.createMemento());
      }
  }
}

Patterns - 036: Behavioral Patterns ( Mediator )



In general, object-oriented applications consist of a set of objects that interactwith each other for the purpose of providing a service.This interaction can be direct (point-to-point) as long as the number of objects referring to each other directly is very low.

As the number of objects increases, this type of direct interaction can lead to a complex maze of references among objects. which affects the maintainability of the application. Also, having an object directly referring to other objects greatly reduces the scope for reusing these objects because of higher coupling.

( Figure 31.2)

In such cases, the Mediator pattern can be used to design a controlled,coordinated communication model for a group of objects, eliminating the needfor objects to refer to each other directly


(Figure 31.3)
The Mediator pattern suggests abstracting all object interaction details into a separate class, referred to as a Mediator. with knowledge about the interacting group of objects.

Every object in the group is still responsible for offering the service it is designed for, but objects do not interact with each other directly for this purpose.

The interaction between any two different objects is routed through the Mediator class. All objects send their messages to the mediator. The mediator then sends messages to the appropriate objects as per the application’s requirements.

The resulting design has the following major advantages:

  • With all the object interaction behavior moved into a separate (mediator) object, it becomes easier to alter the behavior of object interrelationships, by replacing the mediator with one of its subclasses with extended or altered functionality.
  • Moving inter object dependencies out of individual objects results in enhanced object re usability.
  • Because objects do not need to refer to each other directly, objects can be unit tested more easily.
  • The resulting low degree of coupling allows individual classes to be modified without affecting other classes.


Example


Consider the The FTP client simulation application.

(Figure 30.4)

Consider following minor changes
  • When the UI is first displayed, all buttons except the Exit button should be disabled.
  • When a file name is selected from the JList control displaying the local
    file system:
  1. – The Upload and Delete buttons should be enabled.
  2. – Any selected item in the remote file system display should be deselected.
  3. – The Download button should be disabled.

shows the following object interaction.

(Figure 31.5 )

As more controls are added the direct communication between objects creates a complex maze of references among objects.

Applying the Mediator pattern, an abstraction for the object interaction details can be created. This abstraction can be designed as a separate Mediator class.

(Figure 31.6)

From the Mediator class implementation it can be seen that the Mediator offers methods for different UI objects to register themselves with the Mediator. The set of object interactions to be executed when each UI control is activated (or clicked) is designed as a separate method inside the Mediator.
Client Usage of the Mediator
The client creates an instance of the Mediator. Whenever a UI object is created, the client passes the Mediator instance to it. The UI object registers itself with this instance of the Mediator.
User Interface Objects:

Mediator Interaction Because all the object interaction details ar e removed from individual UI objects to the Mediator object, the processEvent method of each of these UI objects gets reduced to a simple call to an appropriate Mediator method.



class Mediator {
    private UploadButton btnUpload;
    private DownloadButton btnDownload;
    private DeleteButton btnDelete;
    private LocalList localList;
    private RemoteList remoteList;

    public void registerUploadButton(UploadButton inp_ib) {
        btnUpload = inp_ib;
    }

    public void registerDownloadButton(
            DownloadButton inp_dnb) {
        btnDownload = inp_dnb;
    }

    public void registerDeleteButton(DeleteButton inp_db) {
        btnDelete = inp_db;
    }

    public void registerLocalList(LocalList inp_arl) {
        localList = inp_arl;
    }

    public void registerRemoteList(RemoteList inp_drl) {
        remoteList = inp_drl;
    }

    public void UploadItem() {

        int index = localList.getSelectedIndex();
        String selectedItem =
                localList.getSelectedValue().toString();
        ((DefaultListModel) localList.getModel()).remove(
                index);

        ((DefaultListModel) remoteList.getModel()).addElement(
                selectedItem);

        btnUpload.setEnabled(false);
        btnDelete.setEnabled(false);
        btnDownload.setEnabled(false);
    }

    public void DownloadItem() {
        int index = remoteList.getSelectedIndex();
        String selectedItem =
                remoteList.getSelectedValue().toString();
        ((DefaultListModel) remoteList.getModel()).remove(
                index);

        ((DefaultListModel) localList.getModel()).addElement(
                selectedItem);

        btnUpload.setEnabled(false);
        btnDelete.setEnabled(false);
        btnDownload.setEnabled(false);
    }

    public void DeleteItem() {
        int index = localList.getSelectedIndex();
        if (index >= 0) {
            ((DefaultListModel) localList.getModel()).remove(
                    index);
        }

        index = remoteList.getSelectedIndex();
        if (index >= 0) {
            ((DefaultListModel) remoteList.getModel()).remove(
                    index);
        }
        btnUpload.setEnabled(false);
        btnDelete.setEnabled(false);
        btnDownload.setEnabled(false);

    }

    public void LocalListSelect() {
        remoteList.setSelectedIndex(-1);
        btnUpload.setEnabled(true);
        btnDelete.setEnabled(true);
        btnDownload.setEnabled(false);
    }

    public void RemoteListSelect() {
        localList.setSelectedIndex(-1);
        btnUpload.setEnabled(false);
        btnDelete.setEnabled(true);
        btnDownload.setEnabled(true);
    }
}

}// end of class

Sunday, October 4, 2009

Patterns - 035: Behavioral Patterns ( Command )


In general, an object-oriented application consists of a set of interacting objects each offering limited, focused functionality.

In terms of implementation, the application may depend on a designated object that invokes methods on these objects by passing the required data as arguments. This designated object can be referred to as an invoker as it invokes operations on different objects.

The invoker may be treated as part of the client application. The set of objects that actually contain the implementation to offer the services required for the request processing can be referred to as Receiver objects.


(client_invoker_receiver)


In this design, the application that forwards the request and the set of Receiver objects that offer the services required to process the request are closely tied to each other in that they interact with each other dir ectly. This could result in a set of conditional if statements in the implementation of the invoker.


     if (RequestType=TypeB){
//do something
}


When a new type of feature is to be added to the application, the existing code needs to be modified and it violates the basic object-oriented open-closed principle.


Using the Command pattern, the invoker that issues a request on behalf of the client and the set of service-rendering Receiver objects can be decoupled. The Command pattern suggests creating an abstraction for the processing to be carried out or the action to be taken in response to client requests.



A given Command object is responsible for offering the functionality required to process the request it represents, but it does not contain the actual implementation of the functionality. Command objects make use of Receiver objects in offering this functionality.


(client_invoker_receiver_abstraction)



When the client application needs to offer a service in response to user (or other application) interaction:


  • 1. It creates the necessary Receiver objects.
  • 2. It creates an appropriate Command object and configures it with the Receiver objects created in Step 1.
  • 3. It creates an instance of the invoker and configures it with the Command object created in Step 2.
  • 4. The invoker invokes the execute() method on the Command object.
  • 5. As part of its implementation of the execute method, a typical Command object invokes necessary methods on the Receiver objects it contains to provide the required service to its caller.

In the new design:


  • The client/invoker does not directly interact with Receiver objects and therefore, they are completely decoupled from each other.
  • When the application needs to offer a new feature, a new Command object can be added. This does not require any changes to the code of the invoker. Hence the new design conforms to the open-closed principle.
  • Because the request is designed in the form of an object, it opens up a whole new set of possibilities such as:

  • (1) – Storing a Command object to persistent media:

    – To be executed later.
    – To apply reverse processing to support the undo feature.

    (2) Grouping together different Command objects to be executed as a single unit.


Example


Let us build an application that simulates the working of an FTP client. In Java, a simple FTP client user interface can be designed using:

  • Two JList objects for the local and remote file systems display
  • Four JButton objects for initiating different types of requests such as upload, download, delete and exit

(command_pattern_gui_example)


Let us define an abstraction in the form of a CommandInterface interface for the functionality associated with different button objects in the FTP client UI for avoiding inelegant conditional statements and as more button and menu item objects are added to the FTP UI.
       interface CommandInterface {
 public void processEvent();
}

Different button objects themselves can implement this interface and behave as individual command objects. But this is not recommended as: so lets define it as follows.


(button_class_hirachy)


The FTP UI can be built using objects of this new set of JButton subclasses. The rest of the application remains unchanged and the actionPerformed method gets highly simplified to a mere two lines of code.

class buttonHandler implements ActionListener {
public void actionPerformed(ActionEvent e) {
   CommandInterface CommandObj =
           (CommandInterface) e.getSource();
   CommandObj.processEvent();
}
}

In the new design whenever a new button or a menu item is to be added, a new Command object needs to be created as an implementer of the CommandInterface. The new Command object can be added to the application in a seamless manner without requiring changes to the existing actionPerformed method code. On the negative side, this results in a larger number of classes.

  class DownloadButton extends JButton
implements CommandInterface {
  public void processEvent() {
    int index = remoteList.getSelectedIndex();
    String selectedItem =
      remoteList.getSelectedValue().toString();
    ((DefaultListModel) remoteList.getModel()).remove(
      index);

    ((DefaultListModel) localList.getModel()).addElement(
      selectedItem);
  }
  public DownloadButton(String name) {
    super(name);
  }
}


Example 2

Let us build an application to manage items in a library item database. Typical library items include books, CDs, videos and DVDs. These items are grouped into categories and a given item can belong to one or more categories. For example, a new movie video may belong to both the Video category and the NewReleases category.

Let us define two classes Item and Category

let us suppose that the library item management application deals only with adding and deleting items. Applying the Command pattern, the action to be taken to process add item and delete item requests can be designed as implementers of a common CommandInterface interface.



The CommandInterface implementers AddCommand and DeleteCommand

(command_library_system_classes)


(command_library_system_seq)



Patterns - 034: Behavioral Patterns


Behavioral Patterns



  • Deal with the details of assigning responsibilities between different objects
  • Describe the communication mechanism between objects
  • Define the mechanism for choosing different algorithms by different objects at runtime


Pattern Name Description

Command

Allows a request to be encapsulated into an object giving control over request queuing, sequencing and undoing.

Mediator

Encapsulates the direct object-to-object communication details among a set of objects in a separate (mediator) object. This eliminates the need for these objects to interact with each other directly.

Memento

Allows the state of an object to be captured and stored. The object can be put back to this (previous) state, when needed.

Observer

Promotes a publisher–subscriber communication model when there is a one-to-many dependency between objects so that when one object changes state, all of its dependents are notified so they can update their state.

Interpreter

Useful when the objective is to provide a client program or a user the ability to specify operations in a simple language. Helps in interpreting operations specified using a language, using its grammar. More suitable for languages with simple grammar.

State

Allows the state-specific behavior of an object to be encapsulated in the form of a set of state objects. With each state-specific behavior mapped onto a specific state object, the object can change its behavior by configuring itself with an appropriate state object.

Strategy

Allows each of a family of related algorithms to be encapsulated into a set of different subclasses (strategy objects) of a common superclass. For an object to use an algorithm, the object needs to be configured with the corresponding strategy object. With this arrangement, algorithm implementation can vary without affecting its clients.

Null Object

Provides a way of encapsulating the (usually do nothing) behavior of a given object type into a separate null object. This object can be used to provide the default behavior when no object of the specific type is available.

Template Method

When there is an algorithm that could be implemented in multiple ways, the template pattern enables keeping the outline of the algorithm in a separate method (Template Method) inside a class (Template Class), leaving out the specific implementations of this
algorithm to different subclasses. In other words, the Template Method pattern is used to keep the invariant part of the functionality in one place and allow the subclasses to provide the
implementation of the variant part.

Object Authenticator

Useful when access to an application object is restricted and requires a client object to furnish proper authentication credentials. Uses a separate object with the responsibility of verifying the access privileges of different client objects instead of keeping this responsibility on the application object.

Common Attribute Registry

Provides a way of designing a repository to store the common transient state of an application.






Patterns - 033: Structural patterns ( Object Cache )

The concept of keeping a copy of an object in the memory, in some form, with the goal of providing a faster response time to a client request is called caching. This is often done when the construction of a new object is expensive in terms of the processing involved. The object in the memory is not kept in the memory forever. Maintaining a large number of objects for a long time could have a negative effect on the application’s performance. A strategy must be developed to decide on the optimal number of objects to be cached and how long these objects are to be kept in the memory. Such decisions constitute the cache management strategy. The following example shows how caching can be applied in an application scenario to improve the response time.

Example

(object_cache)


The ItemManager offers an activate method that can be used by other application objects to activate an item. The ItemManager maintains a cache of some of the most recently activated item bar codes in the form of an instance variable of the ItemCache type. Whenever a client needs to activate an item, it:


1. Creates an ItemManager instance.

2. Invokes the activate method on the ItemManager object passing the item bar code as an argument.

The ItemManager checks to see if the item already exists in the cache.

  • If it exists then, it means that the item has been activated recently. The ItemManager simply returns with an appropriate message.
  • If the item does not exist, then the ItemManager accesses the database using a helper class DBManager to check if the item is already in the active state.
– If the item is already activated, the ItemManager returns with an appropriate message.
– If not, the ItemManager updates the item as active with the current date as the date-of-activation and adds it to the item cache.

This approach eliminates the need for redundant database updates.


The existence of the item cache remains transparent to the client object. The client can invoke methods on the ItemManager without having to know how the ItemManager uses the ItemCache internally.


Source for the ItemCache

public class ItemCache {
  private final static int Max_cache_size = 5;
  Vector cache;

  public ItemCache() {
      cache = new Vector();
  }

  public String getItem(String code) {
      String barCode = null;
      int pos = cache.indexOf(code);
      if (pos != -1)
          barCode = (String) cache.get(pos);
      return barCode;
  }

  public void addItem(String code) {
      // if the max limit is reached
      // remove the LRU item
      if (cache.size() == Max_cache_size) {
          cache.remove(0);
      }
      cache.add(code);
  }
}


Source for the ItemManager



public class ItemManager {
  ItemCache cache;
  DBManager manager;

  public ItemManager() {
      cache = new ItemCache();
      manager = new DBManager();
  }

  public void activate(String code) {
      if (cache.getItem(code) != null) {
          System.out.println("five.zero.three.five.txt.Item Already Activated - cache");

      } else {
          if (manager.isActiveItem(code)) {
              System.out.println(
                      "five.zero.three.five.txt.Item Already Activated - DB Access");
          } else {
              manager.activateItem(code);
              System.out.println(
                      "five.zero.three.five.txt.Item Activated successfully");
              //add to the cache
              cache.addItem(code);
          }
      }
  }
}

Saturday, October 3, 2009

Patterns - 032: Structural patterns ( Explicit Object Release )

The Explicit Object Release pattern suggests that when such an object is no longer needed, the external resources tied up with the object should be released explicitly, in a timely manner.

The Java programming language provides the following two ways to design the mechanism to release external resources explicitly:

  • The finalize() method
  • The finally statement
The garbage collection process runs periodically to reclaim the memory occupied by objects that are out of scope and no longer referenced.

When the garbage collection process runs, before an object is garbage collected, the Java runtime system invokes the object’s finalize() method.

The finalize() method must be declared as:

protected void finalize() throws Throwable


The Garbage Collection Process Runs as a Low-Level Background Daemon Thread


even though the finalize() method can be used to perform clean-up operations, it is not a reliable option to free system resources in a timely manner. This is mainly because the garbage collection process, which invokes the finalize() method on an object, runs at unpredictable times.

Releasing resources inside the finally block is more advisable as the code inside the finally is always guaranteed to be executed even when there is an unexpected runtime exception.


public class OrderLog {
public void log(Order order) {
PrintWriter dataOut = null;
try {
dataOut =
new PrintWriter(new FileWriter("order.txt"));
String dataLine =
order.getID() + "," + order.getItem() +
"," + order.getQty();
dataOut.println(dataLine);
dataOut.close(); //duplicate code
} catch (IOException e) {
System.err.println("IOException Occurred: ");
}
catch (NullPointerException ne) {
System.err.println("NullPointerException Occurred: ");
}
finally { //Guaranteed to get executed
if (dataOut != null) {
dataOut.close();
}
}
}
}

the code implementation to close the PrintWriter object inside the finally statement is guaranteed to always get executed. That means, even if an uncaught runtime exception occurs, the PrintWriter object will still be closed as a result of executing the finally statement code.



Patterns - 031: Structural patterns ( Aggregate Enforcer )

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.

The Aggregate Enforcer pattern recommends that when an Aggregate object is constructed, it must be constructed 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.

(aggregater_enforcer)


NOTE : DO THE OTHER LISTING NOTES


Patterns - 030: Structural patterns ( Counting Proxy )

The Counting Proxy pattern is useful in designing a set of additional operations such as logging and counting that need to be performed before and/or after a client object invokes a method on a service pr ovider object.

One of the characteristics of a well-designed object is that it offers focused functionality. In other words, an object, ideally, should not do various unr elated things.

Encapsulating the logging, counting and other similar functionality into a separate object leaves the service provider object with only the functionality that it is designed to offer.

A counting proxy is designed to have the same interface as the service provider object that a client accesses. Instead of accessing the service provider object directly, client objects invoke methods on the counting proxy. The proxy performs the required logging and counting and forwards the method call to the service provider object.


(counting_proxy_prototype)


Source for Order

public class Order implements OrderIF {
public Vector getAllOrders() {
FileUtil fileUtil = new FileUtil();
Vector v = fileUtil.fileToVector("orders.txt");
return v;
}
}


Source for OrderProxy


public class OrderProxy implements OrderIF {
private int counter = 0;
public Vector getAllOrders() {
Order order = new Order();
counter++;
long t1 = System.currentTimeMillis();
Vector v = order.getAllOrders();
long t2 = System.currentTimeMillis();
long timeDiff = t2 - t1;
String msg =
"Iteration=" + counter + "::Time=" + timeDiff +
"ms";
//log the message
FileUtil fileUtil = new FileUtil();
fileUtil.writeToFile("log.txt", msg, true, true);
return v;
}
}