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

How to Create a Namespace in Aerospike Database

                      T his post is about creating a namespace in Aerospike. I could not find any concrete method to create a namespace like create database in MySQL and MongoDB. So I am suggesting a way to create a namespace in Aerospike Database. Step-1: Locate config file aerospike.conf and open it in your favorite editor and make sure you have permission to modify the file. In my system the path of file /etc/aerospike/aerospike.conf (Default in Ubuntu). Here the content of the file. # Aerospike database configuration file. service { user root group root paxos-single-replica-limit 1 # Number of nodes where the replica pidfile /var/run/aerospike/asd.pid service-threads 4 transaction-queues 4 transaction-threads-per-queue 4 proto-fd-max 15000 } logging { # Log file must be an absolute path. file /var/log/aerospike/aerospike.log { context any info } } network { service { address any port 3000 } heartbeat { mode multicast address 239.1.99.222 p

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