Showing posts with label Design Patterns. Show all posts
Showing posts with label Design Patterns. Show all posts

Tuesday, October 16, 2012

Dependency Injection

1.  What is Dependency Injection?

The general concept behind dependency injection is called Inversion of Control . A class should not configure its dependencies but should be configured from outside.
Dependency injection is a concept which is not limited to Java. But we will look at dependency injection from a Java point of view.
A Java class has a dependency on another class if it uses an instance of this class, e.g. via calling the constructor or via a static method call. For example a class which accesses a logger service has a dependency on this service class.
Ideally Java classes should be as independent as possible from other Java classes. This increases the possibility of reusing these classes and to be able to test them independently from other classes, for example for unit testing.
If the Java class directly creates an instance of another class via the new operator, it cannot be used and tested independently from this class.
To decouple Java classes its dependencies should be fulfilled from the outside. A Java class would simply define its requirements like in the following example:

public class MyPart {
  
  @Inject private Logger logger;
  // DatabaseAccessClass would talk to the DB
  @Inject private DatabaseAccessClass dao;
  
  @Inject
  public void init(Composite parent) {
    logger.info("UI will start to build");
    Label label = new Label(parent, SWT.NONE);
    label.setText("Eclipse 4");
    Text text = new Text(parent, SWT.NONE);
    text.setText(dao.getNumber());
  }

} 


Another class could read these dependencies and create an instance of the class, injecting objects into the defined dependency. This can be done via the Java reflection functionality. This class is usually called the dependency container and is a framework class.
This way the Java class has no hard dependencies, i.e. it does not rely on an instance of a certain class. For example if you want to test a class which uses another object which directly uses a database, you could inject a mock object.
Mock objects are objects which act as if they are the real object but only simulate their behavior. Mock is an old English word meaning to mimic or imitate.
If dependency injection is used, a Java class can be tested in isolation, which is good.
Dependency injection can happen on:
  • the constructor of the class (construction injection)
  • a method (method injection)
  • a field (field injection)

Dependency injection can happen on static as well as on non-static fields and methods.

Java and dependency injection frameworks.:-

You can use dependency injection without any additional framework by providing classes with sufficient constructors or getter and setter methods.
A dependency injection framework simplifies the initialization of the classes with the correct objects.
Two popular dependency injection frameworks are Spring and Google Guice .
Also Eclipse 4 is using dependency injection.

Singleton Design Pattern

1. Singletons in Java

1.1. Overview

A singleton in Java is a class for which only one instance can be created provides a global point of access this instance. The singleton pattern describe how this can be archived.
Singletons are useful to provide a unique source of data or functionality to other Java Objects. For example you may use a singleton to access your data model from within your application or to define logger which the rest of the application can use.

1.2. Code Example

The possible implementation of Java depends on the version of Java you are using.
As of Java 6 you can singletons with a single-element enum type. This way is currently the best way to implement a singleton in Java 1.6 or later according to tht book ""Effective Java from Joshua Bloch.
package mypackage;

public enum MyEnumSingleton {
  INSTANCE;
  
  // other useful methods here
} 
 
Before Java 1.6 a class which should be a singleton can be defined like the following. 
 
public class Singleton {
  private static Singleton uniqInstance;

  private Singleton() {
  }

  public static synchronized Singleton getInstance() {
    if (uniqInstance == null) {
      uniqInstance = new Singleton();
    }
    return uniqInstance;
  }
  // other useful methods here
} 
 
 
 

1.3. Evaluation

A static class with static method would result in the same functionality as a singleton. As singletons are define using an object orientated approach it is in general advised to work with singletons.
Singleton violate the "One Class, one responsibility" principle as they are used to manage its one instance and the functionality of the class.
A singleton cannot be subclassed as the constructor is declared private.
If you are using multiple classloaders then several instances of the singleton can get created.
 

Design Pattrens Introduction

1.Introduction

