Difference between revisions of "Object Orientation with Design Patterns"

From Sinfronteras
Jump to: navigation, search
(Singleton)
(Implementations)
Line 74: Line 74:
 
<blockquote>
 
<blockquote>
 
The Singleton pattern solves two problems at the same time, violating the Single Responsibility Principle:
 
The Singleton pattern solves two problems at the same time, violating the Single Responsibility Principle:
* '''Problem 1:''' '''Ensure that a class has just a single instance.'''
 
: Why would anyone want to control how many instances a class has? The most common reason for this is to control access to some shared resource, for example, a database or a file.
 
  
: Here's how it works: imagine that you created an object, but after a while decided to create a new one. Instead of receiving a fresh object, you'll get the one you already created.
+
*'''Problem 1:''' '''Ensure that a class has just a single instance.'''
  
: Note that this behavior is impossible to implement with a regular constructor since a constructor call must always return a new object by design.
+
:Why would anyone want to control how many instances a class has? The most common reason for this is to control access to some shared resource, for example, a database or a file.
  
* '''Problem 2:''' '''Provide a global access point to that instance.'''
+
:Here's how it works: imagine that you created an object, but after a while decided to create a new one. Instead of receiving a fresh object, you'll get the one you already created.
: Remember those global variables that you (all right, me) used to store some essential objects? While they're very handy, they're also very unsafe since any code can potentially overwrite the contents of those variables and crash the app.
 
  
: Just like a global variable, the Singleton pattern lets you access some object from anywhere in the program. However, it also protects that instance from being overwritten by other code.
+
:Note that this behavior is impossible to implement with a regular constructor since a constructor call must always return a new object by design.
  
: There's another side to this problem: you don't want the code that solves problem 1 to be scattered all over your program. It's much better to have it within one class, especially if the rest of your code already depends on it.
+
*'''Problem 2:''' '''Provide a global access point to that instance.'''
 +
 
 +
:Remember those global variables that you (all right, me) used to store some essential objects? While they're very handy, they're also very unsafe since any code can potentially overwrite the contents of those variables and crash the app.
 +
 
 +
:Just like a global variable, the Singleton pattern lets you access some object from anywhere in the program. However, it also protects that instance from being overwritten by other code.
 +
 
 +
:There's another side to this problem: you don't want the code that solves problem 1 to be scattered all over your program. It's much better to have it within one class, especially if the rest of your code already depends on it.
 
</blockquote>
 
</blockquote>
  
Line 93: Line 96:
 
<blockquote>
 
<blockquote>
 
All implementations of the Singleton have these two steps in common:
 
All implementations of the Singleton have these two steps in common:
* Make the default constructor private, to prevent other objects from using the new operator with the Singleton
 
  
* Create a static creation method that acts as a constructor. Under the hood, this method calls the private constructor to create an object and saves it in a static field. All following calls to this method return the cached object.
+
*Make the default constructor private, to prevent other objects from using the new operator with the Singleton
 +
 
 +
*Create a static creation method that acts as a constructor. Under the hood, this method calls the private constructor to create an object and saves it in a static field. All following calls to this method return the cached object.
  
 
If your code has access to the Singleton class, then it's able to call the Singleton's static method. So whenever that method is called, the same object is always returned.
 
If your code has access to the Singleton class, then it's able to call the Singleton's static method. So whenever that method is called, the same object is always returned.
Line 103: Line 107:
 
'''Applicability:'''
 
'''Applicability:'''
 
<blockquote>
 
<blockquote>
* '''Use the Singleton pattern when a class in your program should have just a single instance available to all clients; for example, a single database object shared by different parts of the program.'''
+
*'''Use the Singleton pattern when a class in your program should have just a single instance available to all clients; for example, a single database object shared by different parts of the program.'''
  
: The Singleton pattern disables all other means of creating objects of a class except for the special creation method. This method either creates a new object or returns an existing one if it has already been created.
+
:The Singleton pattern disables all other means of creating objects of a class except for the special creation method. This method either creates a new object or returns an existing one if it has already been created.
  
* '''Use the Singleton pattern when you need stricter control over global variables.'''
+
*'''Use the Singleton pattern when you need stricter control over global variables.'''
  
