Design Patterns - ilya-khadykin/notes-outdated GitHub Wiki

TO DO:

Singleton

The Singleton design pattern is sometimes regarded as "Anti pattern". This is due to the fact that it has some problems. You have to decide for yourself if you think it is appropriate to use it.

Singletons are used to ensure that only one instance of an object is being created. The singleton allows only a single instance of itself to be created which means it controls its creation. The singleton is one of the Gang of Four design patterns and is a creational pattern.

Below is an example of a singleton class in Java, where only one version of the object can be alive during the program's lifetime (Assuming the program works on one thread)

public class SingletonExample {

    private SingletonExample() { }

    private static SingletonExample _instance;

    public static getInstance() {

        if (_instance == null) {
            _instance = new SingletonExample();
        }
        return _instance;
    }
}

Here is the thread safe version of that program:

public class SingletonThreadSafeExample {

    private SingletonThreadSafeExample () { }

    private static SingletonThreadSafeExample _instance;
    private static Object _lock = new Object();

    public static getInstance() {
        if (_instance == null) {
                createInstance();
        }
        return _instance;
    }

    private static createInstance() {
        synchronized(_lock) {
            if (_instance == null) {
                _instance = new SingletonThreadSafeExample();
            }
        }
    }
}

Java also have an object called ThreadLocal, which creates a single instance of an object on a thread by thread basis. This could be useful in applications where each thread need its own version of the object:

public class SingletonThreadLocalExample {

    private SingletonThreadLocalExample () { }

    private static ThreadLocal<SingletonThreadLocalExample> _instance = new ThreadLocal<SingletonThreadLocalExample>();

    public static getInstance() {
        if (_instance.get() == null) {
            _instance.set(new SingletonThreadLocalExample());
        }
        return _instance.get();
    }
}

Possible issues with Singletons:

  1. They are generally used as a global instance, why is that so bad? Because you hide the dependencies of your application in your code, instead of exposing them through the interfaces. Making something global to avoid passing it around is a code smell.
  1. They violate the single responsibility principle: by virtue of the fact that they control their own creation and lifecycle.
  2. They inherently cause code to be tightly coupled. This makes faking them out under test rather difficult in many cases.
  3. They carry state around for the lifetime of the application. Another hit to testing since you can end up with a situation where tests need to be ordered which is a big no no for unit tests. Why? Because each unit test should be independent from the other.

Factory

A factory decreases coupling between code that needs to create objects from object creation code. Object creation is not made explicitly by calling a class constructor but by calling some function that creates the object on behalf of the caller. A simple Java example is the following one:

interface Car {
}

public class CarFactory{
  static public Car create(String s) {
    switch (s) {
    default:
    case "us":
    case "american": return new Chrysler();
    case "de":
    case "german": return new Mercedes();
    case "jp":
    case "japanese": return new Mazda();
    }
  }
}

class Chrysler implements Car {
  public String toString() { return "Chrysler"; }
}

class Mazda implements Car {
  public String toString() { return "Mazda"; }
}

class Mercedes implements Car {
  public String toString() { return "Mercedes"; }
}

public class CarEx {
  public static void main(String args[]) {
    Car car = CarFactory.create("us");
    System.out.println(car);
  }
}

In this example, user just gives some hint about what he needs and the factory is free to construct something appropriate. It is a dependency inversion: the implementor of Car concept is free to return an appropriate concrete Car requested by the user which in turn doesn't know the details of the concrete object built.

This is a simple example of how factory works, of course in this example it is always possible to instanciate concrete classes; but one can prevent it by hiding concrete classes in a package, such that user is forced to use the factory.

This example shows a Factory class by implementing a FactoryMethod.

import java.util.HashMap;

abstract class Game{
    // Add game related attributes and methods here
    public Game(){
    
    }
    public void getNextMove(){};
    public void makeNextMove(){}
    public abstract String getName();
}
class Chess extends Game{
    public String getName(){
        return Chess.class.getName();
    }
}
class Checkers extends Game{
    public String getName(){
        return Checkers.class.getName();
    }
}
class Ludo extends Game{
    public String getName(){
        return Ludo.class.getName();
    }
}
class SnakeAndLadder extends Game{
    public String getName(){
        return SnakeAndLadder.class.getName();
    }
}
interface IGameFactory {
    public Game getGame(String gameName);
}
class GameFactory implements IGameFactory {
    HashMap<String,Game> games = new HashMap<String,Game>();
    public GameFactory(){
        games.put(Chess.class.getName(),new Chess());
        games.put(Checkers.class.getName(),new Checkers());
        games.put(Ludo.class.getName(),new Ludo());
        games.put(SnakeAndLadder.class.getName(),new SnakeAndLadder());
    }
    public Game getGame(String gameName){
        return games.get(gameName);
    }
}

public class FactoryDemo{
    public static void main(String args[]){
        if ( args.length < 1){
            System.out.println("Usage: java FactoryDemo gameName");
            return;
        }
     
        GameFactory factory = new GameFactory();
        Game game = factory.getGame(args[0]);
        System.out.println("Game="+game.getName());
    }
}

output:

java FactoryDemo Chess
Game=Chess

java FactoryDemo Ludo
Game=Ludo

GameFactory pre-creates different type of games in constructor. It implements IGameFactory factory method.

DAO (Data Access Object)

From http://en.wikipedia.org/wiki/Data_access_object: The Data Access Object (DAO) is basically an object or an interface that provides access to an underlying database or any other persistence storage. Core J2EE Patterns - Data Access Object - http://www.oracle.com/technetwork/java/dataaccessobject-138824.html

Example: Maybe a simple example can help you understand the concept. Let's say we have an entity to represent an employee:

public class Employee {

    private int id;
    private String name;


    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }

}

The employee entities will be persisted into a corresponding Employee table in a database. A simple DAO interface to handle the database operation required to manipulate an employee entity will be like:

interface EmployeeDAO {

    List<Employee> findAll();
    List<Employee> findById();
    List<Employee> findByName();
    boolean insertEmployee(Employee employee);
    boolean updateEmployee(Employee employee);
    boolean deleteEmployee(Employee employee);

}

Next we have to provide a concrete implementation for that interface to deal with SQL server, and another to deal with flat files, etc.

References

⚠️ **GitHub.com Fallback** ⚠️