0% found this document useful (0 votes)
14 views

Java Patterns

The document discusses various creational design patterns in Java including the Factory Method pattern, Abstract Factory pattern, Singleton pattern, Builder pattern, and Prototype pattern. The Factory Method pattern provides a simple decision making class that returns one of several possible subclasses of an abstract base class depending on the data provided. The Abstract Factory pattern provides an interface to create and return one of several families of related objects. The Singleton pattern ensures there is only one instance of a class and provides a global access point. The Builder pattern separates object construction from representation so different representations can be created. The Prototype pattern starts with an initialized instance and clones it to make new instances rather than creating new ones.

Uploaded by

Iulian Marcu
Copyright
© © All Rights Reserved
Available Formats
Download as DOC, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
14 views

Java Patterns

The document discusses various creational design patterns in Java including the Factory Method pattern, Abstract Factory pattern, Singleton pattern, Builder pattern, and Prototype pattern. The Factory Method pattern provides a simple decision making class that returns one of several possible subclasses of an abstract base class depending on the data provided. The Abstract Factory pattern provides an interface to create and return one of several families of related objects. The Singleton pattern ensures there is only one instance of a class and provides a global access point. The Builder pattern separates object construction from representation so different representations can be created. The Prototype pattern starts with an initialized instance and clones it to make new instances rather than creating new ones.

Uploaded by

Iulian Marcu
Copyright
© © All Rights Reserved
Available Formats
Download as DOC, PDF, TXT or read online on Scribd
You are on page 1/ 16

Java Patterns

Creational Patterns
The Factory Method provides a simple decision making class that
returns one of several possible subclasses of an abstract base class depending
on the data that are provided.

The Abstract Factory Method provides an interface to create and


return one of several families of related objects.

The Singleton Pattern is a class of which there can be no more than


one instance. It provides a single global point of access to that instance.

The Builder Pattern separates the construction of a complex object


from its representation, so that several different representations can be created
depending on the needs of the program.

The Prototype Pattern starts with an initialized and instantiated


class and copies or clones it to make new instances rather than creating new
instances.
The Factory Pattern
Factory of what? Of classes. In simple words, if we have a super class and n sub-classes, and based on
data provided, we have to return the object of one of the sub-classes, we use a factory pattern.

a) The skeleton of the code can be given here.

public class Person {


// name string
public String name;
// gender : M or F
private String gender;

public String getName() {


return name;
}

public String getGender() {


return gender;
}
}// End of class

public class Male extends Person {


public Male(String fullName) {
System.out.println("Hello Mr. "+fullName);
}
}// End of class

public class Female extends Person {


public Female(String fullNname) {
System.out.println("Hello Ms. "+fullNname);
}
}// End of class

public class SalutationFactory {

public static void main(String args[]) {


SalutationFactory factory = new SalutationFactory();
factory.getPerson(args[0], args[1]);
}

public Person getPerson(String name, String gender) {


if (gender.equals("M"))
return new Male(name);
else if(gender.equals("F"))
return new Female(name);
else
return null;
}
}// End of class

b) The skeleton of the code can be given here.

//a simple class to take a string apart into two names


class Namer {

//store last name here


protected String last;
//store first name here
protected String first;

//return first name


public String getFirst() {
return first;
}

//return last name


public String getLast() {
return last;
}
}

//split first last


class FirstFirst extends Namer {

public FirstFirst(String s) {
//find sep space
int i = s.lastIndexOf(" ");
if (i > 0) {
//left is first name
first = s.substring(0, i).trim();
//right is last name
last =s.substring(i+1).trim();
} else {
// put all in last name
first = “”;
// if no space
last = s;
}
}
}

//split last, first


class LastFirst extends Namer {

public LastFirst(String s) {
//find comma
int i = s.indexOf(",");
if (i > 0) {
//left is last name
last = s.substring(0, i).trim();
//right is first name
first = s.substring(i + 1).trim();
} else {
last = s; // put all in last name
first = ""; // if no comma
}
}
}

