Sunday, August 30, 2009

Patterns - 015: Creational patterns ( Prototype part - 2)

Consider a Web hosting company that offers hosting services on both Windows and UNIX platforms. Suppose that the Web hosting company offers three different types of hosting packages
  • Basic
  • Premium
  • Premium Plus
on both platforms.

Applying the Abstract Factory pattern the application design would have resulted in a factory class hierarchy as shown, Client objects can make use of an appropriate concrete factory class instance to create required HostingPlan objects.



Applying the Prototype pattern, the HostingPlanFactory class hierarchy shown abobe can be replaced with a single concrete class HostingPlanKit.

  • Maintains different prototypical objects that represent different types ofhosting packages in its instance variables.
  • Offers a set of methods that can be used by different client objects to get access to objects representing different hosting plans. As part of its implementation of these methods, it returns copies of the prototypical objects it contains.


For a client object to be able to make use of a HostingPlanKit instance, the HostingPlanKit instance must be configured with appropriate prototypical objects.




         public class HostingPlanKit {

             private HostingPlan basicPlan;
             private HostingPlan premiumPlan;
             private HostingPlan premPlusPlan;

             public HostingPlanKit(HostingPlan basic, HostingPlan premium,
                                   HostingPlan premPlus) {

                 basicPlan = basic;
                 premiumPlan = premium;
                 premPlusPlan = premPlus;
             }

             public HostingPlan getBasicPlan() {
                 return (HostingPlan) basicPlan.clone();
             }

             public HostingPlan getPremiumPlan() {
                 return (HostingPlan) premiumPlan.clone();
             }

             public HostingPlan getPremPlusPlan() {
                 return (HostingPlan) premPlusPlan.clone();
             }
         }         
     

Let us design a separate class HostingPlanManager with the responsibility of configuring a HostingPlanKit object with appropriate prototypical objects and return it to client objects.







           public class HostingPlanManager {

               public static HostingPlanKit getHostingPlanKit(
                       String platform) {

                   HostingPlan basicPlan = null;
                   HostingPlan premiumPlan = null;
                   HostingPlan premPlusPlan = null;

                   if (platform.equalsIgnoreCase("Win")) {
                       basicPlan = new WinBasic();
                       premiumPlan = new WinPremium();
                       premPlusPlan = new WinPremPlus();
                   }
                   if (platform.equalsIgnoreCase("Unix")) {
                       basicPlan = new UnixBasic();
                       premiumPlan = new UnixPremium();
                       premPlusPlan = new UnixPremPlus();
                   }
                   return new HostingPlanKit(basicPlan, premiumPlan,
                           premPlusPlan);
               }
           }
       

The HostingPlanManager offers a static method getHostingPlanKit that can be used by client objects to get access to a HostingPlanKit object configured with prototypical HostingPlan objects that represent hosting plans on the specified platform. As an alternative design strategy, the static method getHostingPlanKit can be designed as part of the HostingPlanKit class itself.

Once the HostingPlanKit object is received, a client can make use of getBasicPlan/getPremiumPlan/getPremPlusPlan methods to get access to HostingPlan objects.


Example


A computer user in a typical organization is associated with a user account. A user account can be part of one or more groups. Permissions on different resources (such as servers, printers, etc.) are defined at the group level. A user gets all the permissions defined for all groups that his or her account is part of. Let us build an application to facilitate the creation of user accounts. For simplicity, let us consider only two groups — Supervisor and AccountRep — representing users who are supervisors and account representatives,respectively.


For simplicity, let us define the set of permissions for each of the Supervisor and the AccountRep groups in the form of two text files — supervisor.txt and accountrep.txt, respectively. With this arrangement, one of the simplest ways to

create a user account is to:
  • Instantiate the UserAccount class
  • Read permissions from an appropriate data file
  • Set these permissions in the UserAccount object
Though this approach looks straightforward, it is not efficient as it involves expensive file I/O (input/output) each time an account is created. This process can be designed more efficiently using the Prototype pattern. Applying the Prototype pattern, let us make the following changes to the design.







No comments:

Post a Comment