Sunday, August 31, 2014

Structural design patterns in Java

Simple examples of using structural design patterns in Java.
List of them from wikipedia:
Examples of Structural Patterns include:
  • Adapter pattern: 'adapts' one interface for a class into one that a client expects
    • Adapter pipeline: Use multiple adapters for debugging purposes.[1]
    • Retrofit Interface Pattern:[2][3] An adapter used as a new interface for multiple classes at the same time.
  • Bridge pattern: decouple an abstraction from its implementation so that the two can vary independently
    • Tombstone: An intermediate "lookup" object contains the real location of an object.[4]
  • Composite pattern: a tree structure of objects where every object has the same interface
  • Decorator pattern: add additional functionality to a class at runtime where subclassing would result in an exponential rise of new classes
  • Facade pattern: create a simplified interface of an existing interface to ease usage for common tasks
  • Flyweight pattern: a high quantity of objects share a common properties object to save space
  • Proxy pattern: a class functioning as an interface to another thing

1. Adapter pattern.

 Actors:
  1. "convenient" interface
  2. adapter class which adapt "non-convenient" classes to match "convenient" interface
  Goal: using methods of interface on class which doesn't implements that interface using adaptor class.

Main class:

public class Adaptor {
    
    public interface Movable {
        String move();
    }
    
    public class Shape {
        private String name;
        
        public Shape(String name) {
            this.name=name;
        }
        
        public String relocate() {
            return "shape "+name+" is relocated";
        }
    }
    
    public class ShapeToMovableAdaptor implements Movable {
        
        private Shape shape;
        
        public ShapeToMovableAdaptor(Shape shape) {
            this.shape=shape;
        }

        @Override
        public String move() {          
            return shape.relocate();
        }   
    }
}



Test class:

public class AdaptorTest {
    
    @Test
    public void test() {
        Adaptor adaptor=new Adaptor();
        
        Adaptor.Shape shape=adaptor. new Shape("circle");
        
        Adaptor.Movable shapeAdaptor=adaptor. new ShapeToMovableAdaptor(shape);
        
        String result=shapeAdaptor.move();
        
        Assert.assertEquals("shape circle is relocated", result);
    }

}


2. Bridge

  Actors:
    1. Implementation
    2. Abstraction - which depends(aggregate) on Implementation (for instance, Implementation set in constructor)
    3. Concrete classes which extends Abstraction
  Goal: implementation separated from abstraction
Main class:


public class Bridge {
    
    interface Implementation {
        String move();
    }
    
    class FastImplementation implements Implementation {
        @Override
        public String move() {
            return "fast";
        }       
    }
    
    class SlowImplementation implements Implementation {
        @Override
        public String move() {
            return "slow";
        }       
    }   
    
    
    public abstract class Abstraction{
        
        Implementation implementation;
        
        public Abstraction(Implementation implementation) {
            this.implementation=implementation;
        }
        
        public String rellocate() {
            return implementation.move() +" rellocation";
        }
        
    }
    
    public class ConcreteSlowClass extends Abstraction {

        public ConcreteSlowClass() {
            super(new SlowImplementation());
        }
        
    }
    
    public class ConcreteFastClass extends Abstraction {

        public ConcreteFastClass() {
            super(new FastImplementation());
        }
        
    }   
}

Test class:

public class BridgeTest {

    @Test
    public void test() {
        Bridge bridge=new Bridge();
        
        Bridge.ConcreteFastClass fast=bridge. new ConcreteFastClass();
        assertEquals("fast rellocation", fast.rellocate());
        
        
        Bridge.ConcreteSlowClass slow=bridge. new ConcreteSlowClass();
        assertEquals("slow rellocation", slow.rellocate());
    }

}

3. Composite

Actors:
  1. interface
  2. simple object which implements interface
  3. complex object(contain set of simple objects) with implements interface
  Goal:
  Do some logic with set(array) of objects like one single object
Main class:


public class Composite {

    public interface drawable {
        String draw();
    }

    public class SimpleObject implements drawable {

        String name;

        @Override
        public String draw() {
            return "drawing " + name;
        }

        public SimpleObject(String name) {
            this.name = name;
        }

    }

