0% found this document useful (0 votes)
29 views11 pages

Design Patterns: Abstract Factory & Singleton

The document discusses several design patterns including Abstract Factory, Singleton, and Factory Method. The Abstract Factory pattern provides interfaces for creating families of related objects without specifying their concrete classes. The Singleton pattern ensures a class has only one instance and provides a global point of access to it. The Factory Method pattern provides an interface for creating objects in a superclass, but allows subclasses to decide which objects to create.

Uploaded by

api-26221029
Copyright
© Attribution Non-Commercial (BY-NC)
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOC, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
29 views11 pages

Design Patterns: Abstract Factory & Singleton

The document discusses several design patterns including Abstract Factory, Singleton, and Factory Method. The Abstract Factory pattern provides interfaces for creating families of related objects without specifying their concrete classes. The Singleton pattern ensures a class has only one instance and provides a global point of access to it. The Factory Method pattern provides an interface for creating objects in a superclass, but allows subclasses to decide which objects to create.

Uploaded by

api-26221029
Copyright
© Attribution Non-Commercial (BY-NC)
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOC, PDF, TXT or read online on Scribd

1

DESIGN PATTERN
The design patterns are language-independent strategies for solving common
object-oriented design problems.

Patterns are not methods or framework


Patterns give you hint to solve a problem effectively

Abstract Factory
Suppose you need to write a program to show data in two different places. Let's say from a local
or a remote database. You need to make a connection to a database before working on the data.
In this case, you have two choices, local or remote. You may use abstract factory design pattern
to design the interface in the following way:

class DataInfo {}
interface Local {
DataInfo[] loadDB(String filename);
}

interface Remote extends Local{


void connect2WWW(String url);
}

class LocalMode implements Local {


public DataInfo[] loadDB(String name) {
[Link]("Load from a local database ");
return null;
}
}

class RemoteMode implements Remote {


public void connect2WWW(String url) {
[Link]("Connect to a remote site ");
}
public DataInfo[] loadDB(String name) {
[Link]("Load from a remote database ");
return null;
}
}
2

// The Abstract Factory


interface ConnectionFactory {
Local getLocalConnection();
Remote getRemoteConnection();
}

class DataManager implements ConnectionFactory {


boolean local = false;
DataInfo[] data;
//...
public Local getLocalConnection() {
return new LocalMode();
}
public Remote getRemoteConnection() {
return new RemoteMode();
}
public void loadData() {
if(local){
Local conn = getLocalConnection();
data = [Link]("[Link]");
}else {
Remote conn = getRemoteConnection();
conn.connect2WWW("[Link]");
data = [Link]("[Link]");
}

}
// work on data

public void setConnection(boolean b) {


local = b;
}
}

Singleton
Ensure unique instance by defining class final to prevent cloning.

May be extensible by the subclass by defining subclass final.

Make a method or a variable public or/and static.

Access to the instance by the way you provided.

Well control the instantiation of a class.

Define one value shared by all instances by making it static.


3

[Link]

Implementing Singleton Pattern

To implement this design pattern we need to consider the following 4 steps:

Step 1: Provide a default Private constructor

public class SingletonObjectDemo {

// Note that the constructor is private


private SingletonObjectDemo() {
// Optional Code
}
}

Step 2: Create a Method for getting the reference to the Singleton Object

public class SingletonObjectDemo {

private static SingletonObject singletonObject;


// Note that the constructor is private
private SingletonObjectDemo() {
// Optional Code
}
public static SingletonObjectDemo getSingletonObject() {
if (singletonObject == null) {
singletonObject = new SingletonObjectDemo();
}
return singletonObject;
}
}
We write a public static getter or access method to get the instance of the Singleton
Object at runtime. First time the object is created inside this method as it is null.
Subsequent calls to this method returns the same object created as the object is
globally declared (private) and the hence the same referenced object is returned.

Step 3: Make the Access method Synchronized to prevent Thread Problems.

public static synchronized SingletonObjectDemo getSingletonObject()

It could happen that the access method may be called twice from 2 different classes
at the same time and hence more than one object being created. This could violate
the design patter principle. In order to prevent the simultaneous invocation of the
getter method by 2 threads or classes simultaneously we add the synchronized
keyword to the method declaration
4

