Design Pattern

Design a class using the Singleton design pattern

According to the GoF book, the Singleton design pattern "ensures a class has only one instance, and provides a global point of access to it." You use the Singleton pattern to satisfy four simultaneous requirements:

  • An application must have EXACTLY ONE instance of a particular class.

  • The sole instance must be accessible to clients from a well-known access point.

  • The sole instance should be extensible by subclassing.

  • Clients must be able to use and extend the instance without modifying their own code.

The Singleton design pattern ensures that the application has only one global instance of an object. The pattern's code is quite simple, but behind this simplicity, the pattern has some potential pitfalls.

The figure below shows a UML diagram for the Singleton design pattern:

In order to write a singleton class, you'll need to understand the following:

  • Creating a static variable of the instance of your singleton class will ensure that there are no two instances created at any given point.

  • Exposing a method named getInstance() will return the instance of the class: either by creating it or returning the instance if it already exists.

  • Singletons class constructor is declared as private so that the class could not be initialized from outside.

The following code implements the concept of lazy initialization — meaning, you are creating the object of the singleton class, only when the getInstance() method is invoked. It also means that if the getInstance() method is not invoked, then the instance shall never be created:

public class Singleton {

    private static Singleton instance;

    // Private constructor prevents instantiation from other classes
    private Singleton() {
    }

    public static synchronized Singleton getInstance() {
        if (null == instance) {
            instance = new Singleton();
        }
        return instance;
    }
}
					

Using the synchronized keyword in this way will be extremely costly, because it's acted upon every time the getInstance() method is invoked.

There is a different technique to avoid performance bottlenecks in applications, and this is to modify the code to synchronize only the assignment in the getInstance() method:

public class Singleton {

    private static Singleton instance;

    // Private constructor prevents instantiation from other classes
    private Singleton() {
    }