    public class CompositeObject implements drawable {

        List<Composite.SimpleObject> objects=new ArrayList<Composite.SimpleObject>();

        public void addObject(Composite.SimpleObject object) {
            objects.add(object);
        }

        @Override
        public String draw() {
            StringBuilder result = new StringBuilder();

            for (Composite.SimpleObject object : objects) {
                result.append(object.draw() + ".");
            }

            return result.toString();
        }

Test class:

    }

}
public class CompositeTest {

    @Test
    public void test() {
        Composite composite=new Composite();
        
        Composite.SimpleObject simple1=composite. new SimpleObject("first");
        assertEquals("drawing first", simple1.draw());
        
        Composite.SimpleObject simple2=composite. new SimpleObject("second");
        
        Composite.CompositeObject complex=composite. new CompositeObject();
        complex.addObject(simple1);
        complex.addObject(simple2);
                
        assertEquals("drawing first.drawing second.", complex.draw());
                
    }

}

4. Decorator

  Actors:
  1. original class
  2. decorator class which wrap original class
  Goal: extend functionality of original class
Main class:


public class Decorator {
    
    public static class Shape {
        public String draw() {
            return "shape";
        }
    }
    
    public static class RedDecorator  {
        private Shape shape;

        public RedDecorator(Shape shape) {
            this.shape=shape;
        }

        public String drawRed() {
            return shape.draw()+" is red";
            
        }       
    }
    
    public static class BigDecorator {
        private RedDecorator redDecorator;

        public BigDecorator(RedDecorator redDecorator) {
            this.redDecorator=redDecorator;
        }

        public String drawBig() {
            return redDecorator.drawRed()+" and big";
            
        }       
    }   

}

Test class:

public class DecoratorTest {

    @Test
    public void test() {

        String result=new Decorator.BigDecorator(new Decorator.RedDecorator(new Decorator.Shape())).drawBig();


        assertEquals("shape is red and big", result);
        
    }

}

5. Facade

Actors:
  1. set of classes  (library)
  2. facade class for managing them
  Goal: interface for library: one class which manage other classes

Main class:

public class Facade {
    
    public interface Drawable {
        public String draw();
    }
    
    public class Square implements Drawable {

        @Override
        public String draw() {          
            return "square.";
        }
        
    }
    
    public class Circle implements Drawable {

        @Override
        public String draw() {          
            return "circle.";
        }
        
    }
    
    
    public class ComplexDrawingFacade {
                
        public String drawComplexObject() {
            Square square1=new Square();
            Square square2=new Square();
            Circle circle=new Circle();
            
            String result=square1.draw()+circle.draw()+square2.draw();
            
            return result;      
        }
        
    }

}

Test class:

public class FacadeTest {

    @Test
    public void test() {
        Facade facade=new Facade();
        
        Facade.ComplexDrawingFacade compleDrawingFacade=facade. new ComplexDrawingFacade();
        assertEquals("square.circle.square.", compleDrawingFacade.drawComplexObject());
    }

}

6. FlyWeight

Actors:
 1. set of objects
 2. flyweight(cache) object: contains list of created objects
 Goal: using object cache(for memory minimizing) and object sharing instead of new object creation


public class FlyWeight {
    
    public static abstract class AbstractShape {
        public abstract String draw();
    }
    
    public static class Shape extends AbstractShape {

        @Override
        public String draw() {
            return "shape";
        }       
    }
    
    public static class Circle extends AbstractShape {

        @Override
        public String draw() {
            return "circle";
        }       
    }
    
    public class FlyWeightFactory {
        HashMap<String, AbstractShape> cache=new HashMap<String, AbstractShape>(); 
        public AbstractShape lookUp(Class<?> cl) throws InstantiationException, IllegalAccessException {
            String className=cl.getCanonicalName();
            if (!cache.containsKey(className)) {
                try {
                    Object o=cl.newInstance();
                } catch(Exception e) {
                    e.printStackTrace();
                }
                AbstractShape shape=(AbstractShape)cl.newInstance();
                
                cache.put(className, shape);
            }           
            return cache.get(className);
        }
    }

}

Test class:

public class FlyWeightTest {

