Thursday, June 9, 2022

Design Pattern: Decorator Pattern

Chapters

Decorator Pattern

Decorator pattern is a design pattern that allows behavior to be added to an individual object, dynamically, without affecting the behavior of other objects from the same class.

The decorator pattern is often useful for adhering to the Single Responsibility Principle, as it allows functionality to be divided between classes with unique areas of concern.

Decorator use can be more efficient than subclassing, because an object's behavior can be augmented without defining an entirely new object. This example demonstrates decorator pattern.
public class ClientCode{

  public static void main(String[] args){
    Package standard = 
    new StandardPackage("My Package");
    Package business = 
    new BusinessPackage("My Company's Package");
    
    standard.pack();
    business.pack();
    System.out.println();
    
    //with decorator
    new PackageGiftWrap(business).pack();
    System.out.println();
    new PackagePlasticWrap(standard).pack();
  }
}

interface Package{

  void pack();
}

abstract class AbstractPackage implements Package{
  protected String packageName;
  
  AbstractPackage(String packageName){
    this.packageName = packageName;
  }
  
  public String getPackageName(){
    return packageName;
  }
  
}

class StandardPackage extends AbstractPackage{
  
  StandardPackage(String packageName){
    super(packageName);
  }
  
  @Override
  public void pack(){
    System.out.println
    (packageName + " with standard packaging " +
    "has been packed.");
  }
}

class BusinessPackage extends AbstractPackage{
  
  BusinessPackage(String packageName){
    super(packageName);
  }
  
  @Override
  public void pack(){
    System.out.println
    (packageName + " with business packaging " +
    "has been packed.");
  }
}

//abstract decorator
abstract class PackageDecorator implements Package{
  
  protected void setAddon
  (String packageName, String addon){
    System.out.println
    (addon + " add-on has been added to " +
     packageName);
  }
}

//concrete decorator
class PackageGiftWrap extends PackageDecorator{
  private Package itemPackage;
  
  public PackageGiftWrap(Package itemPackage){
    this.itemPackage = itemPackage;
  }
  
  @Override
  public void pack(){
    itemPackage.pack(); //delegation
    giftWrap();
  }
  
  private void giftWrap(){
    if(itemPackage instanceof AbstractPackage){
      AbstractPackage ap = 
      (AbstractPackage) itemPackage;
      System.out.println
      (ap.getPackageName() + 
       " has been gift wrapped.");
    }
    else
      System.out.println("Can't find package name!");
  }
}

//concrete decorator
class PackagePlasticWrap extends PackageDecorator{
  private Package itemPackage;
  
  public PackagePlasticWrap(Package itemPackage){
    this.itemPackage = itemPackage;
  }
  
  @Override
  public void pack(){
    itemPackage.pack(); //delegation
    plasticWrap();
  }
  
  private void plasticWrap(){
    if(itemPackage instanceof AbstractPackage){
      AbstractPackage ap = 
      (AbstractPackage) itemPackage;
      System.out.println
      (ap.getPackageName() + 
       " has been plastic wrapped.");
    }
    else
      System.out.println("Can't find package name!");
  }
}

Result
My Package with standard packaging has been packed.
My Company's Package with business packaging has been packed.

My Company's Package with business packaging has been packed.
My Company's Package has been gift wrapped.

My Package with standard packaging has been packed.
My Package has been plastic wrapped.
In the example above, we can independently add new functionalities to StandardPackage and BusinessPackage instances during run-time by using decorator classes. Decorator and bridge patterns have similar structure.

However, they have different purpose. Bridge pattern is used to separate two related hierarchies so that they can be expanded independently whereas decorator pattern is used to statically or dynamically add new functionalities to an instance related to decorator class instance.

No comments:

Post a Comment