Skip to main content

Decorator Pattern : Real Life Example and Java Code Example

Decorator Pattern

The Decorator Pattern provides a mechanism to dynamically attach the additional responsibilities to an object at runtime. Inheritance also provides the same but it is not flexible and does statically. We will see further in detail why Inheritance is not a good option as compared to Decorator Pattern. One important thing about the Decorator Pattern, It does not affect the core functionality just attach some additional.

Real Life Example:

Take the example of a bicycle store. When someone comes to buy a bicycle, The distributor shows the basic bicycle with core functionalities. After selecting the bicycle, He asks for the accessories you want to attach. Suppose there are accessories like carrier,stand-leg,front-light,front-box,bike-bell. The service man decorates your bicycle with accessories(additional functionalities without affecting the core functionality) as per your requirement.


Java Code Example:

We will try to implement the above real life example in java code by using the Inheritance and Decorator Pattern and discuss the limitation of Inheritance implementation.


Inheritance Implementation

Let's first enumerate the things we have
  1. Core Cycle
  2. Carrier
  3. Single Leg Stand
  4. Front Light
  5. Front Box
  6. Classic Bell
Let's implement the above problem by using inheritance.
//Core Class
package pattern.inherit;

/**
 * Created by shubhamc on 18/4/17.
 */
public class CoreCycle {
    public void coreFunction(){
        System.out.println("Adding Core Functions");
    }
}

___________________________________________________________________________


//Inherited classes
package pattern.inherit;

/**
 * Created by shubhamc on 18/4/17.
 */
public class CycleWithCarrier extends CoreCycle {
    @Override
    public void coreFunction(){
        super.coreFunction();
        addCarrier();
    }

    public void addCarrier(){
        System.out.println("Adding Carrier");
    }
}


/*--------------------------------------------------------------*/
package pattern.inherit;

/**
 * Created by shubhamc on 18/4/17.
 */
public class CycleWithClassicBell extends CoreCycle {
    @Override
    public void coreFunction(){
        super.coreFunction();
        addClassicBell();
    }

    public void addClassicBell(){
        System.out.println("Adding Classic Bell");
    }
}


/*--------------------------------------------------------------*/

package pattern.inherit;

/**
 * Created by shubhamc on 18/4/17.
 */
public class CycleWithFrontLight extends CoreCycle{
    @Override
    public void coreFunction(){
        super.coreFunction();
        addFrontLight();
    }

    public void addFrontLight(){
        System.out.println("Adding Front Light");
    }
}


/*--------------------------------------------------------------*/

package pattern.inherit;

/**
 * Created by shubhamc on 18/4/17.
 */
public class CycleWithCarrierAndFrontLight extends CycleWithCarrier {
    CycleWithFrontLight obj = new CycleWithFrontLight();

    @Override
    public void coreFunction(){
        super.coreFunction();
        obj.addFrontLight();
    }
}




/*--------------------------------------------------------------*/
package pattern.inherit;

/**
 * Created by shubhamc on 18/4/17.
 */
public class CycleWithCarrierAndFrontLightAndClassicBell extends CycleWithCarrierAndFrontLight {
    CycleWithClassicBell obj = new CycleWithClassicBell();

    @Override
    public void coreFunction(){
        super.coreFunction();
        obj.addClassicBell();
    }
}

___________________________________________________________________________



//The main Class
package pattern.inherit;

/**
 * Created by shubhamc on 18/4/17.
 */
public class MainCycle {
    public static void main(String[] args) {
        //Core Cycle
        System.out.println("#####-Core Cycle-#####");
        CoreCycle c1 = new CoreCycle();
        c1.coreFunction();
        System.out.println();

        //Cycle with Carrier
        System.out.println("#####-Cycle with Carrier-#####");
        CycleWithCarrier c2 = new CycleWithCarrier();
        c2.coreFunction();
        System.out.println();

        //Cycle with Front Light
        System.out.println("#####-Cycle with Front Light-#####");
        CycleWithFrontLight c3 = new CycleWithFrontLight();
        c3.coreFunction();
        System.out.println();

        //Cycle with Classic Bell
        System.out.println("#####-Cycle with Classic Bell-#####");
        CycleWithClassicBell c4 = new CycleWithClassicBell();
        c4.coreFunction();
        System.out.println();

        //Cycle with Carrier and Front Light
        System.out.println("#####-Cycle with Carrier and Front Light-#####");
        CycleWithCarrierAndFrontLight c5 = new CycleWithCarrierAndFrontLight();
        c5.coreFunction();
        System.out.println();

        //Cycle with Carrier,Front Light and Classic Bell
        System.out.println("#####-Cycle with Carrier,Front Light and Classic Bell-#####");
        CycleWithCarrierAndFrontLightAndClassicBell c6 = new CycleWithCarrierAndFrontLightAndClassicBell();
        c6.coreFunction();
        System.out.println();



    }
}