    @Test
    public void test() throws InstantiationException, IllegalAccessException {
        
        FlyWeight flyWeight=new FlyWeight();
        FlyWeight.FlyWeightFactory factory=flyWeight. new FlyWeightFactory();
        
        
        FlyWeight.AbstractShape circle=factory.lookUp(FlyWeight.Circle.class);
        FlyWeight.AbstractShape shape=factory.lookUp(FlyWeight.Shape.class);
        
        assertEquals("shape", shape.draw());
        assertEquals("circle", circle.draw());
        
    }

}

7. Proxy

Actors:
  1. remote object
  2. local proxy class which has the same interface as remote object
  3. local client, which works with proxy as like it is remote object
  Goal : make client independent of remote object and connection. 
  Also proxy object can add some addition functionality, checking and other stuff.

Main class:

public class Proxy {
    
    interface Drawable {
        String draw();
    }
    
    public class RealImplementation implements Drawable {

        @Override
        public String draw() {
            return "real draw";
        }
        
    }
    
    public class ProxyImplementation extends RealImplementation {
        
        RealImplementation realImplementation=new RealImplementation();

        @Override
        public String draw() {
            // do some logic
            return realImplementation.draw();
            // do some logic
        }
        
    }

}

Test class:

public class ProxyTest {

    @Test
    public void test() {
        Proxy proxy=new Proxy();
        Proxy.RealImplementation remoteObject=proxy. new ProxyImplementation();
        assertEquals("real draw", remoteObject.draw());
        
    }

}



Creational design patterns in Java

In this post, I'm going to show samples of using creational design patterns in Java.
List of them from wikipedia:
  • Abstract factory pattern, which provides an interface for creating related or dependent objects without specifying the objects' concrete classes.[3]
  • Builder pattern, which separates the construction of a complex object from its representation so that the same construction process can create different representation.
  • Factory method pattern, which allows a class to defer instantiation to subclasses.[4]
  • Prototype pattern, which specifies the kind of object to create using a prototypical instance, and creates new objects by cloning this prototype.
  • Singleton pattern, which ensures that a class only has one instance, and provides a global point of access to it.[5]
Let's consider them closely. 

1. Abstract factory.

Actors: 
 1.abstract factory - interface which defines factory which can be returned.
 2.concrete factory:  concrete class which implements abstract factory and returns implementations of factories.  
Goal: create in one step different objects using different creation classes(factories).
Main class:
public class AbstractFactory {
    
    public static abstract class AbstractShapeFactory {
        public abstract RedShapeFactory getRedShapeFactory();
        public abstract BlackShapeFactory getBlackShapeFactory();
    }
    
    public static abstract class Drawable {
        protected String pattern;
        public Drawable(String pattern) {
            this.pattern=pattern;
        }
        public abstract String createShape(String pattern);
    }
    
    public static class RedShapeFactory extends Drawable {

        public RedShapeFactory(String pattern) {
            super(pattern);
        }

        @Override
        public String createShape(String pattern) {
            return "red "+pattern;          
        }       
    }
    
    public static class BlackShapeFactory extends Drawable {
        public BlackShapeFactory(String pattern) {
            super(pattern);
        }

        @Override
        public String createShape(String pattern) {
            return "black "+pattern;            
        }       
    }
    
    public static class ShapeFactory extends AbstractShapeFactory {
        private final String pattern;
        
        public ShapeFactory(String pattern) {
            this.pattern=pattern;
        }

        @Override
        public RedShapeFactory getRedShapeFactory() {
            return new RedShapeFactory(pattern);
        }

        @Override
        public BlackShapeFactory getBlackShapeFactory() {
            return new BlackShapeFactory(pattern);
        }
        
    }

}


Test class:


import org.junit.Before;
import org.junit.Test;

public class AbstractFactoryTest {
    
    AbstractFactory.ShapeFactory factory;
    String pattern;
    
    @Before
    public void init() {
        pattern="square";
    }

    @Test
    public void blackFactoryTest() {
        factory=new AbstractFactory.ShapeFactory(pattern);
        String result=factory.getBlackShapeFactory().createShape(pattern);
        assertEquals("black square", result);
    }

