Sunday, July 17, 2011

Design Patterns2(Abstract Factory, Bridge, Facade)

Hey ...

Do you remember my past post about design patterns? Here I'm going to continue it.

4. Abstract Factory
4.1. Pattern Goal
The abstract factory pattern is a software design pattern that provides a way to encapsulate a group of individual factories that have a common theme. In normal usage, the client software creates a concrete implementation of the abstract factory and then uses the generic interfaces to create the concrete objects that are part of the theme. The client does not know (or care) which concrete objects it gets from each of these internal factories since it uses only the generic interfaces of their products. This pattern separates the details of implementation of a set of objects from their general usage.

In software development, a factory is the location in the code at which objects are constructed. The intent in employing the pattern is to insulate the creation of objects from their usage. This allows for new derived types to be introduced with no change to the code that uses the base class.

Use of this pattern makes it possible to interchange concrete implementations without changing the code that uses them, even at runtime. However, employment of this pattern, as with similar design patterns, may result in unnecessary complexity and extra work in the initial writing of code. Used correctly the "extra work" pays off in the second implementation of the factory.
4.2 Pattern Detail
In this pattern we should have 2 kinds of interfaces and classes. 1: Concrete Products 2:Concrete Factories
Please take a look to this class diagram:
as you see there are two kinds of classes. Factory classes are responsible for creation their own class. Client(Application) should only uses ConcreteFactory class and retrieve an object type of ConcreteProduct class.
4.3 Pattern sample
In this sample we want to have a block to support templates. We place a key property containing template name. When we change the template key to green or blue, the block color should change its color. To do that we need 2 interfaces:
public interface Panel {
    public String paint(String value);
}
public interface PanelFactory {
    public Panel createPanel();
}
two classes should implement Panel. Each class should implement its own color:
public class GreenPanel implements Panel{
    public String paint(String value) {
        return "<div style='border-width:1px; border-color:green; border-style:solid; margin:2px; padding:2px; color:green'>" + value + "</div>";
    }
}
public class BluePanel implements Panel{
    public String paint(String value) {
        return "<div style='border-width:1px; border-color:blue; border-style:solid; margin:2px; padding:2px; color:blue'>" + value + "</div>";
    }
}
And two classes should implement PanelFactory:
public class BluePanleFactory implements PanelFactory{
    public Panel createPanel() {
        return new BluePanel();
    }
}
public class GreenPanelFactory implements PanelFactory{
    public Panel createPanel() {
        return new GreenPanel();
    }
}
Now its join time. we should make a class to use a PanelFactory to create a Panel object and use its method:
public class PageUIManager {
    Panel panel;

    public PageUIManager(PanelFactory panelFactory) {
        this.panel = panelFactory.createPanel();
    }

    public String createPageElements(String value){
        return this.panel.paint(value);
    }
}
And here is the use of PageUIManager class:
@Controller
@Scope("prototype")
@RequestMapping("/graphicalpage")
public class PageController {
    @ModelAttribute("pagebody")
    public String pageBody() {
        ResourceBundle rb = ResourceBundle.getBundle("edu.patterns.abstractfactory.theme");
        if (rb.getObject("currentTheme").equals("blue")) {
            return (new PageUIManager(new BluePanleFactory())).createPageElements("This page color will be changed if you set 'currentTheme' key to 'green' value in edu.patterns.abstractfactory.theme file.");
        }
        return (new PageUIManager(new GreenPanelFactory())).createPageElements("This page color will be changed if you change 'currentTheme' key to 'blue' value in edu.patterns.abstractfactory.theme file.");
    }

    @RequestMapping("/view")
    public String View() {
        return "graphicalpage.view";
    }
}

This class checks the resource bundle if decide which panel should be displayed.

5. Bridge
5.1 Pattern Goal
The bridge pattern is a design pattern used in software engineering which is meant to "decouple an abstraction from its implementation so that the two can vary independently".The bridge uses encapsulation, aggregation, and can use inheritance to separate responsibilities into different classes.
When a class varies often, the features of object-oriented programming become very useful because changes to a program's code can be made easily with minimal prior knowledge about the program. The bridge pattern is useful when both the class as well as what it does vary often.
5.2 Pattern Detail
This pattern has four major classes. Please Take a look here:
Abstraction:
    defines the abstract interface
    maintains the Implementor reference