Step 4: Override the Object clone method to prevent cloning

We can still be able to create a copy of the Object by cloning it using the Object’s
clone method. This can be done as shown below

SingletonObjectDemo clonedObject = (SingletonObjectDemo) [Link]();

This again violates the Singleton Design Pattern's objective. So to deal with this we
need to override the Object’s clone method which throws a
CloneNotSupportedException exception.

public Object clone() throws CloneNotSupportedException {


throw new CloneNotSupportedException();
}

The below program shows the final Implementation of Singleton Design Pattern in java, by using
all the 4 steps mentioned above.

class SingletonClass {

private static SingletonClass singletonObject;


/** A private Constructor prevents any other class from instantiating. */
private SingletonClass() {
// Optional Code
}
public static synchronized SingletonClass getSingletonObject() {
if (singletonObject == null) {
singletonObject = new SingletonClass();
}
return singletonObject;
}
public Object clone() throws CloneNotSupportedException {
throw new CloneNotSupportedException();
}
}

public class SingletonObjectDemo {

public static void main(String args[]) {


// SingletonClass obj = new SingletonClass();
//Compilation error not allowed
SingletonClass obj = [Link]();
// Your Business Logic
[Link]("Singleton object obtained");
}
}

Download [Link]

Another approach
5

We don't need to do a lazy initialization of the instance object or to check for null in the get
method. We can also make the singleton class final to avoid sub classing that may cause other
problems.

public class SingletonClass {

private static SingletonClass ourInstance


= new SingletonClass();
public static SingletonClass
getInstance() {
return singletonObj;
}
private SingletonClass() {
}
}

Double-checked locking

Double-checked locking is a technique that, at first glance, appears to make lazy instantiation
thread-safe. That technique is illustrated in the following code fragment:

public static Singleton getInstance() {


if(singleton == null) {
synchronized([Link]) {
if(singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}

What happens if two threads simultaneously access getInstance()? Imagine Thread 1 enters
the synchronized block and is preempted. Subsequently, a second thread enters the if block.
When Thread 1 exits the synchronized block, Thread 2 makes a second check to see if the
singleton instance is still null. Since Thread 1 set the singleton member variable, Thread 2's
second check will fail, and a second singleton will not be created. Or so it seems.

Use reflection

Example 9 lists a singleton with a registry that uses reflection to instantiate a particular class's
objects. With this implementation, as opposed to Example 8, the [Link]()
method does not need to update when new subclasses are implemented.
6

Example 9. Use reflection to instantiate singletons


import [Link];
import [Link];
public class Singleton {
private static HashMap map = new HashMap();
private static Logger logger = [Link]();
protected Singleton() {
// Exists only to thwart instantiation
}
public static synchronized Singleton getInstance(String classname) {
Singleton singleton = (Singleton)[Link](classname);
if(singleton != null) {
[Link]("got singleton from map: " + singleton);
return singleton;
}
try {
singleton = (Singleton)[Link](classname).newInstance();
}
catch(ClassNotFoundException cnf) {
[Link]("Couldn't find class " + classname);
}
catch(InstantiationException ie) {
[Link]("Couldn't instantiate an object of type " + classname);
}
catch(IllegalAccessException ia) {
[Link]("Couldn't access class " + classname);
}
[Link](classname, singleton);
[Link]("created singleton: " + singleton);
return singleton;
}
}

Factory Method
Definition

Provides an abstraction or an interface and lets subclass or implementing classes decide which
class or method should be instantiated or called, based on the conditions or parameters given.

Connect parallel class hierarchies.


A class wants its subclasses to specify the object.
A class cannot anticipate its subclasses, which must be created.
A family of objects needs to be separated by using shared interface.
The code needs to deal with interface, not implemented classes.
Hide concrete classes from the client.
Factory methods can be parameterized.
The returned object may be either abstract or concrete object.
7

Examples

To illustrate such concept, let's use a simple example. To paint a picture, you may need several
steps. A shape is an interface. Several implementing classes may be designed in the following
way.

interface Shape {
public void draw();
}
class Line implements Shape {
Point x, y;
Line(Point a, Point b) {
x = a;
y = b;
}
public void draw() {
//draw a line;
}
}
class Square implements Shape {
Point start;
int width, height;
Square(Point s, int w, int h) {
start = s;
width = w;
height = h;
}
public void draw() {
//draw a square;
}
}
class Circle implements Shape {
....
}

class Painting {
Point x, y;
int width, height, radius;
Painting(Point a, Point b, int w, int h, int r) {
x = a;
y = b;
width = w;
height = h;
radius = r;
}
Shape drawLine() {
return new Line(x,y);
}
Shape drawSquare() {
return new Square(x, width, height);
}
Shape drawCircle() {
8

return new Circle(x, radius);


}
....
}

...
Shape pic;
Painting pt;
//initializing pt
....
if (line)
pic = [Link]();
if (square)
pic = [Link]();
if (circle)
pic = [Link]();

From the above example, you may see that the Shape pic's type depends on the condition given.
The variable pic may be a line or square or a circle.

You may use several constructors with different parameters to instantiate the object you want. It
is another way to design with Factory pattern. For example,

class Painting {
...
Painting(Point a, Point b) {
new Line(a, b); //draw a line
}
Painting(Point a, int w, int h) {
new Square(a, w, h); //draw a square
}
Painting(Point a, int r){
new Circle(a, r); //draw a circle
}
...
}

You may use several methods to finish the drawing jobs. It is so-called factory method pattern.
for example,

class Painting {
...
Painting(Point a, Point b) {
draw(a, b); //draw a line
}
Painting(Point a, int w, int h) {
draw(a, w, h); //draw a square
}
9

Painting(Point a, int r){


draw(a, r); //draw a circle
}
...
}

The above draw() methods are overloaded.

Façade
Definition

Make a complex system simpler by providing a unified or general interface, which is a higher
layer to these subsystems.

Where to use & benefits

• Want to reduce complexities of a system.


• Decouple subsystems , reduce its dependency, and improve portability.
• Make an entry point to your subsystems.
• Minimize the communication and dependency between subsystems.
• Security and performance consideration.

Example

JDBC design is a good example of Façade pattern. A database design is complicated. JDBC is
used to connect the database and manipulate data without exposing details to the clients.

Security of a system may be designed with Façade pattern. Clients' authorization to access
information may be classified. General users may be allowed to access general information;
special guests may be allowed to access more information; administrators and executives may be
allowed to access the most important information. These subsystems may be generalized by one
interface. The identified users may be directed to the related subsystems.

interface General {
public void accessGeneral();
}
interface Special extends General {
public void accessSpecial();
}
interface Private extends General {
public void accessPrivate();
}

class GeneralInfo implements General {


public void accessGeneral() {
//...
10

}
//...
}
class SpecialInfo implements Special{
public void accessSpecial() {
//...
}
public void accessGeneral() {}
//...
}
class PrivateInfo implements Private, Special {
public void accessPrivate() {
// ...
}
public void accessSpecial() {
//...
}
public void accessGeneral() {
// ...
}
//...
}

class Connection {
//...

if (user is unauthorized) throw new Exception();


if (user is general) return new GeneralInfo();
if (user is special) return new SpecialInfo();
if (user is executive) return new PrivateInfo();
//...
}

The above code example illustrates that the whole system is not exposed to the clients. It
depends on the user classification.

Mr. SudHakar Chavali proposes a better design, similar to the above, but avoids repeated code.
Look at code below.
interface General {
public void accessGeneral();
}

interface Special extends General {

public void accessSpecial();

interface Private extends General {

public void accessPrivate();

class GeneralInfo implements General {


11

public void accessGeneral() {

//...
}

//...
}

class SpecialInfo extends GeneralInfo implements Special{

public void accessSpecial() {

//...
}

class PrivateInfo extends SpecialInfo implements Private {

public void accessPrivate() {

// ...

//...
}

To avoid repeated code, SpecialInfo become subclass of GeneralInfo and PrivateInfo becomes
subclass of SpecialInfo. When a person is exposed to special information, that person is allowed
to access general information also. When a person is exposed to private information, that person
is allowed to access general information and special information also.

You might also like