blogger templates blogger widgets
This is part of a list of blog posts.
To browse the contents go to

Structural Design Patterns


Adapter pattern

It’s used so that two unrelated interfaces can work together. The object that joins these unrelated interface is called an Adapter.


interface Draw {
	public void draw();
}

class Circle implements Draw {

	@Override
	public void draw() {
		println("Drawing a circle");
	}
}


interface Polygon {
	public void getSides();
	public void getArea();
}

class Square implements Polygon {

	int length;

	Square(int length){
		this.length = length;
	}

	@Override
	public void getSides() {
		println("Sides: 4");
	}

	@Override
	public void getArea() {
		println("Area: "+length*length);
	}
}


Client:

Draw drawingObj = null;

drawingObj = new Circle();
drawingObj.draw();

//Now lets say the client wants to draw a Square but it
//doesn't implement Draw
//drawingObj = new Square();
//drawingObj.draw() //this is not possible so we write a adapter

//in case of object adapters
drawingObj = new SquareAdapter(new Square(5));
drawingObj.draw();
((SquareAdapter) drawingObj).getSquare().getSides();
((SquareAdapter) drawingObj).getSquare().getArea();

//in case of inherited adapters
drawingObj = new SquareAdapter(5);
drawingObj.draw();
((Square) drawingObj).getSides();
((Square) drawingObj).getArea();


Object composition adapters


class SquareAdapter implements Draw {

	Polygon square;

	public SquareAdapter(Polygon square){
		this.square = square;
	}

	@Override
	public void draw(){
		println("Drawing a square");
	}

	public Polygon getSquare() {
		return square;
	}
}

Class inheritance adapters


class SquareAdapter extends Square implements Draw {

	SquareAdapter(int length) {
		super(length);
	}

	@Override
	public void draw(){
		println("Drawing a square");
	}
}
Output:
[main] Drawing a circle [main] Drawing a square [main] Sides: 4 [main] Area: 25
JDK: java.util.Arrays#asList() java.io.InputStreamReader(InputStream) (returns a Reader) java.io.OutputStreamWriter(OutputStream) (returns a Writer) Composite pattern is used when we have to represent a part-whole hierarchy. When we need to create a structure in a way that the objects in the structure has to be treated the same way. Client:

//Initialize leafs ellipses
Ellipse ellipse1 = new Ellipse();
Ellipse ellipse2 = new Ellipse();
Ellipse ellipse3 = new Ellipse();

Hexagon hexagon1 = new Hexagon();
Hexagon hexagon2 = new Hexagon();


//Initialize composite graphics
CompositeGraphic graphic = new CompositeGraphic();
CompositeGraphic graphic1 = new CompositeGraphic();
CompositeGraphic graphic2 = new CompositeGraphic();

//Composes the graphics
graphic1.add(ellipse1);
graphic1.add(ellipse2);
graphic1.add(ellipse3);
graphic2.add(hexagon1);
graphic2.add(hexagon2);

graphic.add(graphic1);
graphic.add(graphic2);

//Prints the complete graphic (four times the string "Ellipse").
graphic.print();

/** "Component" */
interface Graphic {

    //Prints the graphic.
    public void print();
}

/**
 * "Composite" 
 * Composite class usually contains a container for Components (list or tree or..)
 * Composite class usually has 3 operations 
 * 1. add objects to the composite 
 * 2. remove objects, iterate objects
 * 3. perform some operation on all or subset of the objects
 */
class CompositeGraphic implements Graphic {

    //Collection of child graphics.
    private List childGraphics = new ArrayList();

    //Prints the graphic.
    public void print() {
        for (Graphic graphic : childGraphics) {
            if(graphic instanceof CompositeGraphic) {
            	System.out.println("> ");
            	graphic.print();
            }
            else
            	graphic.print();
        }
    }

    //Adds the graphic to the composition.
    public void add(Graphic graphic) {
        childGraphics.add(graphic);
    }

    //Removes the graphic from the composition.
    public void remove(Graphic graphic) {
        childGraphics.remove(graphic);
    }
}

/** A "Leaf" Type */
class Ellipse implements Graphic {

    //Prints the graphic.
    public void print() {
        System.out.println("Ellipse");
    }
}

/** Another "Leaf" Type */
class Hexagon implements Graphic {

    //Prints the graphic.
    public void print() {
        System.out.println("Hexagon");
    }
}
JDK: Lots of Data structures like trees follow this design. java.awt.Container#add(Component) Proxy pattern Provide a surroage or placeholder for another object to control access to it Client:

CommandExecutor cmdExec = new CommandExecutorImpl();
cmdExec.runCommand("rm");

//to force any client to use restricted access
//do not expose CommandExecutorImpl class to the client instead expose
//the proxy class

CommandExecutor cmdExecProxy = new CommandExecutorProxy("supr", "asdf");
cmdExecProxy.runCommand("rm");

interface CommandExecutor {
	public void runCommand(String cmd);
}

class CommandExecutorImpl implements CommandExecutor {

	@Override
	public void runCommand(String cmd) {
		println("Running command: " + cmd);

	}
}


class CommandExecutorProxy implements CommandExecutor {
	private CommandExecutor executor;

	public CommandExecutorProxy(String user, String pwd) {
		// authenticate that the user has privileges
		// if he doesn't have then don't create the
		// dummy impl follows
		if ("super".equals(user) && pwd != null) {
			executor = new CommandExecutorImpl();
		}

	}

	@Override
	public void runCommand(String cmd) {
		if (cmd.trim().startsWith("rm")) {
			// not allowed for any user using the proxy
			println("not allowed");
		} else {
			executor.runCommand(cmd);
		}
	}
}
JDK: Java RMI Flyweight pattern Is used when we need to create a lot of Objects of a class. Since every object consumes memory space that can be crucial for low memory devices Intrinsic properties make the Object unique whereas extrinsic properties are set by client code and used to perform different operations. In below example there are no extrinsic properties. This pattern generally uses factory pattern within itself. Client:

Image img1 = ImageFactory.getImage(ImageType.jpeg);
img1.drawImage();

Image img2 = ImageFactory.getImage(ImageType.jpeg);
img2.drawImage();

Image img3 = ImageFactory.getImage(ImageType.jpeg);
img3.drawImage();

interface Image {
	public void drawImage();
}

class JPEGImage implements Image {

	JPEGImage(){
		println("creating a jpeg image");
		//a sleep added to mean that it's a heavy creation process
		try {
			Thread.sleep(3000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
	
	@Override
	public void drawImage() {
		println("drawing jpeg image");
	}
}

class GIFImage implements Image {

	GIFImage(){
		println("creating a gif image");
		//a sleep added to mean that it's a heavy creation process
		try {
			Thread.sleep(5000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
	
	@Override
	public void drawImage() {
		println("drawing gif image");
	}
	
}

enum ImageType {
	jpeg, gif;
}

class ImageFactory {
	
	public static final Map cache = new HashMap();
	
	public static Image getImage(ImageType imageType) {
		Image image = cache.get(imageType);
		if (image == null) {
			if (imageType.equals(ImageType.jpeg)) {
				image = new JPEGImage();
			} else if (imageType.equals(ImageType.gif)) {
				image = new GIFImage();
			}
			cache.put(imageType, image);
		}
		return image;
	}
}
JDK: wrapper classes valueOf in JDK java string pool Facade pattern Provide a unified interface to a set of interfaces in a subsystem. Facade Pattern defines a higher-level interface that makes the subsystem easier to use. Client:

Shape shape = new Shape();
shape.draw("circle");
shape.draw("square");
shape.draw("square");

class Circle {
	
	public void drawCircle(){
		println("draws a circle");
	}
}

class Square {
	
	public void drawSquare() {
		println("draws a square");
	}
}


//both circle and square classes come from different sources
//they are clossed to modification
//now we create a common interface for accessing both

class Shape {
	Circle circle;
	Square square;

	public void draw(String type) {
		if (type.equals("circle")) {
			if(circle==null)
				circle = new Circle();
			circle.drawCircle();
		} else {
			if(square==null)
				square = new Square();
			square.drawSquare();
		}

	}
}
Decorator pattern We use inheritance or composition to extend the behavior of an object but this is done at compile time and its applicable to all the instances of the class. We can’t add any new functionality of remove any existing behavior at runtime – this is when Decorator pattern comes into picture. Client:

int c;
try {
	InputStream in = new LowerCaseInputStream(new BufferedInputStream(new FileInputStream("test.txt")));

	while ((c = in.read()) >= 0) {
		System.out.print((char) c);
	}

	in.close();
} catch (IOException e) {
}

class LowerCaseInputStream extends FilterInputStream {
	public LowerCaseInputStream(InputStream in) {
		super(in);
	}

	public int read() throws IOException {
		int c = super.read();
		return (c == -1 ? c : Character.toLowerCase((char) c));
	}
}

No comments:

Post a Comment