    public static Singleton getInstance() {
        if (instance == null) {
            synchronized (Singleton.class) {
                if (instance == null) {
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}
					

This solution is thread-safe with eager instantiation:

public class Singleton {

    private static final Singleton instance = new Singleton();

    // Private constructor prevents instantiation from other classes
    private Singleton() {
    }

    public static Singleton getInstance() {
        return instance;
    }
}
					

The initialization on demand holder (lazy-loaded) solution:

public class Singleton {

    // Private constructor prevents instantiation from other classes
    private Singleton() {
    }

    /**
     * SingletonHolder is loaded on the first execution of Singleton.getInstance()
     * or the first access to SingletonHolder.INSTANCE, not before.
     */
    private static class SingletonHolder {
        public static final Singleton INSTANCE = new Singleton();
    }

    public static Singleton getInstance() {
        return SingletonHolder.INSTANCE;
    }
}
					

The single-element enum type solution (from "Effective Java" 2nd edition by Joshua Bloch):

public enum Singleton {
    INSTANCE;
}
					

or

public enum Singleton {
    INSTANCE;

    public static Singleton getInstance() {
        return INSTANCE;
    }
}
					



Identify when and how to use composition to solve business problems

Object composition is a way to combine simple objects or data types into more complex ones.

Composited (composed) objects are often referred to as having a "has a" relationship. A real-world example of composition may be seen in an automobile: the objects wheel, steering wheel, seat, gearbox and engine may have no functionality by themselves, but an object called automobile containing all of those objects would serve a higher function, greater than the sum of its parts.

When, in a language, objects are typed, types can often be divided into composite and noncomposite types, and composition can be regarded as a relationship between types: an object of a composite type (e.g. car) "has an" object of a simpler type (e.g. wheel).

Composition must be distinguished from subtyping, which is the process of adding detail to a general data type to create a more specific data type. For instance, cars may be a specific type of vehicle: car is a vehicle. Subtyping doesn't describe a relationship between different objects, but instead, says that objects of a type are simultaneously objects of another type.

You should prefer composition over inheritance as it is more flexible and easy to modify later. With composition, it's easy to change behavior on the fly with dependency injection or setters. Inheritance is more rigid as most languages do not allow you to derive from more than one type.

  • Test for need of Inheritance:

    Does TypeB want to expose the complete interface (all public methods no less) of TypeA such that TypeB can be used where TypeA is expected?

    Example: A Cessna biplane will expose the complete interface of an Airplane, if not more. So that makes it fit to derive from Airplane.

    public class Airplane {
        public void startEngine() {
            // ...
        }
    
        public void fly() {
            // ...
        }
    }
    								

    public class Cessna extends Airplane {
        public void setTurboMode(boolean b) {
            // ...
        }
    }
    								

  • Test for need of Composition:

    Does TypeB only want only some/part of the behavior exposed by TypeA?

    Example: e.g. A Bird may need only the fly behavior of an Airplane. In this case, it makes sense to extract it out as an interface / class / both and make it a member of both classes.

    public class FlyBehaviour {
    
        public void fly() {
            // ...
        }
    }
    								

    public class Airplane {
        @Resource
        FlyBehaviour fb;
    
        public void fly() {
            fb.fly();
        }
    
        public void startEngine() {
            // ...
        }
    }
    								

    public class Bird {
        @Resource
        FlyBehaviour fb;
    
        public void fly() {
            fb.fly();
        }
    
        public void tweet() {
            // ...
        }
    }
    								

In UML, an object relationship that is formed using composition is drawn using a filled diamond. The following UML diagram illustrates the concepts of composition:

Composition in UML

In the diagram above, the battery, the door, and the engine have no meaning outside of the car, as the car cannot work without either of them, so the relationship is formed using composition.



Write code to implement the DAO Pattern

A data access object (DAO) is an object that provides an abstract interface to some type of database or persistence mechanism, providing some specific operations without exposing details of the database. It provides a mapping from application calls to the persistence layer. This isolation separates the concerns of what data accesses the application needs, in terms of domain-specific objects and data types (the public interface of the DAO), and how these needs can be satisfied with a specific DBMS, database schema, etc. (the implementation of the DAO).

The advantage of using data access objects is the relatively simple and rigorous separation between two important parts of an application that can and should know almost nothing of each other, and which can be expected to evolve frequently and independently. Changing business logic can rely on the same DAO interface, while changes to persistence logic does not affect DAO clients as long as the interface remains correctly implemented.

The CustomerDAO interface shown below defines the DAO methods for Customer persistent object that are implemented by all concrete DAO implementations, such as DerbyCustomerDAO, OracleCustomerDAO, and DB2CustomerDAO.


import java.util.Collection;

public interface CustomerDAO {
    public int insertCustomer(Customer c);
    public boolean deleteCustomer(Customer c);
    public Customer findCustomer(int id);
    public boolean updateCustomer(Customer c);
    public Collection<Customer> selectCustomers(String query);
}

					

The DerbyCustomerDAO implements the CustomerDAO as shown in code below:


import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Collection;

public class DerbyCustomerDAO implements CustomerDAO {

    Connection con;
    ResultSet rs;
    Statement stmt;

    public DerbyCustomerDAO() throws SQLException {
        con = getConnection();
    }

    private Connection getConnection() throws SQLException {
        return DriverManager.getConnection("jdbc:derby:sample;user=mikalai;password=pswd");
    }

    @Override
    public int insertCustomer(Customer c) {
        // ...
    }

    @Override
    public boolean deleteCustomer(Customer c) {
        // ...
    }

    @Override
    public Customer findCustomer(int id) {
        // ...
    }

    @Override
    public boolean updateCustomer(Customer c) {
        // ...
    }

    @Override
    public Collection<Customer> selectCustomers(String query) {
        // ...
    }
}

					



Design a class that uses the Factory design pattern

The Factory Method design pattern is a way to encapsulate object creation. Without a Factory Method, you would simply call the class's constructor directly: Foo x = new Foo(). With this pattern, you would instead call the factory method: Foo x = Foo.create(). The constructors are marked private, so they cannot be called except from inside the class, and the Factory Method is marked as static so that it can be called without first having an object.

Consider the following interface:

public interface Logger {

    // Write out a debug message
    public void debug(String msg);

    // Write out an error message
    public void error(String msg);
}
					

Suppose that you have written two implementations. One implementation writes the messages out to the standard console, while another writes them to a file:

public class ConsoleLogger implements Logger {

    ConsoleLogger() {} // Not accessible from other packages !

    public void debug(String msg) {
        out.println("DEBUG: " + msg);
    }

    public void error( String msg) {
        out.println("ERROR: " + msg);
    }
}
					

public class FileLogger implements Logger {

    private PrintWriter pw;

    FileLogger() throws IOException { // Not accessible from other packages !
        // throws java.io.FileNotFoundException if the file does not exist
        pw = new PrintWriter(new FileWriter("/tmp/logger.log" ) );
    }

    public void debug(String msg) {
        pw.println("DEBUG: " + msg);
        pw.flush();
    }

    public void error(String msg) {
        pw.println("ERROR: " + msg);
        pw.flush();
    }
}
					

Using a Factory Method to obtain an instance can save you a lot of work later. If you use a Factory Method to obtain your instance, you need to make only one change in one class in order to meet the new requirements. You do not need to make changes in every class that uses Logger:

public class LoggerFactory {

    private static Logger l = null;

    public static Logger getLogger() {
        if (l == null) {
            try {
                l = new FileLogger(); // Can fail if log file does not exist
            } catch (IOException e) {
                l = new ConsoleLogger();
            }
        }
        return l;
    }
}
					

Client code will look like:

public class LoggerTest {
     public static void main(String[] args) {
         LoggerFactory.getLogger().debug("Test debug");
         LoggerFactory.getLogger().error("Test error");
    }
}
					

There are a few advantages to this pattern:

  • The Factory can choose from many subclasses (or implementers of an interface) and return that.

    This way the caller can specify the behavior desired via parameters, without having to know or understand a potentially complex class hierarchy.

    For example, some of the methods in java.sql.DriverManager are Factory Methods that return implementation instances by their interface type. By keeping the actual concrete type hidden, the factory has the flexibility to provide any implementing type, even a different one from time to time, without damage to client code. This is part of what is sometimes called, "programming to the interface" or "programming to the type", a best practice of defining behaviors at the interface level and generally hiding the concrete classes involved.

    The conn is actually some DB vendor's class implementing java.sql.Connection interface:

    String url = "jdbc:some_jdbc_vendor:other_data";
    Connection conn = DriverManager.getConnection(url);
    								

  • Controlling access to a limited resource such as connections. This a way to implement pools of reusable objects - instead of building, using, and tearing down an object, if the construction and destruction are expensive processes it might make more sense to build them once and recycle them.

    The Factory Method can return an existing, unused instantiated object if it has one, or construct one if the object count is below some lower threshold, or throw an exception or return null if it is above the upper threshold.

  • Factory Methods have names, unlike constructors, which can clarify code.

  • Factory Method is useful when working with hierarchies of related classes, a good example of this would be a GUI toolkit.

Today factories have largely been brushed aside in favor of using Dependency Injection (DI) because they require a lot of boiler-plate code that turns out to be a little hard to maintain itself. Dependency Injection is basically equivalent to factories but allows you to specify how your objects get wired together declaratively (through XML configuration or annotations).

Usage of factory Design Patterns in Java Se and Java EE

Abstract factory (recognizeable by creational methods returning an abstract/interface type):

  • java.util.Calendar#getInstance()

  • java.util.Arrays#asList()

  • java.util.ResourceBundle#getBundle()

  • java.net.URL#openConnection()

  • java.sql.DriverManager#getConnection()

  • java.sql.Connection#createStatement()

  • java.sql.Statement#executeQuery()

  • java.text.NumberFormat#getInstance()

Factory method (recognizeable by creational methods returning a concrete type)

  • java.lang.Object#toString() (overrideable in all subclasses)

  • java.lang.Class#newInstance()

  • java.lang.Integer#valueOf(String) (also on Boolean, Byte, Character, Short, Long, Float, and Double)

  • java.lang.Class#forName()

Class NumberFormat

NumberFormat is the abstract base class for all number formats. This class provides the interface for formatting and parsing numbers. NumberFormat also provides methods for determining which locales have number formats, and what their names are.

NumberFormat helps you to format and parse numbers for any locale. Your code can be completely independent of the locale conventions for decimal points, thousands-separators, or even the particular decimal digits used, or whether the number format is even decimal.

To format a number for the current Locale, use one of the factory class methods:

NumberFormat nf	= NumberFormat.getInstance();
String myString = nf.format(myNumber);
					

To format a number for a different Locale, specify it in the call to getInstance(...):

NumberFormat nf = NumberFormat.getInstance(Locale.FRENCH);
					

The NumberFormat class has many factory methods:

public static final NumberFormat getInstance()
public static NumberFormat getInstance(Locale inLocale)

public static final NumberFormat getNumberInstance()
public static NumberFormat getNumberInstance(Locale inLocale)

public static final NumberFormat getIntegerInstance()
public static NumberFormat getIntegerInstance(Locale inLocale)

public static final NumberFormat getCurrencyInstance()
public static NumberFormat getCurrencyInstance(Locale inLocale)

public static final NumberFormat getPercentInstance()
public static NumberFormat getPercentInstance(Locale inLocale)
					



Database Applications with JDBC

JDBC is Sun's attempt to create a platform-neutral interface between databases and Java. With JDBC, you can count on a standard set of database access features and (usually) a particular subset of SQL, SQL-92. The JDBC API defines a set of interfaces that encapsulate major database functionality, including running queries, processing results, and determining configuration information. A database vendor or third-party developer writes a JDBC driver, which is a set of classes that implements these interfaces for a particular database system.

Figure 2.2.  The classes and interfaces of the JDBC API

The classes and interfaces of the JDBC API


  • java.sql.DriverManager - The basic service for managing a set of JDBC drivers.

    public class DriverManager extends Object {
        ...
        static Connection 	getConnection(String url);
        static Connection 	getConnection(String url, Properties info);
        static Connection 	getConnection(String url, String user, String password);
    }
    								

    NOTE: The DataSource interface, new in the JDBC 2.0 API, provides another way to connect to a data source. The use of a DataSource object is the preferred means of connecting to a data source.

    In JDBC 3.0 and earlier, before you can connect to a database, you need to load the driver. Your code implicitly loads the driver using the Class.forName(...) method. For example:

    // Needed with JDBC 3.0 and earlier
    try {
        Class.forName("com.oracle.jdbc.OracleDriver");
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    }
    								

    This will load the driver, and while loading, the driver will automatically register itself with DriverManager class. The forName(...) method can throw a ClassNotFoundException if the driver is not available.

    In JDBC 4.0 and later, applications no longer need to explictly load JDBC drivers using Class.forName(...). Existing programs which currently load JDBC drivers using Class.forName(...) will continue to work without modification.

    When the method getConnection(...) is called, the DriverManager will attempt to locate a suitable driver from amongst those loaded at initialization and those loaded explicitly using the same classloader as the current applet or application.

  • java.sql.Connection - A connection (session) with a specific database. SQL statements are executed and results are returned within the context of a connection.

    public interface Connection extends Wrapper, AutoCloseable {
        ...
        void close() throws SQLException;
    }
    								

    A Connection object's database is able to provide information describing its tables, its supported SQL grammar, its stored procedures, the capabilities of this connection, and so on. This information is obtained with the getMetaData() method.

    The Connection.close() method releases this Connection object's database and JDBC resources immediately instead of waiting for them to be automatically released.

  • java.sql.Statement - The object used for executing a static SQL statement and returning the results it produces.

    public interface Statement extends Wrapper, AutoCloseable {
        ...
        void close() throws SQLException;
    }
    								

    By default, only one ResultSet object per Statement object can be open at the same time. Therefore, if the reading of one ResultSet object is interleaved with the reading of another, each must have been generated by different Statement objects. All execution methods in the Statement interface implicitly close a statment's current ResultSet object if an open one exists.

    The Statement.close() method releases this Statement object's database and JDBC resources immediately instead of waiting for this to happen when it is automatically closed. It is generally good practice to release resources as soon as you are finished with them to avoid tying up database resources. Calling the method close() on a Statement object that is already closed has no effect. NOTE: when a Statement object is closed, its current ResultSet object, if one exists, is also closed.

  • java.sql.PreparedStatement - An object that represents a precompiled SQL statement.

    public interface PreparedStatement extends Statement {
        ...
    }
    								

    A SQL statement is precompiled and stored in a PreparedStatement object. This object can then be used to efficiently execute this statement multiple times.

  • java.sql.ResultSet - A table of data representing a database result set, which is usually generated by executing a statement that queries the database.

    public interface ResultSet extends Wrapper, AutoCloseable {
        ...
    }
    								

    A ResultSet object maintains a cursor pointing to its current row of data. Initially the cursor is positioned BEFORE the first row. The next() method moves the cursor to the next row, and because it returns false when there are no more rows in the ResultSet object, it can be used in a while loop to iterate through the result set.

    A default ResultSet object is not updatable and has a cursor that moves forward only. Thus, you can iterate through it only once and only from the first row to the last row. It is possible to produce ResultSet objects that are scrollable and/or updatable. The following code fragment, in which con is a valid Connection object, illustrates how to make a result set that is scrollable and insensitive to updates by others, and that is updatable:

    Statement stmt = con.createStatement(
        ResultSet.TYPE_SCROLL_INSENSITIVE,
        ResultSet.CONCUR_UPDATABLE
    );
    
    ResultSet rs = stmt.executeQuery("SELECT ID, NAME FROM PERSON");
    
    // rs will be scrollable, will not show changes made by others,
    // and will be updatable
    								

    The ResultSet interface provides getter methods (getBoolean, getLong, and so on) for retrieving column values from the current row. Values can be retrieved using either the index number of the column or the name of the column. In general, using the column index will be more efficient. Columns are numbered from 1. For maximum portability, result set columns within each row should be read in left-to-right order, and each column should be read only once.

    For the getter methods, a JDBC driver attempts to convert the underlying data to the Java type specified in the getter method and returns a suitable Java value. The JDBC specification has a table showing the allowable mappings from SQL types to Java types that can be used by the ResultSet getter methods.

    Column names used as input to getter methods are case insensitive. When a getter method is called with a column name and several columns have the same name, the value of the first matching column will be returned. The column name option is designed to be used when column names are used in the SQL query that generated the result set. For columns that are NOT explicitly named in the query, it is best to use column numbers. If column names are used, the programmer should take care to guarantee that they uniquely refer to the intended columns, which can be assured with the SQL AS clause.

  • java.sql.ResultSetMetaData - An object that can be used to get information about the types and properties of the columns in a ResultSet object.

    
    public interface ResultSetMetaData extends Wrapper {
        ...
    }
    								

    The following code fragment creates the ResultSet object rs, creates the ResultSetMetaData object rsmd, and uses rsmd to find out how many columns rs has:

    ResultSet rs = stmt.executeQuery("SELECT ID, NAME FROM PERSON");
    ResultSetMetaData rsmd = rs.getMetaData();
    int numberOfColumns = rsmd.getColumnCount();
    								

  • java.sql.DatabaseMetaData - Comprehensive information about the database as a whole.

    public interface DatabaseMetaData extends Wrapper {
        ...
    }
    								

    This interface is implemented by driver vendors to let users know the capabilities of a Database Management System (DBMS) in combination with the driver based on JDBC technology ("JDBC driver") that is used with it. Different relational DBMSs often support different features, implement features in different ways, and use different data types. In addition, a driver may implement a feature on top of what the DBMS offers. Information returned by methods in this interface applies to the capabilities of a particular driver and a particular DBMS working together. Note that as used in this documentation, the term "database" is used generically to refer to both the driver and DBMS.