The terminology of "Design Pattern" in software developed is based on the GOF (Gang of Four) book "Design Patterns - Elements of Reusable Object-Oriented Software" from Erich Gamma, Richard Helm, Ralph Johnson und John Vlissides. Design Pattern are proven solutions approaches to specific problems. A design pattern is not framework and is not directly deployed via code.
Design Pattern have two main usages:
  • Common language for developers: They provide developer a common language for certain problems. For example if a developer tells another developer that he is using a Singleton, the another developer (should) know exactly what this means.
  • Capture best practices: Design patterns capture solutions which have been applied to certain problems. By learning these patterns and the problem they are trying to solve a unexperienced developer can learn a lot about software design.

Design pattern are based on the base principles of object orientated design.
  • Program to an interface not an implementation
  • Favor object composition over inheritance

Design Patterns can be divided into:
  • Creational Patterns
  • Structural Patterns
  • Behavioral Patterns

2.Object Orientated Programming


OO programming suggests that you use the following principles during the design of a software. The following are not "Design Principles" but a repetition of a good OO design.

2.1. Encapsulation

In general a general manipulation of an object's variables by other objects or classes is discouraged to ensure data encapsulation. A class should provide methods through which other objects could access variables. Java deletes objects which are not longer used (garbage collection).

2.2. Abstraction

Java support the abstraction of data definition and concrete usage of this definition.
The concept is divided from the concrete which means you first define a class containing the variables and the behavior (methods) and afterwards you create the real objects which then all behave like the class defined it.
A class is the definition of the behavior and data. A class can not be directly be used.
A object in an instance of this class and is the real object which can be worked with.

2.3. Polymorphisms

The ability of object variables to contain objects of different classes. If class X1 is a subclass of class X then a method which is defined with a parameter for an object X can also get called which an object X1.
If you define a supertype for a group of classes any subclass of that supertype can be substituted where the supertype is expected.
If you use an interface as a polymorphic type any object which implements this interface can be used as arguments.

2.4. Inheritance

Inheritance allows that classes can be based on each other. If a class A inherits another class B this is called "class A extends class B".
For example you can define a base class which provides certain logging functionality and this class is extended by another class which adds email notification to the functionality.

2.5. Delegation

Delegation is then you hand over the responsibility for a particular task to anther class or method.
If you need to use functionality in another class but you do not want to change that functionality then use delegation instead of inheritance.

2.6. Composition

When you refer to a whole family of behavior then you use composition. Here you program against an interface and then any class which implements this interface can be used to be defined. In composition the composition class is still defined in the calling class.
When you use composition, the composing object owns the behaviors is uses and they stop existing as soon as the composing object does.

2.7. Aggregation

Aggregation allows you to use behavior from another class without limiting the lifetime of those behaviors.
Aggregation is when one class is used as part of another class but still exists outside of that class.

2.8. Design by contract

Programming by contract assumes both sides in a transaction understand what actions generate what behavior and will abide by that contact.
Methods usually return null or unchecked exceptions when errors occurs in programming by contract environment.
If you believe that a method should not get called in a certain way just throw an unchecked runtime exception. This can be really powerful. Instead of checking in your calling code for exceptions you just throw an exception in the called code. Therefore you can easier identify the place in the coding their an error occurs. This follows the "crash-early" principle, which tells that if an error occurs in your software you should crash immediately and not later in the program because then it is hard to find the error.

2.9. Cohesion

A system should have a high cohesion.
In a highly-cohesive system, code readability and the likelihood of reuse is increased, while complexity is kept manageable.
Cohesion is a measure of how strongly-related and focused the responsibilities of a single class are. In object-oriented programming, it is beneficial to assign responsibilities to classes in a way that keeps cohesion high. Code readability and the likelihood of reuse is increased, while complexity is kept manageable, in a highly-cohesive system.

2.10. The Principle of Least Knowledge

Talk only to your immediate friends.
Also known as Law of Demeter.

2.11. The Open Closed Principle

Software entities like classes, modules and functions should be open for extension but closed for modifications.
This principles encourages developers to write code that can be easily extended with only minimal or no changes to existing code.
An example for a good application of this principles would be that a certain class calls internally an abstract class to conducted a certain behavior. At runtime this class is provided with an concrete implementation of this abstract class. This allows the developer later to implement another concrete calls of this abstract class without changing the code of the class which uses this abstract class.
Another excellent example is the Eclipse Extension Point method. Eclipse Plugins or Eclipse based application can define extension points where other plugs-ins can later add functionality.