: Unlike global variables, the Singleton pattern guarantees that there's just one instance of a class. Nothing, except for the Singleton class itself, can replace the cached instance.
+
:Unlike global variables, the Singleton pattern guarantees that there's just one instance of a class. Nothing, except for the Singleton class itself, can replace the cached instance.
  
 
Note that you can always adjust this limitation and allow creating any number of Singleton instances. The only piece of code that needs changing is the body of the getInstance() method.
 
Note that you can always adjust this limitation and allow creating any number of Singleton instances. The only piece of code that needs changing is the body of the getInstance() method.
Line 117: Line 121:
 
'''How to Implement:'''
 
'''How to Implement:'''
 
<blockquote>
 
<blockquote>
# Add a private static field to the class for storing the singleton instance.
+
#Add a private static field to the class for storing the singleton instance.
# Declare a public static creation method for getting the singleton instance.
+
#Declare a public static creation method for getting the singleton instance.
# Implement "lazy initialization" inside the static method. It should create a new object on its first call and put it into the static field. The method should always return that instance on all subsequent calls.
+
#Implement "lazy initialization" inside the static method. It should create a new object on its first call and put it into the static field. The method should always return that instance on all subsequent calls.
# Make the constructor of the class private. The static method of the class will still be able to call the constructor, but not the other objects.
+
#Make the constructor of the class private. The static method of the class will still be able to call the constructor, but not the other objects.
# Go over the client code and replace all direct calls to the singleton's constructor with calls to its static creation method.
+
#Go over the client code and replace all direct calls to the singleton's constructor with calls to its static creation method.
 
</blockquote>
 
</blockquote>
  
Line 127: Line 131:
 
===Implementations===
 
===Implementations===
 
There are different implementations of the Singleton design pattern:
 
There are different implementations of the Singleton design pattern:
* Eager implementations
+
 
* Static Block implementations
+
*Eager implementations
* Lazy Initialisation implementations
+
*Static Block implementations
* Thread safe implementations
+
*Lazy Initialisation implementations
* Double Check Locking implementations
+
*Thread safe implementations
* Bill Pugh implementations
+
*Double Check Locking implementations
* Enum implementations
+
*Bill Pugh implementations
 +