//returns an instance of LastFirst or FirstFirst


//depending on whether a comma is found
class NameFactory {

public Namer getNamer(String entry) {


//comma determines name order
int i = entry.indexOf(",");
//return one class
if (i>0) {
return new LastFirst(entry);
} else {
return new FirstFirst(entry); //or the other
}
}

public static void main(String args[]) {

NameFactory nfactory = new NameFactory();

//send the text to the factory and get a class back


namer = nfactory.getNamer(entryField.getText());
//compute the first and last names
//using the returned class
txFirstName.setText(namer.getFirst());
txLastName.setText(namer.getLast());
}
}

c) The skeleton of the code can be given here.


class Complex {
float real;
float imag;
}

abstract class Butterfly {


float y;

public Butterfly() {
}

public Butterfly(float angle) {


y = angle;
}
abstract public void Execute(Complex x, Complex y);
}

class addButterfly extends Butterfly {


float oldr1, oldi1;

public addButterfly(float angle) {


}

public void Execute(Complex xi, Complex xj) {


oldr1 = xi.getReal();
oldi1 = xi.getImag();
//add and subtract
xi.setReal(oldr1 + xj.getReal());
xj.setReal(oldr1 - xj.getReal());
xi.setImag(oldi1 + xj.getImag());
xj.setImag(oldi1 - xj.getImag());
}
}

class trigButterfly extends Butterfly {


float y;
float oldr1, oldi1;
float cosy, siny;
float r2cosy, r2siny, i2cosy, i2siny;

public trigButterfly(float angle) {


y = angle;
//precompute sine and cosine
cosy = (float) Math.cos(y);
siny = (float)Math.sin(y);
}

public void Execute(Complex xi, Complex xj) {


//multiply by cos and sin
oldr1 = xi.getReal();
oldi1 = xi.getImag();
r2cosy = xj.getReal() * cosy;
r2siny = xj.getReal() * siny;
i2cosy = xj.getImag()*cosy;
i2siny = xj.getImag()*siny;
//store sums
xi.setReal(oldr1 + r2cosy +i2siny);
xi.setImag(oldi1 - r2siny +i2cosy);
xj.setReal(oldr1 - r2cosy - i2siny);
xj.setImag(oldi1 + r2siny - i2cosy);
}
}

class Cocoon {
public Butterfly getButterfly(float y) {
if (y !=0) {
//get multiply class
return new trigButterfly(y);
} else {
//get add/sub class
return new addButterfly(y);
}
}
}

When to Use a Factory Pattern


· A class can’t anticipate which kind of class of objects it must create.
· A class uses its subclasses to specify which objects it creates.
· You want to localize the knowledge of which class gets created.

· When a class does not know which class of objects it must create.
· A class specifies its sub-classes to specify which objects to create.
· In programmer’s language (very raw form), you can use factory pattern where you have to create an
object of any one of sub-classes depending on the data provided.

There are several similar variations on the factory pattern to recognize.


1. The base class is abstract and the pattern must return a complete working class.
2. The base class contains default methods and is only subclassed for cases where the default methods
are insufficient.
3. Parameters are passed to the factory telling it which of several class types to return. In this case the
classes may share the same method names but may do something quite different.
Abstract Factory Pattern
This pattern is one level of abstraction higher than factory pattern. This means that the abstract factory
returns the factory of classes. Like Factory pattern returned one of the several sub-classes, this returns
such factory which later will return one of the sub-classes.

a) The different parts of computer are, say Monitor, RAM and Processor. The different types of
computers are PC, Workstation and Server.

So, here we have an abstract base class Computer.

package creational.abstractfactory;