By analyzing the above code We can say that There will be need of certain no. of classes for all cases. Let's do the simple math to calculate the total no. of classes.
If there is n additional accesseries then total no. of possible combinations will be
nC1 + nC2 + ...... + nCn = 2^n - 1

In this case, there are total 5 accessories, So total no. of classes will be: (2^5 - 1) = 31

Now We need to write 31 to classes to cover all cases and it will be the very cumbersome task.


Decorator Pattern Implementation

Analyze the below code and you will find that there will be only n no. of classes will be required to cover all cases for n accessories. In this case only 5 classes.



___________________________________________________________________________


//The Core Interface
package pattern.decorator;

/**
 * Created by shubhamc on 18/4/17.
 */
public interface Cycle {
    void coreFunction();
}
___________________________________________________________________________


//The core Implementation
package pattern.decorator;

/**
 * Created by shubhamc on 18/4/17.
 */
public class CoreCycle implements Cycle {
    @Override
    public void coreFunction(){
        System.out.println("Get the core Cycle");
    }
}
___________________________________________________________________________


//The core Abstract Decorator
package pattern.decorator;

/**
 * Created by shubhamc on 18/4/17.
 */
public abstract class CycleDecorator implements Cycle {
    private Cycle cycle;
    public CycleDecorator(Cycle inner){
        this.cycle = inner;
    }

    @Override
    public void coreFunction(){
        cycle.coreFunction();
    }
}

___________________________________________________________________________


//The Decorators
package pattern.decorator;

/**
 * Created by shubhamc on 18/4/17.
 */
public class CarrierDecorator extends CycleDecorator {
    public CarrierDecorator(Cycle inner){
        super(inner);
    }

    @Override
    public void coreFunction(){
        super.coreFunction();
        decorateCarrier();
    }

    private void decorateCarrier(){
        System.out.println("Decorating Carrier");
    }
}


/*--------------------------------------------------------------*/

package pattern.decorator;

/**
 * Created by shubhamc on 18/4/17.
 */
public class ClassicBellDecorator extends CycleDecorator {
    public ClassicBellDecorator(Cycle inner){
        super(inner);
    }

    @Override
    public void coreFunction(){
        super.coreFunction();
        decorateClassicBell();
    }

    private void decorateClassicBell(){
        System.out.println("Decorating Classic Bell");
    }
}


/*--------------------------------------------------------------*/

package pattern.decorator;

/**
 * Created by shubhamc on 18/4/17.
 */
public class FrontBoxDecorator extends CycleDecorator {
    public FrontBoxDecorator(Cycle inner){
        super(inner);
    }

    @Override
    public void coreFunction(){
        super.coreFunction();
        decorateFrontBox();
    }

    private void decorateFrontBox(){
        System.out.println("Decorating Front Box");
    }
}

/*--------------------------------------------------------------*/

package pattern.decorator;

/**
 * Created by shubhamc on 18/4/17.
 */
public class FrontLightDecorator extends CycleDecorator {
    public FrontLightDecorator(Cycle inner){
        super(inner);
    }

    @Override
    public void coreFunction(){
        super.coreFunction();
        decorateFrontLight();
    }

    private void decorateFrontLight(){
        System.out.println("Decorating Front Light");
    }
}


/*--------------------------------------------------------------*/
package pattern.decorator;

/**
 * Created by shubhamc on 19/4/17.
 */
public class SingleLegStandDecorator extends CycleDecorator {
    public SingleLegStandDecorator(Cycle inner){
        super(inner);
    }

    @Override
    public void coreFunction(){
        super.coreFunction();
        decorateSingleLegStand();
    }

    private void decorateSingleLegStand(){
        System.out.println("Decorating Single Leg Stand");
    }
}
___________________________________________________________________________



//The main Class
package pattern.decorator;

/**
 * Created by shubhamc on 19/4/17.
 */