    @Test
    public void redFactoryTest() {
        factory=new AbstractFactory.ShapeFactory(pattern);
        String result=factory.getRedShapeFactory().createShape(pattern);
        assertEquals("red square", result);
    }
}

2. Factory method

May be the simplest matters: very often developers starts with this pattern and later migrate to more complex solutions.  
Actors: 
1.factory method class with different methods for creation different classes
Goal: 
create in one step different objects using different functions.
Main class:

public class FactoryMethod {
    
    public String createRedSquareStringObject() {
        return "red square";
    }
    
    public String createBlackSquareStringObject() {
        return "black square";
    }

}

Test class:

public class FactoryMethodTest {
    
    private FactoryMethod factory=new FactoryMethod();
    
    @Test
    public void readSquareTest() {
        String shape=factory.createRedSquareStringObject();
        Assert.assertEquals("red square", shape);
    }
    
    @Test
    public void blackSquareTest() {
        String shape=factory.createBlackSquareStringObject();
        Assert.assertEquals("black square", shape);
    }

}

3. Builder

Actors: builder class with methods for adding components to the created object.
Goal: create different objects(with different components) in few steps.
Main class:

public class Builder {
    
    public void addFundament(StringBuilder object) {
        object.append("fundament ");
    } 
    
    public void addFloor(StringBuilder object) {
        object.append("floor ");
    }
    
    public void addMansarda(StringBuilder object) {
        object.append("mansarda");
    }   
    
    public void addRoof(StringBuilder object) {
        object.append("roof");
    }
 
}

Test class:

public class BuilderTest {
    
    private Builder builder=new Builder(); 
    
    @Test
    public void oneFlootBuildingWithRoofTest() {
        StringBuilder building=new StringBuilder();
        
        builder.addFundament(building);
        builder.addFloor(building);
        builder.addRoof(building);
        
        Assert.assertEquals("fundament floor roof", building.toString());
         
    }
    
    @Test
    public void threeFlootBuildingWithMansardaTest() {
        StringBuilder building=new StringBuilder();
        
        builder.addFundament(building);
        builder.addFloor(building);
        builder.addFloor(building);
        builder.addFloor(building);
        builder.addMansarda(building);
        
        Assert.assertEquals("fundament floor floor floor mansarda", building.toString());
         
    }   

}

4.Singleton

Actors: class with static instance 
Goal: only one instance of object can be created and  used by other objects.
Main class:


public enum Singleton {
        INSTANCE;
        
        public String data;
        
}

Test class:

public class SingletonTest {
    
    @Test
    public void test() {
        Singleton s1=Singleton.INSTANCE;
        Singleton s2=Singleton.INSTANCE;
        s1.data="Hello world!";
        Assert.assertEquals(s1.data, s2.data);      
    }
}

5.Prototype

Actors: class which implements Clonable interface
 Goal: sometimes when object has a lot of properties, it's easier to clone object than execute setXXX a lot of times.
Main class:

public class Prototype {
    
    public class ComplexObject implements Cloneable{
                
        private String name;
        private String description;
        private String department;
        
        public ComplexObject(String name, String description, String department) {
            super();
            this.name = name;
            this.description = description;
            this.department = department;
        }
        
        public ComplexObject clone() throws CloneNotSupportedException {
            return (ComplexObject)super.clone();
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public String getDescription() {
            return description;
        }

        public void setDescription(String description) {
            this.description = description;
        }

        public String getDepartent() {
            return department;
        }

        public void setDepartent(String departent) {
            this.department = departent;
        }
    }
}

Test class:





public class PrototypeTest {
    
    @Test
    public void test() throws CloneNotSupportedException {
        Prototype prototype=new Prototype();
        
        Prototype.ComplexObject complexObject1= prototype. new ComplexObject("name", "description", "departent");
        Prototype.ComplexObject complexObject2=complexObject1.clone();
        
        Assert.assertEquals(complexObject1.getName(), complexObject2.getName());
        Assert.assertEquals(complexObject1.getDescription(), complexObject2.getDescription());
        Assert.assertEquals(complexObject1.getDepartent(), complexObject2.getDepartent());
        
    }

}