RefinedAbstraction:
    extends the interface defined by Abstraction
Implementor:
    defines the interface for implementation classes
ConcreteImplementor:
    implements the Implementor interface

On the other hands, whenever we have some classes with the same materials(ConcreteImplementor), we can standardize them with an super class(Implementor), then we can make a Bridge to connect and maintain them. We can generalise it because each set of Implementor classes has its own protocols(Abstraction). Finally the bridge implementation classes implement Abstraction class and during its implementation they will follow set of Implementor classes protocol.
5.3 Pattern Sample
We are going to create some components for HTML pages. All of them are containing component. This is the share point of them. I'll show you how to create them with Bridge pattern.
First of all I should define the component standard:
public abstract class Container {
    private Map<String, String> styles;

    protected Container() {
        this.styles = new HashMap<String, String>();
    }

    public void addStyle(String key, String value){
        styles.put(key, value);
    }

    protected String renderStyles(){
        if (!styles.isEmpty()) {
            String[] styleArray = new String[styles.size()];
            int i = 0;
            for (String key : styles.keySet()) {
                styleArray[i++] = key + ":" + styles.get(key);
            }
            return "style='" + org.springframework.util.StringUtils.arrayToDelimitedString(styleArray, ";") + "'";
        }
        return "";
    }
    public abstract String startTag();

    public abstract String endTag();
}
As you see every component classes should implement startTag and endTag method. It also has a style attribute type of List and two usefull method for that: addStyle to add a new style and renderStyle to render the list of styles as HTML styles.
Now its the time to implement the component classes. They should implement Container.
public class Div extends Container {

    public String startTag() {
        return "<div " + renderStyles() + ">";
    }

    public String endTag() {
        return "</div>";
    }
}
public class Paragraph extends Container {
    public String startTag() {
        return "<p " + renderStyles() + ">";
    }

    public String endTag() {
        return "</p>";
    }
}
public class Span extends Container {
    public String startTag() {
        return "<span " + renderStyles() + ">";
    }

    public String endTag() {
        return "</span>";
    }
}
every componets implement its own tag as easy as possible via the two methods wich is determined in super class.
Now its the time of bridge class. It has some fields which will be render as html styles in Container class. So the role of this class is a bridge with client class and Container class. Take a look here:
public abstract class ContainerBridge {
    int width;
    int height;
    String color;
    String backgroundColor;
    int borderWidth;
    String borderColor;
    String borderStyle;

    protected Container implementor;

    protected ContainerBridge(Container implementor) {
        this.implementor = implementor;
    }

    public int getWidth() {
        return width;
    }

    public void setWidth(int width) {
        this.width = width;
        implementor.addStyle("width", (new Integer(width)).toString());
    }

    public int getHeight() {
        return height;
    }

    public void setHeight(int height) {
        this.height = height;
        implementor.addStyle("height", (new Integer(height)).toString());
    }

    public String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
        implementor.addStyle("color", color);
    }

    public String getBackgroundColor() {
        return backgroundColor;
    }

    public void setBackgroundColor(String backgroundColor) {
        this.backgroundColor = backgroundColor;
        implementor.addStyle("background-color", backgroundColor);
    }

    public int getBorderWidth() {
        return borderWidth;
    }

    public void setBorderWidth(int borderWidth) {
        this.borderWidth = borderWidth;
        implementor.addStyle("border-width", (new Integer(borderWidth)).toString());
    }

    public String getBorderColor() {
        return borderColor;
    }

    public void setBorderColor(String borderColor) {
        this.borderColor = borderColor;
        implementor.addStyle("border-color", borderColor);
    }

    public String getBorderStyle() {
        return borderStyle;
    }

    public void setBorderStyle(String borderStyle) {
        this.borderStyle = borderStyle;
        implementor.addStyle("border-style", borderStyle);
    }

    public abstract String wrapText(String text);
}
As you see it maintains Componet passed parameter in constructor as a field(implementor) and  in every setter method it adds a new attribute in style of implementor.This class has also an abstract method called wrapText which should be implemented.
Finally we should implement Bridge class. HtmlContainer will do it:
public class HTMLContainer extends ContainerBridge {
    public HTMLContainer(Container implementor) {
        super(implementor);
    }