public class MainCycle {
    public static void main(String[] args) {

        //Core Cycle
        System.out.println("#####-Core Cycle-#####");
        Cycle c1 = new CoreCycle();
        c1.coreFunction();
        System.out.println();

        //Cycle with Carrier
        System.out.println("#####-Cycle with Carrier-#####");
        Cycle c2 = new CarrierDecorator(new CoreCycle());
        c2.coreFunction();
        System.out.println();


        //Cycle with Carrier and Front Light
        System.out.println("#####-Cycle with Carrier and Front Light-#####");
        Cycle c3 = new CarrierDecorator(new FrontLightDecorator(new CoreCycle()));
        c3.coreFunction();
        System.out.println();

        //Cycle with Carrier,Front Light and Classic Bell
        System.out.println("#####-Cycle with Carrier,Front Light and Classic Bell-#####");
        Cycle c4 = new CarrierDecorator(new FrontLightDecorator(new ClassicBellDecorator(new CoreCycle())));;
        c4.coreFunction();
        System.out.println();

    }
}


Comments

Popular posts from this blog

java.lang.IllegalArgumentException: Could not instantiate implementation: org.janusgraph.diskstorage.cassandra.thrift.CassandraThriftStoreManager

If you are trying to get started with Janus Graph with Apache Cassandra. You may get the following error. Caused by: org.janusgraph.diskstorage.TemporaryBackendException: Temporary failure in storage backend at org.janusgraph.diskstorage.cassandra.thrift.CassandraThriftStoreManager.getCassandraPartitioner(CassandraThriftStoreManager.java:219) ~[janusgraph-cassandra-0.2.0.jar:na] at org.janusgraph.diskstorage.cassandra.thrift.CassandraThriftStoreManager.<init>(CassandraThriftStoreManager.java:198) ~[janusgraph-cassandra-0.2.0.jar:na] ... 48 common frames omitted Caused by: org.apache.thrift.transport.TTransportException: java.net.ConnectException: Connection refused (Connection refused) at org.apache.thrift.transport.TSocket.open(TSocket.java:187) ~[libthrift-0.9.2.jar:0.9.2] at org.apache.thrift.transport.TFramedTransport.open(TFramedTransport.java:81) ~[libthrift-0.9.2.jar:0.9.2] at org.janusgraph.diskstorage.cassandra.thrift.thriftpool.CTConnectionFactory.makeR...

com.mongodb.MongoCommandException: Command failed with error 18: 'Authentication failed.' on server

If you are trying to connect Mongo DB Server and it insanely throwing following error. com.mongodb.MongoTimeoutException : Timed out after 1000 ms while waiting for a server that matches ReadPreferenceServerSelector{readPreference=primary}. Client view of cluster state is {type=UNKNOWN, servers=[{address=192.168.1.10:27010, type=UNKNOWN, state=CONNECTING, exception={ com.mongodb.MongoSecurityException: Exception authenticating MongoCredential {mechanism=null, userName='user123', source='admin', password=<hidden>, mechanismProperties={}}}, caused by {com.mongodb.MongoCommandException: Command failed with error 18 : 'Authentication failed.' on server 192.168.1.10:27010 . The full response is { "ok" : 0.0, "code" : 18, "errmsg" : "Authentication failed." }}}] If you start looking the error content First you encounter with Timeout Exception which may mislead you. It is basically an authentication error. I...

Move like a Ninja on Terminal Console

If you are in IT and do a lot of stuff on terminal, this is the post for you. In the following post, we will explore various key shortcuts to jump and edit on console. Note:- Short keys may behave differnt on differnt OS systems. These keys best work with Linux sytem, For mac OS you have to enable Option key as Meta key in case of Alt . I have never checked these on windows, Please share your experinece with windows in comments. ------------------------------------------------------------------ Edit Control Move forward one char: Ctrl + f Move backward one char: Ctrl + b Move forward one word: Alt + f Move backward one word: Alt + b Move to end: Ctrl + e #Like End Move to start: Ctrl + a #Like Home Jump toggle between current location and start: Ctrl + xx Delete forward one char: Ctrl + d #Like Delete Delete backward one char: Ctrl + h #Like Backspace Delete forward one word: Alt + d Delete backward one word: Ctrl + w Delete to end: Ctrl + k Delete to start: Ctrl + u Undo: Ct...