public abstract class Computer {


/**
* Abstract method, returns the Parts ideal for
* Server
* @return Parts
*/
public abstract Parts getRAM();
/**
* Abstract method, returns the Parts ideal for
* Workstation
* @return Parts
*/
public abstract Parts getProcessor();

/**
* Abstract method, returns the Parts ideal for
* PC
* @return Parts
*/
public abstract Parts getMonitor();
}// End of class

package creational.abstractfactory;

public class Parts {


/**
* specification of Part of Computer, String
*/
public String specification;
/**
* Constructor sets the name of OS
* @param specification of Part of Computer
*/
public Parts(String specification) {

this.specification = specification;
}

/**
* Returns the name of the part of Computer
*
* @return specification of Part of Computer, String
*/
public String getSpecification() {
return specification;
}

}// End of class


package creational.abstractfactory;

public class PC extends Computer {


/**
* Method over-ridden from Computer, returns the Parts ideal for
* Server
* @return Parts
*/
public Parts getRAM() {
return new Parts("512 MB");
}
/**
* Method over-ridden from Computer, returns the Parts ideal for
* Workstation
* @return Parts
*/
public Parts getProcessor() {
return new Parts("Celeron");
}

/**
* Method over-ridden from Computer, returns the Parts ideal for
* PC
* @return Parts
*/
public Parts getMonitor() {
return new Parts("15 inches");
}
}// End of class

package creational.abstractfactory;

public class Workstation extends Computer {


/**
* Method over-ridden from Computer, returns the Parts ideal for
* Server
* @return Parts
*/
public Parts getRAM() {
return new Parts("1 GB");
}

/**
* Method over-ridden from Computer, returns the Parts ideal for
* Workstation
* @return Parts
*/
public Parts getProcessor() {
return new Parts("Intel P 3");
}

/**
* Method over-ridden from Computer, returns the Parts ideal for
* PC
* @return Parts
*/
public Parts getMonitor() {
return new Parts("19 inches");
}
}// End of class
package creational.abstractfactory;

public class Server extends Computer{


/**
* Method over-ridden from Computer, returns the Parts ideal for
* Server
* @return Parts
*/
public Parts getRAM() {
return new Parts("4 GB");
}

/**
* Method over-ridden from Computer, returns the Parts ideal for
* Workstation
* @return Parts
*/
public Parts getProcessor() {
return new Parts("Intel P 4");
}

/**
* Method over-ridden from Computer, returns the Parts ideal for
* PC
* @return Parts
*/
public Parts getMonitor() {
return new Parts("17 inches");
}
}// End of class

package creational.abstractfactory;

/**
* This is the computer abstract factory which returns one
* of the three types of computers.
*
*/
public class ComputerType {
  private Computer comp;
public static void main(String[] args) {
    ComputerType type = new ComputerType();
Computer computer = type.getComputer("Server");
System.out.println("Monitor:
"+computer.getMonitor().getSpecification());
System.out.println("RAM: "+computer.getRAM().getSpecification());
System.out.println("Processor:
"+computer.getProcessor().getSpecification());
  }       
/**
* Returns a computer for a type
*
* @param computerType String, PC / Workstation / Server
* @return Computer
*/
public Computer getComputer(String computerType) {    
if (computerType.equals("PC")) {
comp = new PC();
} else if(computerType.equals("Workstation")) {
comp = new Workstation();
} else if(computerType.equals("Server")) {
comp = new Server();
return comp;
}  
}
}// End of class

b) Suppose you are writing a program to plan the layout of gardens.


These could be annual gardens, vegetable gardens or perennial gardens.

public abstract class Garden {


public abstract Plant getCenter();
public abstract Plant getBorder();
public abstract Plant getShade();
}

public class Plant {


String name;
public Plant(String pname) {
name = pname; //save name
}
public String getName() {
return name;
}
}

public class VegieGarden extends Garden {


public Plant getShade() {
return new Plant("Broccoli");
}
public Plant getCenter() {
return new Plant("Corn");
}
public Plant getBorder() {
return new Plant("Peas");
}
}

//Abstract Factory which returns one of three gardens


class GardenMaker
{
private Garden gd;
public Garden getGarden(String gtype)
{ //default
gd = new VegieGarden();
if(gtype.equals("Perennial")) {
gd = new PerennialGarden(); }
if(gtype.equals("Annual")) {
gd = new AnnualGarden(); }
return gd;
}
}

When to Use Abstract Factory Pattern ?


One of the main advantages of Abstract Factory Pattern is that it isolates the concrete classes that
are generated. The names of actual implementing classes are not needed to be known at the client
side. Because of the isolation, you can change the implementation from one factory to another.
Singleton Pattern
This is one of the most commonly used patterns. There are some instances in the application where
we have to use just one instance of a particular class.
Builder Pattern
Builder, as the name suggests builds complex objects from simple ones step-by-step. It separates the
construction of complex objects from their representation.

a) To build a house, we will take several steps:


build foundation,
build frame,
build exterior,
build interior

import java.util.*;

class WorkShop {
//force the order of building process
public void construct(HouseBuilder hb) {
hb.buildFoundation();
hb.buildFrame();
hb.buildExterior();
hb.buildInterior();
}
}

//set steps for building a house


abstract class HouseBuilder {
protected House house = new House();

protected String showProgress() {


return house.toString();
}

abstract public void buildFoundation();


abstract public void buildFrame();
abstract public void buildExterior();
abstract public void buildInterior();
}

class OneStoryHouse extends HouseBuilder {

public OneStoryHouse(String features) {


house.setType(this.getClass() + " " + features);
}
public void buildFoundation() {
//doEngineering()
//doExcavating()
//doPlumbingHeatingElectricity()
//doSewerWaterHookUp()
//doFoundationInspection()
house.setProgress("foundation is done");
}

public void buildFrame() {


//doHeatingPlumbingRoof()
//doElectricityRoute()
//doDoorsWindows()
//doFrameInspection()
house.setProgress("frame is done");
}

public void buildExterior() {


//doOverheadDoors()
//doBrickWorks()
//doSidingsoffitsGutters()
//doDrivewayGarageFloor()
//doDeckRail()
//doLandScaping()
house.setProgress("Exterior is done");
}

public void buildInterior() {


//doAlarmPrewiring()
//doBuiltinVacuum()
//doInsulation()
//doDryWall()
//doPainting()
//doLinoleum()
//doCabinet()
//doTileWork()
//doLightFixtureBlinds()
//doCleaning()
//doInteriorInspection()
house.setProgress("Interior is under going");
}
}

class TwoStoryHouse extends HouseBuilder {

public TwoStoryHouse(String features) {


house.setType(this.getClass() + " " + features);
}
public void buildFoundation() {
//doEngineering()
//doExcavating()
//doPlumbingHeatingElectricity()
//doSewerWaterHookUp()
//doFoundationInspection()
house.setProgress("foundation is done");
}

public void buildFrame() {


//doHeatingPlumbingRoof()
//doElectricityRoute()
//doDoorsWindows()
//doFrameInspection()
house.setProgress("frame is under construction");
}

public void buildExterior() {


//doOverheadDoors()
//doBrickWorks()
//doSidingsoffitsGutters()
//doDrivewayGarageFloor()
//doDeckRail()
//doLandScaping()
house.setProgress("Exterior is waiting to start");
}

public void buildInterior() {


//doAlarmPrewiring()
//doBuiltinVacuum()
//doInsulation()
//doDryWall()
//doPainting()
//doLinoleum()
//doCabinet()
//doTileWork()
//doLightFixtureBlinds()
//doCleaning()
//doInteriorInspection()
house.setProgress("Interior is not started yet");
}
}