    public String wrapText(String text) {
        return implementor.startTag() + text + implementor.endTag();
    }
}
As you see in HTML we should start a tag and place our text then close the tag. This class follows this standard and implement it.

Now its the time to use these tage. we do it in BridgeController:
@Controller
@Scope("prototype")
@RequestMapping("/bridgecontroller")
public class BridgeController {
    @ModelAttribute("pagebody")
    public String pageBody() {
        HTMLContainer div = new HTMLContainer(new Div());
        div.setWidth(200);
        div.setHeight(100);
        div.setColor("lightgray");
        div.setBackgroundColor("gray");

        HTMLContainer p = new HTMLContainer(new Paragraph());
        p.setBorderStyle("solid");
        p.setBorderWidth(1);
        p.setBorderColor("black");
        p.setColor("green");
        p.setWidth(200);
        p.setBackgroundColor("orange");

        HTMLContainer span = new HTMLContainer(new Span());
        span.setColor("lightblue");
        span.setBackgroundColor("brown");
        return div.wrapText("this is div tag from bridge pattern. width:200; height:100; Color:lightgray; Background Color:gray")
                + p.wrapText("this is p tag from bridge pattern. width:200; Border Style:solid; Border Width:1; Border Color:black; Color:cyan; Background Color:orange")
                + span.wrapText("this is span tag from bridge pattern. Color:lightblue; BackgroundColor:brown");
    }

    @RequestMapping("/view")
    public String View() {
        return "bridgecontroller.view";
    }

}

3. Facade
3.1 Pattern Goal
The facade pattern is a software engineering design pattern commonly used with Object-oriented programming. The name is by analogy to an architectural facade.
A facade is an object that provides a simplified interface to a larger body of code, such as a class library. A facade can:
  • make a software library easier to use, understand and test, since the facade has convenient methods for common tasks;
  • make code that uses the library more readable, for the same reason;
  • reduce dependencies of outside code on the inner workings of a library, since most code uses the facade, thus allowing more flexibility in developing the system;
  • wrap a poorly-designed collection of APIs with a single well-designed API (as per task needs).
An Adapter is used when the wrapper must respect a particular interface and must support a polymorphic behavior. On the other hand, a facade is used when one wants an easier or simpler interface to work with.
3.2 Pattern Detail
Facade is a simple class which know when and how to create and use other classes and methods of them. Take a look here:
3.3 Pattern Sample
We have a list of people. Suppose that they are our employee so they have these fields:
public class Person {
    Long id;
    String firstname;
    String lastname;
    Long durationTime;
    Long fractionTime;
    Long overtime;
    Long contraction;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getFirstname() {
        return firstname;
    }

    public void setFirstname(String firstname) {
        this.firstname = firstname;
    }

    public String getLastname() {
        return lastname;
    }

    public void setLastname(String lastname) {
        this.lastname = lastname;
    }

    public Long getDurationTime() {
        return durationTime;
    }

    public void setDurationTime(Long durationTime) {
        this.durationTime = durationTime;
    }

    public Long getFractionTime() {
        return fractionTime;
    }

    public void setFractionTime(Long fractionTime) {
        this.fractionTime = fractionTime;
    }

    public Long getOvertime() {
        return overtime;
    }

    public void setOvertime(Long overtime) {
        this.overtime = overtime;
    }

    public Long getContraction() {
        return contraction;
    }

    public void setContraction(Long contraction) {
        this.contraction = contraction;
    }
}
duration fraction and over times are in minutes and contraction is amount of person salary per hour. PersonSalary is a class wich maintain the person salary:
public class PersonSalary{
    Person person;
    Long salary;

    public PersonSalary(Person person, Long salary) {
        this.person = person;
        this.salary = salary;
    }

    public Person getPerson() {
        return person;
    }

    public void setPerson(Person person) {
        this.person = person;
    }

    public Long getSalary() {
        return salary;
    }

    public void setSalary(Long salary) {
        this.salary = salary;
    }
}
We have claculator class for duration, overtime and fractiontime.
public class DurationCalculator {
    public Long calculate(Person p) {
        return (p.getDurationTime() / 60) * p.getContraction();
    }
}
public class OvertimeCalculator {
    Long overtimeFactor;