*Enum implementations
  
 
Let's explain the different implementations through an example: The '''CalendarSingleton'''
 
Let's explain the different implementations through an example: The '''CalendarSingleton'''
  
 
A Calendar is a good example for the Singleton implementation. We need to make sure that every user have access to the same instance of the Calendar class.
 
A Calendar is a good example for the Singleton implementation. We need to make sure that every user have access to the same instance of the Calendar class.
[[File:Singleton_design_pattern.png|553x553px|thumb|center]]
+
[[File:Singleton_design_pattern.png|553x553px|thumb|center]]<br />
 
 
 
====Eager implementations====
 
====Eager implementations====
  
Line 192: Line 196:
 
      
 
      
 
}
 
}
</syntaxhighlight>
+
</syntaxhighlight><br />
 
 
 
  User.java
 
  User.java
 
<syntaxhighlight lang="java">
 
<syntaxhighlight lang="java">
Line 237: Line 240:
 
      
 
      
 
}
 
}
</syntaxhighlight>
+
</syntaxhighlight><br />
 
 
 
  Main.java   
 
  Main.java   
 
<syntaxhighlight lang="java">
 
<syntaxhighlight lang="java">
Line 290: Line 292:
 
}
 
}
 
</syntaxhighlight>
 
</syntaxhighlight>
 +
  
 
Se debe notar que en la ''Eager Implementation'' the instance is created at compiling time:
 
Se debe notar que en la ''Eager Implementation'' the instance is created at compiling time:
 
 
 
<syntaxhighlight lang="java">
 
<syntaxhighlight lang="java">
 
public class CalendarSingleton {
 
public class CalendarSingleton {
Line 305: Line 306:
 
     .
 
     .
 
     .
 
     .
</syntaxhighlight>
+
</syntaxhighlight><br />
 +
====Static Block implementations====
  
====Static Block implementations====
+
*Very similar to Eager initialisation, but the instance is inside an static block.
* Very similar to Eager initialisation, but the instance is inside an static block.
+
*This allows the use of a try-catch to handle exceptions in case something goes wrong
* This allows the use of a try-catch to handle exceptions in case something goes wrong
 
  
 
<syntaxhighlight lang="java">
 
<syntaxhighlight lang="java">
Line 330: Line 331:
  
 
In both cases (Eager and Static block implementations) the instance is created before it is actually used or needed:
 
In both cases (Eager and Static block implementations) the instance is created before it is actually used or needed:
* More memory consumption
 
* Not good practice
 
  
 +
*More memory consumption
 +
*Not good practice
 +
 +
<br />
 
====Lazy Initialisation implementations====
 
====Lazy Initialisation implementations====
* Verifies first if the instance already exists:
+
 
** If it doesn't, it will create it and return it.
+
*Verifies first if the instance already exists:
** If it does, it will return it.
+
**If it doesn't, it will create it and return it.
 +
**If it does, it will return it.
  
 
<syntaxhighlight lang="java">
 
<syntaxhighlight lang="java">
Line 358: Line 362:
 
</syntaxhighlight>
 
</syntaxhighlight>
  
* Works well for a single thread environment
+
*Works well for a single thread environment
* When it comes to multi-threaded environments, this could crash.
+
*When it comes to multi-threaded environments, this could crash.
* Imagine two threads trying to get the same instance simultaneously before it has been created. It could lead to a double instance of the class.
+
*Imagine two threads trying to get the same instance simultaneously before it has been created. It could lead to a double instance of the class.
  
 +
<br />
 
====Thread Safe implementations====
 
====Thread Safe implementations====
* Similar to Lazy Initialisation
+
 
* But this time, we'll add another modifier to the getInstance static method: ''synchronized''
+
*Similar to Lazy Initialisation
 +
*But this time, we'll add another modifier to the getInstance static method: ''synchronized''
  
 
<syntaxhighlight lang="java">
 
<syntaxhighlight lang="java">
Line 383: Line 389:
 
</syntaxhighlight>
 
</syntaxhighlight>
  
* The Thread Safe implementation works fine but it reduces the performance because of the cost associated with the synchronized method:
+
*The Thread Safe implementation works fine but it reduces the performance because of the cost associated with the synchronized method:
** Imagine to freeze the whole program any time an object tries to access the instance.
+
**Imagine to freeze the whole program any time an object tries to access the instance.
  
 +
<br />
 
====Double Check Locking implementations====
 
====Double Check Locking implementations====
* The synchronized block is used inside the if statement with an additional check to ensure that only one instance of the singleton class is created.
+
 
 +
*The synchronized block is used inside the if statement with an additional check to ensure that only one instance of the singleton class is created.
  
 
<syntaxhighlight lang="java">
 
<syntaxhighlight lang="java">
Line 413: Line 421:
 
</syntaxhighlight>
 
</syntaxhighlight>
  
* This approach is very good for multithreaded environments.
+
*This approach is very good for multithreaded environments.
  
 +
<br />
 
====Bill Pugh implementations====
 
====Bill Pugh implementations====
* This is a completely different approach from what we've seen so far
+
 
* Instead of verifying if the instance exists, this time we will use an inner static class
+
*This is a completely different approach from what we've seen so far
* This inner class will contain and instantiate the outer class
+
*Instead of verifying if the instance exists, this time we will use an inner static class
 +
*This inner class will contain and instantiate the outer class
  
 
<syntaxhighlight lang="java">
 
<syntaxhighlight lang="java">
Line 439: Line 449:
 
</syntaxhighlight>
 
</syntaxhighlight>
  
* This approach is very good as it doesn't require synchronisation.
+
*This approach is very good as it doesn't require synchronisation.
  
 +
<br />
 
====Enum implementations====
 
====Enum implementations====
  

Revision as of 00:12, 16 February 2019

Amilcar Aponte amilcar@cct.ie

Literature

What are design patterns

  • They provide solutions to common software design problems.
  • Generally aimed at solving the problems of object generation and interaction, rather than the larger scale problems of overall software architecture
  • They give generalised solutions in the form of templates that may be applied to real-world problems.

Why use design patters

  • Flexibility: Using design patterns your code becomes more flexible. It helps to provide the correct level of abstraction due to which objects become loosely coupled to each other which makes your code easy to maintain.
  • Reusability: Loosely coupled and cohesive objects and classes can make your code more reusable.
  • Shared Vocabulary:
    • Shared vocabulary makes it easy to share your code and thought with other team members.
    • It creates more understanding between the team members related to the code.
  • Capture best practices (In Amilcar's my opinion, the most important):
    • Design patterns capture solutions that have been successfully applied to problems.
    • By learning these patterns and the related problem, an inexperienced developer learns a lot about software design.
    • These solutions have been tested, used, reused and used again – And they work!

Essential elements

Design patterns essential elements
  • Name:
    • Provides a single and meaningful name to the pattern, and defines a problem and a solution for it.
    • Naming a design pattern helps itself to be referred to others easily. It also becomes easy to provide documentation for and the right vocabulary word makes it easier to think about the design.
  • The Problem:
    • It explains the problem and its context.
    • It might describe specific design problems.
    • Sometimes the problem will include a list of conditions that must be met before it makes sense to apply the pattern.
  • The solution:
    • It describes the elements that make up the design, their relationships, responsibilities, and collaborations.
    • The solution is not the complete code, but it works as a template which can be fulfilled with code.
    • The pattern provides an abstract description of a design problem and how a general arrangement of elements (classes and objects in our case) solves it.
  • Implications:
    • The consequences of a pattern include its impact on a system's flexibility, extensibility, portability or possible trade-offs.
    • Listing these consequences explicitly helps you understand and evaluate them.

Categories of patterns

  • Creational:
    • Creational design patterns are used to design the instantiation process of objects.
    • The creational pattern uses inheritance to vary the object creation.
  • Structural:
    • Structural patterns are concerned with how classes and objects are composed to form larger structures.
    • These patterns are particularly useful for making independently developed class libraries work together.
    • Rather than composing interfaces or implementations, structural object patterns describe ways to compose objects to realize new functionality.
  • Behavioural:
    • Behavioural patterns are concerned with algorithms and the assignment of responsibilities between objects.
    • Behavioural patterns describe not just patterns of objects or classes but also the patterns of communication between them.
    • Some describe how a group of peer objects cooperate to perform a task that no single object can carry out by itself.

Singleton

https://refactoring.guru/design-patterns/singleton

Singleton is a creational design pattern that lets you ensure that a class has only one instance, while providing a global access point to this instance.


Problem:

The Singleton pattern solves two problems at the same time, violating the Single Responsibility Principle:

  • Problem 1: Ensure that a class has just a single instance.
Why would anyone want to control how many instances a class has? The most common reason for this is to control access to some shared resource, for example, a database or a file.
Here's how it works: imagine that you created an object, but after a while decided to create a new one. Instead of receiving a fresh object, you'll get the one you already created.
Note that this behavior is impossible to implement with a regular constructor since a constructor call must always return a new object by design.
  • Problem 2: Provide a global access point to that instance.
Remember those global variables that you (all right, me) used to store some essential objects? While they're very handy, they're also very unsafe since any code can potentially overwrite the contents of those variables and crash the app.
Just like a global variable, the Singleton pattern lets you access some object from anywhere in the program. However, it also protects that instance from being overwritten by other code.
There's another side to this problem: you don't want the code that solves problem 1 to be scattered all over your program. It's much better to have it within one class, especially if the rest of your code already depends on it.


Solution:

All implementations of the Singleton have these two steps in common:

  • Make the default constructor private, to prevent other objects from using the new operator with the Singleton
  • Create a static creation method that acts as a constructor. Under the hood, this method calls the private constructor to create an object and saves it in a static field. All following calls to this method return the cached object.

If your code has access to the Singleton class, then it's able to call the Singleton's static method. So whenever that method is called, the same object is always returned.


Applicability:

  • Use the Singleton pattern when a class in your program should have just a single instance available to all clients; for example, a single database object shared by different parts of the program.
The Singleton pattern disables all other means of creating objects of a class except for the special creation method. This method either creates a new object or returns an existing one if it has already been created.
  • Use the Singleton pattern when you need stricter control over global variables.
Unlike global variables, the Singleton pattern guarantees that there's just one instance of a class. Nothing, except for the Singleton class itself, can replace the cached instance.

Note that you can always adjust this limitation and allow creating any number of Singleton instances. The only piece of code that needs changing is the body of the getInstance() method.


How to Implement:

  1. Add a private static field to the class for storing the singleton instance.
  2. Declare a public static creation method for getting the singleton instance.
  3. Implement "lazy initialization" inside the static method. It should create a new object on its first call and put it into the static field. The method should always return that instance on all subsequent calls.
  4. Make the constructor of the class private. The static method of the class will still be able to call the constructor, but not the other objects.
  5. Go over the client code and replace all direct calls to the singleton's constructor with calls to its static creation method.


Implementations

There are different implementations of the Singleton design pattern:

  • Eager implementations
  • Static Block implementations
  • Lazy Initialisation implementations
  • Thread safe implementations
  • Double Check Locking implementations
  • Bill Pugh implementations
  • Enum implementations

Let's explain the different implementations through an example: The CalendarSingleton

A Calendar is a good example for the Singleton implementation. We need to make sure that every user have access to the same instance of the Calendar class.

Singleton design pattern.png


Eager implementations

CalendarSingleton.java
package designPatterEx1;

import java.util.Map;
import java.util.HashMap;
import java.util.Date;
import java.util.Map.Entry;

public class CalendarSingleton {
    
    // HashMap to save one event per date
    private Map <Date, String> calendar;
    
    // Create a static private instance 
    static private CalendarSingleton instance = new CalendarSingleton();
    
    // Constructor
    // Change: The constructor is now private
    // This means that no one can instantiate it but itself
    private CalendarSingleton () {
        calendar = new HashMap<Date, String>();
    }
    
    // Add event on a particular date
    public void addEvent(Date date, String event) {
        calendar.put(date, event);
    }
    
    // Check event on a particular date
    public String getEvent(Date date) {
        return calendar.get(date);
    }
    
    public String getEvents() {
        String events = "";
        
        for (Entry entry : calendar.entrySet()) {
            events += entry.getKey() + " - " + entry.getValue() + "\n";
        }
        
        return events;
    }
    
    // Add a static public getter for the instance
    public static CalendarSingleton getInstance() {
        return instance;
    }
    
}


User.java
package designPatterEx1;

import java.util.Calendar;

public class User {

    private String name;
    private CalendarSingleton calendar;

    
    public User(String name) {
        this.name = name;
        // Change: getting the ONE instance of the calendar
        // from the unique universal access to it (static method)
        this.calendar = CalendarSingleton.getInstance();
    }

    
    public String getName() {
        return name;
    }

    
    public void setName(String name) {
        this.name = name;
    }

    
    public CalendarSingleton getCalendar() {
        return calendar;
    }
    
    
    // We can get rid of the calendar setter, as there is only
    // one calendar in the whole program.
    
    // public void setCalendar(CalendarSingleton calendar) {
    //  this.calendar = calendar;
    // }
    
}


Main.java  
package designPatterEx1;

import java.util.Date;

public class Week1Main {

    public static void main(String[] args) {
        new Week1Main();
    }
    
    public Week1Main() {
        // Creating a date object
        Date d1 = new Date(2019,02,04);
        
        // Creating a calendar object
        // Change: I don't create a new calendar. I access the one
        // that already exists.
        CalendarSingleton calendar = CalendarSingleton.getInstance();
        
        // Adding an event to the calendar
        calendar.addEvent(d1, "Amilcar's Class");
        
        // Retrieving the event on the date
        //System.out.println(calendar.getEvent(d1));
        
        // Creating a date object
        Date d2 = new Date(2019,02,05);
                
        // Adding another event to the calendar
        calendar.addEvent(d2, "Greg's Class");
        
        // Retrieving all events
        //System.out.println(calendar.getEvents());
        
        // Creating multiple users.
        User u1 = new User("Amilcar");
        User u2 = new User("Greg");
        User u3 = new User("Graham");
        User u4 = new User("Neil");
        
        // Testing that the calendar belongs to user one
        // actually has the changes
        CalendarSingleton u1Cal = u1.getCalendar();
        System.out.println(u1Cal.getEvents());
                
    }

}


Se debe notar que en la Eager Implementation the instance is created at compiling time:

public class CalendarSingleton {
    
    // HashMap to save one event per date
    private Map <Date, String> calendar;
    
    // Create a static private instance 
    static private CalendarSingleton instance = new CalendarSingleton();
    .
    .
    .


Static Block implementations

  • Very similar to Eager initialisation, but the instance is inside an static block.
  • This allows the use of a try-catch to handle exceptions in case something goes wrong
        .
        .
        .
        // Adding an static block allows us to 
        // handle exceptions in case it is needed.
        static {
                try {
                        instance = new CalendarStaticBlock();
                } catch(Exception e) {
                        System.out.println(e);
                }
        }
        .
        .
        .

In both cases (Eager and Static block implementations) the instance is created before it is actually used or needed:

  • More memory consumption
  • Not good practice


Lazy Initialisation implementations

  • Verifies first if the instance already exists:
    • If it doesn't, it will create it and return it.
    • If it does, it will return it.
        .
        .
        .	
        // Don't instantiate eagerly at compiling time
        private static CalendarLazy instance = null;
        .
        .
        .
        public static CalendarLazy getInstance() {	
                if (instance == null) {
                        instance = new CalendarLazy();
                }
                return instance;
        }
        .
        .
        .
  • Works well for a single thread environment
  • When it comes to multi-threaded environments, this could crash.
  • Imagine two threads trying to get the same instance simultaneously before it has been created. It could lead to a double instance of the class.


Thread Safe implementations

  • Similar to Lazy Initialisation
  • But this time, we'll add another modifier to the getInstance static method: synchronized
        .
        .
        .
        // The synchronised modifier, will process one request at the time
        // so we can guarantee that only one instance is created
        public static synchronized CalendarThreadSafe getInstance() {
                if (instance == null) {
                        instance = new CalendarThreadSafe();
                }	
                return instance;
        }
        .
        .
        .
  • The Thread Safe implementation works fine but it reduces the performance because of the cost associated with the synchronized method:
    • Imagine to freeze the whole program any time an object tries to access the instance.


Double Check Locking implementations

  • The synchronized block is used inside the if statement with an additional check to ensure that only one instance of the singleton class is created.
	.
	.
	.
	// Instead of freezing the whole program every time a class
	// request the instance calendar, only synchronise when the
	// instance has to be created.
	public static CalendarDoubleCheckLocker getInstance() {
		if(instance == null) {
			// Double check, in case the are multiple thread
			synchronized (CalendarDoubleCheckLocker.class){
				// Accessing the same instance
				if(instance == null) {
					instance = new CalendarDoubleCheckLocker();
				}
			}
		}
		return instance;
	}
	.
	.
	.
  • This approach is very good for multithreaded environments.


Bill Pugh implementations

  • This is a completely different approach from what we've seen so far
  • Instead of verifying if the instance exists, this time we will use an inner static class
  • This inner class will contain and instantiate the outer class
        .
        .
        .
        // Inner class to hold an instance of the outer class
        private static class CalendarHelper{		
                private static CalendarBillPugh instance = new CalendarBillPugh();
        }
        .
        .
        .
        public static CalendarBillPugh getInstance() {
                return CalendarHelper.instance;
        }
        .
        .
        .
  • This approach is very good as it doesn't require synchronisation.


Enum implementations

Introspection and Reflexion

Introspection and reflexion allow us to get access to a class from an object of that type or the class itself. This way, it is perfectly possible to break the above implementation of the singleton pattern accessing the constructor and making it public.

Introspection
try {     
     Class calendarClass = instanceOne.getClass();
     Constructor[] constructors = calendarClass.getDeclaredConstructors();

     for (Constructor constructor : constructors){
          constructor.setAccessible(true);
          instanceTwo = (CalendarSingleton) constructor.newInstance();
          break;
     }
} catch(Exception e){
     e.printStackTrace();
}
Reflexion
try {
     Constructor[] constructors = CalendarSingleton.class.getDeclaredConstructors();

     for (Constructor constructor : constructors) {
          // Below code will destroy the singleton pattern
          constructor.setAccessible(true);
          instanceTwo = (CalendarSingleton) constructor.newInstance();
     }
} catch (Exception e) {
     e.printStackTrace();
}
Enum implementations

Joshua Bloch suggests the use of Enum to implement the Singleton design pattern as Java ensures that any enum value is instantiated only once in a Java program. Since Java Enum values are globally accessible, so is the singleton. The use of Enum avoid the possibility of to breaking singleton pattern using Introspection or Reflexion.

The drawback is that the enum type is somewhat inflexible; for example, it does not allow lazy initialization.

// Completely different approach. Let's use an enum instead
public enum CalendarEnum {
        // HashMap to save one event per date
        private Map <Date, String> calendar;

        // We don't need the instance anymore, just an unique value for the enum
        instance;
        .
        .
        .
        public static CalendarEnum getInstance() {
                return instance;
        }
}