class House {
private String type = null;
private List features = new ArrayList();

public House() {

public House(String type) {


this.type = type;
}

public void setType(String type) {


this.type = type;
}

public String getType() {


return type;
}

public void setProgress(String s) {


features.add(s);
}

public String toString() {


StringBuffer ff = new StringBuffer();
String t = type.substring(6);
ff.append(t + "\n ");
for (int i = 0; i < features.size(); i ++) {
ff.append(features.get(i) + "\n ");
}
return ff.toString();
}
}

class TestBuilder {

public static void main(String[] args) {

HouseBuilder one = new OneStoryHouse("2 bedrooms, 2.5 baths, 2-car garage,


1500 sqft");
HouseBuilder two = new TwoStoryHouse("4 bedrooms, 4 baths, 3-car garage, 5000
sqft");

WorkShop shop = new WorkShop();


shop.construct(one);
shop.construct(two);
System.out.println("Check house building progress: \n");
System.out.println(one.showProgress());
System.out.println(two.showProgress());
}
}

b)
package creational.builder;

public interface Item {


/**
* pack is the method, as every item will be packed
* in a different way.
* E.g.:- The burger will be packed as wrapped in a paper
* The cold drink will be given in a glass
* The medium fries will be packed in a card box and
* The toy will be put in the bag straight.
* The class Packing is an interface for different types of
* for different Items.
*/
public Packing pack();
/**
* price is the method as all the items
* burger, cold drink, fries will have a price.
* The toy will not have any direct price, it will
* be given free with the meal.
*
* The total price of the meal will be the combined
* price of the three items.
*
* @return price, int in rupees.
*/

public int price();

}// End of class

package creational.builder;
/**
* The class remains abstract as price method will be implemented
* according to type of burger.
* @see price()
*
*/
public abstract class Burger implements Item {
/**
* A burger is packed in a wrapper. Its wrapped
* in the paper and is served. The class Wrapper is
* sub-class of Packing interface.
* @return new Wrapper for every burger served.
*/
public Packing pack() {
return new Wrapper();
}

/**
* This method remains abstract and cannot be
* given an implementation as the real implementation
* will lie with the type of burger.
* E.g.:- Veg Burger will have a different price from
* a fish burger.
* @return price, int.
*/
public abstract int price();
}// End of class

package creational.builder;

/**
* The implementation of price method.
*/
public class VegBurger extends Burger {
/**
* This is the method implementation from
* the super class Burger.
* @return price of a veg burger in rupees.
*/
public int price() {
return 39;
}
}// End of class

package creational.builder;

/**
* Implements the Item interface.
*/
public class Fries implements Item {
/**
* Packing in which fries are served.
*
* @return new Packing for every fries.
* Envelop is a packing in which fries are given
*/
public Packing pack() { return new Envelop(); }

/**
* Price of the medium fries.
*
* @return int , price of medium fries in rupees
*/
public int price() { return 25; }

}// End of class


package creational.builder;

/**
* Main builder class which builds the entire meal
* for the customers
*/
public class MealBuilder {

public Packing additems() {


Item[] items = {new VegBurger(), new Fries(), new Cola(), new Doll()}
return new MealBox().addItems(items);
}

public int calculatePrice() {


int totalPrice = new VegBurger().price() + new Cola().price() + new
Fries().price() + new Doll().price();
return totalPrice;
}
}// End of class

When to Use Builder Pattern ?


 Make a complex object by specifying only its type and content. The built object is shielded
from the details of its construction.

 Want to decouple the process of building a complex object from the parts that make up the
object.

 Isolate code for construction and representation.

 Give you finer control over the construction process.

 Related patterns include

o Abstract Factory, which focuses on the layer over the factory pattern (may be simple
or complex), whereas a builder pattern focuses on building a complex object from
other simple objects.

o Composite, which is often used to build a complex object.

Prototype Pattern
The prototype means making a clone. This implies cloning of an object to avoid creation. If the
cost of creating a new object is large and creation is resource intensive, we clone the object. We use
the interface Cloneable and call its method clone() to clone the object.

You might also like