    public OvertimeCalculator(Long overtimeFactor) {
        this.overtimeFactor = overtimeFactor;
    }

    public Long calculate(Person p) {
        return (p.getOvertime() / 60) * overtimeFactor * p.getContraction();
    }
}
public class FractiontimeCalculator {
    Long fractiontimeFactor;

    public FractiontimeCalculator(Long fractiontimeFactor) {
        this.fractiontimeFactor = fractiontimeFactor;
    }

    public Long calculate(Person p) {
        return (p.getFractionTime() / 60) * fractiontimeFactor * p.getContraction();
    }
}
the salary formula is: duration salary(duration / 60 * contraction) + overtime salary(overtime / 60 * contraction * overtime factor) - fractiontime salary(fractiontime / 60 * contraction * fractiontime factor)
every parantheses will calculate in calculator class but the facade class is responsible for create these calculator class and summation and subtraction of them:
public class CalculatorFacade {
    public static final Long OVER_TIME_FACTORLONG = 2l;
    public static final Long FRACTMENT_TIME_FACTORLONG = 3l;

    Person person;
    DurationCalculator durationCalculator;
    OvertimeCalculator overtimeCalculator;
    FractiontimeCalculator fractiontimeCalculator;

    public CalculatorFacade(Person person) {
        this.person = person;
        durationCalculator = new DurationCalculator();
        overtimeCalculator = new OvertimeCalculator(OVER_TIME_FACTORLONG);
        fractiontimeCalculator = new FractiontimeCalculator(FRACTMENT_TIME_FACTORLONG);
    }

    public Long calculate() {
        return durationCalculator.calculate(person) + overtimeCalculator.calculate(person) - fractiontimeCalculator.calculate(person);
    }
}
The client class should only create CalculatorFacade and then use the calculate method of it:
@Controller
@Scope("prototype")
@RequestMapping("/employee")
public class EmployeeController {

    public List<PersonSalary> initPersonSalary() {
        List<PersonSalary> personSalaryList = new ArrayList<PersonSalary>();

        Person p1 = new Person();
        p1.setId(1l);
        p1.setFirstname("Jack");
        p1.setLastname("Shepard");
        p1.setContraction(50l);
        p1.setDurationTime(10200l);
        p1.setOvertime(900l);
        p1.setFractionTime(300l);

        Person p2 = new Person();
        p2.setId(2l);
        p2.setFirstname("John");
        p2.setLastname("Luke");
        p2.setContraction(40l);
        p2.setDurationTime(10800l);
        p2.setOvertime(480l);
        p2.setFractionTime(120l);

        Person p3 = new Person();
        p3.setId(3l);
        p3.setFirstname("Mostafa");
        p3.setLastname("Rastgar");
        p3.setContraction(60l);
        p3.setDurationTime(11400l);
        p3.setOvertime(1200l);
        p3.setFractionTime(0l);

        personSalaryList.add(new PersonSalary(p1, 0l));
        personSalaryList.add(new PersonSalary(p2, 0l));
        personSalaryList.add(new PersonSalary(p3, 0l));
        return personSalaryList;
    }

    @ModelAttribute("personList")
    public List<PersonSalary> getPersonList() {
        return initPersonSalary();
    }

    @RequestMapping("/view")
    public String View() {
        return "employee.view";
    }

    @RequestMapping("/calculate")
    public String calculate(@ModelAttribute("personList") List<PersonSalary> personSalaryList) {
        for (PersonSalary p : personSalaryList) {
            CalculatorFacade calculatorFacade = new CalculatorFacade(p.getPerson());
            p.setSalary(calculatorFacade.calculate());
        }
        return View();
    }
}

Source Code

You can download those 3 samples(Abstract Factory, Bridge, Facade) and old 3 samples(Singleton, Decorator, Immutable Class) from here. After the deployment the start page is: http://localhost:8080/button/view.html



all rights reserved by Mostafa Rastgar and Programmer Assistant weblog

2 comments:

omidbiz said...

Learning new technology is like reading a good book, learning patterns is like learning to read

good post

mostafa rastgar said...

But I hate to read something. I just like to learn.