Inspired from Bangladesh. It's pure java lab. Just exploring the power of Java. Here most of the content collected from web sources, books and etc. If you have any query please drop some line at [email protected]
Avoiding coupling the sender of a request to its receiver by giving more than one object a chance to handle the request.Chain the receiving objects and pass the request along the chain until an object handles it.
The idea of this pattern is to decouple senders and receivers by giving multiple objects a chance to handle a request. The request gets passed along a chain of objects until one of them handles it.
To forward the request along the chain, and to ensure receivers remain implicit, each object on the chain shares a common interface for handling requests and for accessing its successor on the chain.
Extra:
More than one object may handle a request, and the handler isn't known a priori. The handler should be ascertained automatically.
You want to issue a request to one of several objects without specifying the receiver explicitly.
The set of objects that can handle a request should be specified dynamically.
Example:
package com.designpattern.behavioralpattern;
/**
*
* @author collection
*/
public class ChainfOfResponsibilityPattern {
public static void main(String[] args){
Logger logger, logger1, logger2;
logger = new StdoutLogger(Logger.DEBUG);
logger1 = logger.setNext(new EmailLogger(Logger.NOTICE));
logger2 = logger1.setNext(new StderrLogger(Logger.ERR));
logger.message("Entering function y.", Logger.DEBUG);
logger.message("Step1 completed", Logger.NOTICE);
logger.message("An error has occurred.", Logger.ERR);
}
}
abstract class Logger{
public static int ERR = 3;
public static int NOTICE = 5;
public static int DEBUG = 7;
protected int mask;
protected Logger next;
public Logger setNext(Logger log){
next = log;
return log;
}
public void message(String msg, int priority){
if(priority <= mask){
writeMessage(msg);
}
if(next != null){
next.message(msg, priority);
}
}
abstract protected void writeMessage(String msg);
}
class StdoutLogger extends Logger{
public StdoutLogger(int mask){
this.mask = mask;
}
@Override
protected void writeMessage(String msg) {
System.out.println("Writing to stdout: " + msg);
}
}
class EmailLogger extends Logger{
public EmailLogger(int mask){
this.mask = mask;
}
@Override
protected void writeMessage(String msg) {
System.out.println("Sending via email: " + msg);
}
}
class StderrLogger extends Logger{
public StderrLogger(int mask){
this.mask = mask;
}
@Override
protected void writeMessage(String msg) {
System.out.println("Sending to stderr: " + msg);
}
}
Use sharing to support large numbers of fine-grained objects efficiently.
The intent of this pattern is to use sharing to support a large number of objects that have part of their internal state in common where the other part of state can vary.
A flyweight is a shared object that can be used in multiple contexts simultaneously.
The flyweight acts as an independent object in each context- it's indistinguishable from an instance of the object that's not shared.
A flyweight is an object that minimizes memory use by sharing as much data as possible with other similar objects.
It is a way to use objects in large numbers when a simple repeated representation would use an unacceptable amount of memory.
Where it is used:
An application uses a large number of objects.
Storage costs are high because of the sheer quantity of objects
Most object state can be made extrinsic
Many groups of objects may be replaced by relatively few shared objects once extrinsic state is removed.
The application doesn't depend on object identity. Since flyweight objects may be shared, identity tests will return true for conceptually distinct objects.
Example:
package com.designpattern.structuralpattern;
import java.util.HashMap;
import java.util.Map;
/**
*
* @author shaiful islam(palash)
*/
public class FlyweightPattern {
private static CoffeeFlavor[] flavors = new CoffeeFlavor[100];
private static CoffeeOrderContext[] tables = new CoffeeOrderContext[100];
private static int ordersMade = 0;
private static CoffeeFlavorFactory flavorFactory;
public static void takeOrders(String flavorIn, int table){
flavors[ordersMade] = flavorFactory.getCoffeeFlavor(flavorIn);
tables[ordersMade++] = new CoffeeOrderContext(table);
}
public static void main(String[] args){
flavorFactory = new CoffeeFlavorFactory();
takeOrders("Cappuccino", 2);
takeOrders("Xpresso", 121);
for (int i = 0; i < ordersMade; i++) {
flavors[i].serveCoffee(tables[i]);
}
System.out.println("total CoffeeFlavor objects made: " + flavorFactory.getTotalCoffeeFlavorsMade());
}
}
//Flyweight factory
class CoffeeFlavorFactory{
private Map<String, CoffeeFlavor> flavors = new HashMap<String, CoffeeFlavor>();
public CoffeeFlavor getCoffeeFlavor(String flavorName){
CoffeeFlavor flavor = flavors.get(flavorName);
if(flavor == null){
flavor = new CoffeeFlavor(flavorName);
flavors.put(flavorName, flavor);
}
return flavor;
}
public int getTotalCoffeeFlavorsMade(){
return flavors.size();
}
}
interface CoffeOrder{
public void serveCoffee(CoffeeOrderContext context);
}
class CoffeeFlavor implements CoffeOrder{
private String flavor;
public CoffeeFlavor(String newFlavor){
this.flavor = newFlavor;
}
public String getFlavor(){
return this.flavor;
}
@Override
public void serveCoffee(CoffeeOrderContext context) {
System.out.println("Serving coffee flavor " + flavor + " to table number " + context.getTable());
}
}
class CoffeeOrderContext{
private int tableNumber;
public CoffeeOrderContext(int tableNumber){
this.tableNumber = tableNumber;
}
public int getTable(){
return this.tableNumber;
}
}
The compareTo method is the sole method in the java.lang.Comparable interface. It is similar in character to Object's equals method, except that it permits order comparisons in addition to simple equality comparisons. By implementing Comparable, a class indicates that its instances have a natural ordering.
Compares a object with the specified object for order. Returns a negative integer, zero, or a positive integer as this object is less than, equal to, or greater than the specified object. Throws ClassCastException if the specified object's type prevents it from being compared to this project.
The implementor must ensure sgn(x.compareTo(y)) == -sgn(y.compareTo(x)) for all x and y.
The implementor must also ensure that the relation is transitive: (x.compareTo(y)>0 && y.compareTo(z)>0) implies x.compareTo(z)>0.
Finally, the implementor must ensure that x.compareTo(y) == 0 implies that sgn(x.compareTo(z)) == sgn(y.compareTo(z)), for all z.
It is strongly recommended, but not strictly required, that (x.compareTo(y)==0) == (x.equals(y)).
A compareTo method must obey the same restrictions imposed by the equals contract: reflexivity, symmetry, transitivity, and non-nullity. The compareTo method should generally return the same results as the equals method. If this provision is obeyed, the ordering imposed by the compareTo method is said to be consistent with equals. If it's violated, the ordering is said to be inconsistent with equals.
A class whose compareTo method imposes an order that is inconsistent with equals will still work
consider the Float class, whose compareTo method is inconsistent with equals.
If you create a HashSet and add new Float(-0.0f) and new Float(0.0f), the set will
contain two elements because the two Float instances added to the set are unequal when compared using the equals method. If, however, you perform the same procedure using a TreeSet instead of a HashSet, the set will contain only one element because the two Float instances are equal when compared using the compareTo method.
Writing a compareTo method is similar to writing an equals method, but there are a few key differences. You don't need to type check the argument prior to casting. If the argument is not of the appropriate type, the compareTo method should throw a ClassCastException. If the argument is null, the compareTo method should throw a NullPointerException.
The Cloneable interface permit cloning but unfortunately it fails to serve this purpose. Its primary flaw is that it lacks a clone method, and object's clone method is protected.
Actually, Cloneable determines the behavior of Object's protected clone implementation: If a class implements Cloneable, Object's clone method returns a field-by-field copy of the object otherwise it throws CloneNotFoundException. In the case of Cloneable, however, it modifies the behavior of a protected method on a superclass. The Cloneable mechanism is extralinguistic: It creates an object without calling a constructor.
So, Copying an object will typically entail creating a new instance of its class, but it may require copying of internal data structures as well. No constructors called.
Process-1:
If you override the clone method in a nonfianl class, you should return an object obtained by invoking super.clone.
In practise, a class that implements Cloneable is expected to provide a properly functioning public clone method.
public Object clone(){
try{
return super.clone();
}catch(CloneNotSupportException e){}
}
If your object contains fields that refer to mutable objects, using this clone implementation can be disastrous. It will throws ArrayIndexOutOfBoundException.
Process-2:
In effect, the clone method functions as another constructor, you must ensure that it does no harm to the original object and that it properly establishes invarients on the clone. In order for the clone method on Class to work properly, it must copy the internals of the class. The easiest way to do this is by calling clone recursively on the elements array
public Object clone() throws CloneNotSupportedException{
Stack result = (Stack) super.clone();
result.elements = (Object[])elements.clone();
return result;
}
This solution would not work if the composite field were final because the clone method would be prohibited from assigning a new value to the field. The clone architecture is incompatible with normal use of final fields referring to mutable objects. So, In order to make a class cloneable, it may be necessary to remove final modifiers from some fields.
To fix this problem, you'll have to copy the linked list that comprises each object individually. Although this will work when objects aren't too long. If too long this could easily cause a stack overflow.
You are probably better off providing some alternative means of object copying or simply not providing the capability. It doesn't make much sense for immutable classes to support object copying because copies would be virtually indistinguishable from the original.
A fine approach to object copying is to provide a copy constructor.
Facade pattern is used to wrap a set of complex classes into a simpler enclosing interface.
It allows you to simplify this complexity by providing a simplified interface to those subsystems. This simplification might in some cases reduce the flexibility of the underlying classes, but usually it provides all of the function needed for all but the most sophisticated users.
Provides a unified interface to a set of interfaces in a subsystem. Facade defines a higher-level interface that makes the subsystem easier to use.
Clients communicate with the subsystem by sending requests to Facade, which forwards them to the appropriate subsystem objects. Although the subsystem objects perform the actual work, the facade may have to do work of its interface to subsystem interfaces.
Extra:
It shields clients from subsystem components, thereby reducing the number of objects that clients deal with and making the subsystem easier to use.
It promotes weak coupling between the subsystem and its clients.
It doesn't prevent applications from using subsystem classes if they need to.
A facade is an object that provides a simplified interface to a larger body of code, such as class library.
make a software library easier to use, understand and test, since the facade has convenient methods for common tasks
make the library more readable, for the same reason
reduce dependencies of outside code on the inner working 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.
Example:
package com.designpattern.structuralpattern;
/**
*
* @author Shaiful Islam(palash)
*/
class CPU{
public void freeze(){}
public void jump(long position){}
public void execute(){}
}
class Memory{
public void load(long position, byte[] data){}
}
class HardDrive{
public byte[] read(long lba, int size){return null;}
}
class Computer{
private CPU cpu;
private Memory memory;
private HardDrive hardDrive;
public Computer(){
this.cpu = new CPU();
this.memory = new Memory();
this.hardDrive = new HardDrive();
}
public void startComputer(){
cpu.freeze();
memory.load(1, null);
cpu.jump(1);
cpu.execute();
}
}
public class FacadePattern {
public static void main(String[] args){
Computer facade = new Computer();
facade.startComputer();
}
}
Providing a good toString implementation makes your class much more pleasant to use.
The toString method is automatically invoked when your object is passed to println, the string concatenation operator(+) and etc.
The benefits of providing a good toString method extend beyond instances of the class to objects containing references to these instances, especially collections.
When practical, the toString method should return all of the interesting information contained in the object.
One important decision you'll have to make when implementing a toString method is whether to specify the format of the return value in the documentation.
Extra:
Example: BigInteger, BigDecimal and most primitive wrapper classes.
The disadvantages of specifying the format of the toString return value is that once you've specified it, you're stuck with it for life.
Whether or not you decide to specify the format, you should clearly document your intentions.
Example:
package com.effectivejava;
/**
*
* @author Shaiful Islam(palash)
*/
public class Item9 {
public static void main(String[] args){
Telephone telephone = new Telephone(02, 881, 6480);
System.out.println(telephone.toString());
}
}
class Telephone{
private int areadCode;
private int exchange;
private int extension;
public Telephone(int areaCode, int exchange, int extension) {
this.areadCode = areaCode;
this.exchange = exchange;
this.extension = extension;
}
private static String[] ZEROS = {"", "0", "00", "000",
"0000", "00000", "000000", "0000000", "00000000", "000000000"};
@Override
public String toString(){
return "(" + toPaddedString(this.areadCode, 3) + ") " +
toPaddedString(exchange, 3) + "-" +
toPaddedString(extension, 4);
}
private static String toPaddedString(int i, int length){
String s = Integer.toString(i);
return ZEROS[length - s.length()] + s;
}
}
Idea is: The Decorator pattern provides us with a way to modify the behavior of individual objects without having to create a new derived class.
Attach additional responsibilities to an object dynamically.
Decorators provide a flexible alternative to subclassing for extending functionally
Also known as Wrapper
A flexible approach is to enclose the component in another object. The enclosing object is called a decorator.
The decorator conforms forwards requests to the component and may perform additional actions before or after forwarding. Transparency lets you nest decorators recursively, thereby allowing an unlimited number of added responsibilities.
Use decorator to add responsibilities to individual objects dynamically and transparently, that is, without affecting other objects.
Use decorator for responsibilities that can be withdrawn
Decorator forwards requests to its component object. It may optionally perform additional operations before and after forwarding the request.
Extra:
More flexibility than static inheritance
Avoids feature-laden classes high up int the hierarchy. Decorator offers a pay-as-you-go approach to adding responsibilities .
A decorator and its component aren't identical.
Lots of little objects
Decorator wraps the original class. This wrapping could be achieved by the following:
Subclass the original "Decorator" class into a "Component" class
In the decorator class, add a Component pointer as field.
Pass a Component to the Decorator constructor to initialize the Component pointer
In the decorator class, redirect all "Component" methods to the "Component" pointer
In the ConcreteDecorator class, override any component methods whose behavior needs to be modified
Example:-
package com.designpattern.structuralpattern;
/**
*
* @author 154166
*/
public class DecoratorPattern {
public static void main(String[] args){
SimpleWindow simpleWindow = new SimpleWindow();
//simpleWindow.draw();
//System.out.println(simpleWindow.getDescription());
//Window decoratedWindow = new HorizontalScrollBarDecorator(simpleWindow);
Window decoratedWindow = new HorizontalScrollBarDecorator (new VerticalScrollBarDecorator(new SimpleWindow()));
System.out.println(decoratedWindow.getDescription());
}
}
interface Window{
public void draw();
public String getDescription();
}
class SimpleWindow implements Window{
@Override
public void draw(){
System.out.println("Printing something");
}
@Override
public String getDescription(){
return "simple window";
}
}
// abstract decorator class - note that it implements Window
abstract class WindowDecorator implements Window{
protected Window decoratedWindow;
public WindowDecorator(Window decorateWindow){
this.decoratedWindow = decorateWindow;
}
// delegation
@Override
public void draw(){
decoratedWindow.draw();
}
// delegation
@Override
public String getDescription(){
return decoratedWindow.getDescription();
}
}
class VerticalScrollBarDecorator extends WindowDecorator{
public VerticalScrollBarDecorator(Window decoratedWindow){
super(decoratedWindow);
}
@Override
public void draw(){
decoratedWindow.draw();
drawHorizontalScrollBar();
}
private void drawHorizontalScrollBar(){
System.out.println("draw horizontal scroll bar");
}
@Override
public String getDescription(){
return decoratedWindow.getDescription() + ", including vertical scrollbars";
}
}
class HorizontalScrollBarDecorator extends WindowDecorator{
public HorizontalScrollBarDecorator(Window decoratedWindow){
super(decoratedWindow);
}
@Override
public void draw(){
decoratedWindow.draw();
drawHorizontalScrollBar();
}
private void drawHorizontalScrollBar(){
System.out.println("drawing the horizontal scroll bar");
}
@Override
public String getDescription(){
return decoratedWindow.getDescription() + ", including horizontal scrollbars";
}
}
Following procedures can follow to override hashCode method in java:-
Store some constant nonzero value, say 17 in an int variable called result.
For each significant field f in your object(each field taken into account by the equals method, that is), do the following:
Compute an int hash code c for the field:
If the field is a boolean, compute (f ? 0 : 1)
If the field is a byte, char, short, or int, compute (int)f
If the field is a long, compute (int)(f^(f>>>32))
If the field is float compute Float.floatToIntBits(f)
If the field is an object reference and this class's equals method compares the field by recursively invoking equals, recursively invoke hashCode on the field. If a more complex comparison is required, compute a "canonical representation" for this field and invoke hashCode on the canonical representation. If the value of the field is null, return 0 (or some other constant, but 0 is traditional)
If the field is an array, treat it as if each element were a separate field. That is, compute a hash code for each significant element by applying these rules recursively, and combine these values.
Combine the hash code c computed in previous step a into result as follows: result = 37*result + c;
return result
When you are done writing the hashCode method, ask yourself whether equal instances have equal hash codes. If not, figure out why and fix the problem
It is acceptable to exclude redundant fields from the hash code computation. If a class is immutable and the cost of computing the hash code is significant, you might consider caching the hash code in the object rather than recalculating it each time it is requested. Do not be tempted to exclude significant parts of an object from the hash code computation to improve performance.
EJ-8/57: Always override hashCode when you override equals
You must override hashCode in every class that overrides equals. Otherwise, It will prevent your prevent your class from functioning properly in conjunction with all-based collections, including HashMap, HashSet and Hashtable.
java.lang.Object specification:
Whenever it(equals override) is invoked on the same object more than once during an execution of an application, the hashCode method must consistently return the same integer, provided no information used in equals comparisons in the object is modified. This integer need not remain consistent from one execution of an application to another execution of the same application.
It is not required that if two objects are unequal according to the equals(object) method, then calling the hashCode method on each of the two objects must produce distinct integer results. However, the programmer should be aware that producing distinct integer results for unequal objects may improve the performance of hash tables
Equals objects must have equal hash codes. Because two distinct instances may be logically equal according to the class's equal method, but to the object class's hashCode method, they're just two objects with nothing much in common. Therefore object's hashCode method returns two seemingly random numbers instead of two equal numbers as required by the contract. That's why it is very important to override hashCode when equals override.
Example:
without overriding hashCode method:
package com.effectivejava;
import java.util.HashMap;
import java.util.Map;
/**
*
* @author palash
*/
public class Item8 {
public static void main(String[] args){
System.out.println("testing item8");
Map m = new HashMap();
m.put(new PhoneNumber(408, 876, 5309), "palash");
System.out.println(m.get(new PhoneNumber(408, 876, 5309)));
}
}
final class PhoneNumber{
private final short areaCode;
private final short exchange;
private final short extension;
public PhoneNumber(int areaCode, int exchange, int extension){
rangeCheck(areaCode, 999, "area code");
rangeCheck(exchange, 999, "exchange");
rangeCheck(extension, 9999, "extension");
this.areaCode = (short)areaCode;
this.exchange = (short) exchange;
this.extension = (short) extension;
}
private static void rangeCheck(int arg, int max, String name){
if(arg<0 || arg > max)
throw new IllegalArgumentException(name + ": " + arg);
}
@Override
public boolean equals(Object o){
if(o == this) return true;
if(!(o instanceof PhoneNumber)) return false;
PhoneNumber pn = (PhoneNumber) o;
return pn.extension == extension &&
pn.exchange == exchange &&
pn.areaCode == areaCode;
}
}
Programmers often develop systems in which a component may be an individual object or may represent a collection of objects. The Composite pattern is designed to accommodate both cases. You can use it to build part-whole hierarchies or to construct data representations of trees.
Composite is a collection of objects
It describes that a group of objects are to be treated in the same way as a single instance of an object
The intent of a composite is to "compose" objects into tree structures to represent part-whole hierarchies
Example code:
package com.designpattern.structuralpattern;
import java.util.List;
import java.util.ArrayList;
// component
interface Graphic{
public void print();
}
// composite
class CompositeGraphic implements Graphic{
private List<Graphic> childGraphics = new ArrayList<Graphic>();
@Override
public void print() {
for(Graphic graphic : childGraphics){
graphic.print();
}
}
public void add(Graphic graphic){
childGraphics.add(graphic);
}
public void remove(Graphic graphic){
childGraphics.remove(graphic);
}
}
// leaf
class Ellipse implements Graphic{
@Override
public void print() {
System.out.println("Ellipse");
}
}
// client
public class CompositePattern {
public static void main(String[] args){
Ellipse ellipse1 = new Ellipse();
Ellipse ellipse2 = new Ellipse();
Ellipse ellipse3 = new Ellipse();
Ellipse ellipse4 = new Ellipse();
//composite
CompositeGraphic graphic = new CompositeGraphic();
CompositeGraphic graphic1 = new CompositeGraphic();
CompositeGraphic graphic2 = new CompositeGraphic();
graphic1.add(ellipse1);
graphic1.add(ellipse2);
graphic1.add(ellipse3);
graphic2.add(ellipse4);
graphic.add(ellipse1);
graphic.add(ellipse2);
graphic.print();
}
}
EJ-7/57: Obey the general contract when overriding equals
When override the equals method, must adhere following contract:
It is reflexive: For any reference value x,x.equals(x) must return true
It is symmetric: For any reference values x and y, x.equals(y) must return true if and only if y.equals(x) returns true
It is transitive: For any reference values x,y and z, if x.equals(y) returns true and y.equals(z) returns true, then x.equals(z) must return true
It is consistent: For any reference values x and y, multiple invocations of x.equals(y) consistently return true or consistently return false, provided no information used in equals comparisons on the object is modified
For any non-null reference value x, x.equals(null) must return false
Each instance of the class is inherently unique.
You don't care whether the class provides a "logical equality" test.
A superclass has already overridden equals, and the behavior inherited from the superclass is appropriate for this class.
The class is private or package-private, and you are certain that its equals method will never be invoked
Some High quality equals method :
Use the == operator to check if the argument is a reference to this object
Use the instanceof operator to check if the argument is of the correct type
Cast the argument to the correct type
For each "significant" field in the class, check to see if that field of the argument matches the corresponding field of this object
Always override hashCode when you override equals
Don't write an equals method that relies on unreliable resources
Don't substitute another type for Object in the equals declaration
Extra:
o instanceof MyType. Where instanceof operator to check the type is correct or not. It returns false if its first operand is null.
The Bridge Pattern is used to separate out the interface from its implementation.
Doing this gives the flexibility so that both can vary independently.
Also known as Handle/Body
From GOF: 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.
Bridge design pattern is a modified version of the notion of "prefer composition over inheritance"
UML:
Image description:
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
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package com.designpattern.structuralpattern;
/**
*
* @author palash
*/
public class BridgePattern {
public static void main(String[] args){
// first example
Fan fan = new Fan();
fan.switchOn();
Bulb bulb = new Bulb();
bulb.switchOff();
// second example
Shape[] shapes = new Shape[]{
new CircleShape(1, 2, 3, new DrawingAPI1()),
new CircleShape(5, 7, 11, new DrawingAPI2()),
};
for(Shape shape : shapes){
shape.resizeByPercentage(2.5);
shape.draw();
}
}
}
// first example
interface Switch{
public void switchOn();
public void switchOff();
}
class Fan implements Switch{
@Override
public void switchOn() {
System.out.println("Fan's switch on");
}
@Override
public void switchOff() {
System.out.println("Fan's switch off");
}
}
class Bulb implements Switch{
@Override
public void switchOn() {
System.out.println("Bulb's switch on");
}
@Override
public void switchOff() {
System.out.println("Bulb's switch off");
}
}
///////////////////////////////////////
// second example
//implementor
interface DrawingAPI{
public void drawCircle(double x, double y, double radius);
}
// concreteImplementor
class DrawingAPI1 implements DrawingAPI{
@Override
public void drawCircle(double x, double y, double radius) {
System.out.printf("API1.circle at %f:%f radius %f\n", x, y, radius);
}
}
// concreteImplementor
class DrawingAPI2 implements DrawingAPI{
@Override
public void drawCircle(double x, double y, double radius) {
System.out.printf("API1.circle at %f:%f radius %f\n", x, y, radius);
}
}
// abstraction
abstract class Shape{
protected DrawingAPI drawingAPI;
protected Shape(DrawingAPI drawingAPI){
this.drawingAPI = drawingAPI;
}
public abstract void draw();
public abstract void resizeByPercentage(double pct);
}
class CircleShape extends Shape{
private double x,y,radius;
public CircleShape(double x, double y, double radius, DrawingAPI drawingAPI){
super(drawingAPI);
this.x = x; this.y = y; this.radius = radius;
}
@Override
public void draw() {
drawingAPI.drawCircle(x, y, radius);
}
@Override
public void resizeByPercentage(double pct) {
radius *= pct;
}
}
Adapter pattern also known as wrapper pattern or simply wrapper.
Translates one interface for a class into a compatible interface.
Allows classes to work together that normally could not because of incompatible interfaces, by providing its interface to clients while using the original interface.
Also responsible for transforming data into appropriate forms.
Example:
Transforming the format of dates(e.g YYYYMMDD to MM/DD/YYYY)
java.io.InputStreamReader(InputStream)
java.io.OutputStreamWriter(OutputStream)
Types: There are two types of adapter pattern.
Class Adapter pattern
Object Adapter pattern
Class Adapter pattern: Inheritance is used to implement class adapter pattern. This type of adapter uses multiple polymorphic interface to achieve its goal. The adapter is created by implementing or inheriting both the interface that is expected and the interface that is pre-existing.
Object Adapter pattern: In this type of adapter pattern, the adapter contains an instance of the class it wraps. In this situation, the adapter makes calls to the instance of the wrapped object.
package com.designpattern.structuralpattern;
/**
*
* @author palash
*/
public class AdapterPattern {
public static void main(String[] args){
// class adapter pattern by inheritance
RectangularPlugClass clientPlug = new RectangularPlugClass("5amp", "15map");
System.out.println(clientPlug.getPower());
// object adapter pattern by composition
RectangularPlugObject clientPlugObj = new RectangularPlugObject("7amp", "20amp");
System.out.println(clientPlugObj.getPower());
}
}
// class adapter pattern
class CylindericalSocketClass{
public String supply(String cylinStem1, String cylinStem2){
System.out.println("Power...");
return cylinStem1 + " and " + cylinStem2 + " power supply from class adapter pattern";
}
}
class RectangularAdapterClass extends CylindericalSocketClass{
public String adapt(String rectaStem1, String rectaStem2){
String cylinStem1 = rectaStem1;
String cylinStem2 = rectaStem2;
return supply(cylinStem1, cylinStem2);
}
}
class RectangularPlugClass{
private String rectaStem1;
private String rectaStem2;
public RectangularPlugClass(String param1, String param2){
this.rectaStem1 = param1;
this.rectaStem2 = param2;
}
public String getPower(){
RectangularAdapterClass adapter = new RectangularAdapterClass();
String power = adapter.adapt(rectaStem1, rectaStem2);
return power;
}
}
///////////////////////////////////////////////
// Object adapter pattern
class CylindericalSocketObject{
public String supply(String cylinStem1, String cylinStem2){
System.out.println("Power...");
return cylinStem1 + " and " + cylinStem2 + " power supply from object adapter pattern";
}
}
class RectangularAdapterObject{
private CylindericalSocketObject socket;
public String adapt(String rectaStem1, String rectaStem2){
socket = new CylindericalSocketObject();
String cylinStem1 = rectaStem1;
String cylinStem2 = rectaStem2;
return socket.supply(cylinStem1, cylinStem2);
}
}
class RectangularPlugObject{
private String rectaStem1;
private String rectaStem2;
public RectangularPlugObject(String param1, String param2){
this.rectaStem1 = param1;
this.rectaStem2 = param2;
}
public String getPower(){
RectangularAdapterObject adapter = new RectangularAdapterObject();
String power = adapter.adapt(rectaStem1, rectaStem2);
return power;
}
}
Structural patterns are concerned with how classes and objects are composed to form larger structures.
Structural class patterns use inheritance to compose interfaces or implementations.
Example:
Consider how multiple inheritance mixes two or more classes into one. The results is a class that combines the properties of its parent classes.
Adapter pattern: An adapter makes one interface conform to another, thereby providing a uniform abstraction of different interfaces.
Composite pattern: It describes how to build a class hierarchy made up of classes for two kinds of objects: primitive and composite. The composite objects let you compose primitive and other composite objects into arbitrarily complex structure.
Proxy pattern: A proxy acts as a convenient surrogate or placeholder for another object. It can act as a local representative for an object in a remote address space. It can represent a large object that should be loaded on demand. It might protect access to a sensitive object.
Flyweight pattern: The flyweight pattern defines a structure for sharing objects. Objects are shared for at least two reasons: efficiency and consistency. Flyweight focuses on sharing for space efficiency.
Facade pattern: Facade shows how to make a single object represent an entire subsystem. A facade is a representative for a set of objects.
Bridge pattern: The Bridge pattern separates an object's abstraction from its implementation so that you can vary them independently.
Decorator pattern: Decorator describes how to add responsibilities to objects dynamically. Decorator is a structural pattern that composes object recursively to allow an open-ended number of additional responsibilities.
Finalizers are unpredictable, often dangerous, and generally unnecessary. Their use can cause erratic behavior, poor performance, and portability problems.
In the Java programming language, the garbage collector reclaims the storage associated with an object when it becomes unreachable, requiring no special effort on the part of the programmer. The try-finally block is generally used for this purpose.
There is no guarantee that finalizers will be executed promptly. Nothing time-critical should ever be done by a finalizer.
Explicit termination methods are often used in combination with the try-finally construct to ensure prompt termination. Invoking the explicit termination method inside the finally clause ensures that it will get executed even if an exception is thrown while the object is being used.
Foo foo = new Foo();
try{...}finally{
foo.terminate(); //explicit termination method
}
InputStream, OutputStream and Timer use explicit termination method. Also have finalizers that serve as safety nets in case their termination methods aren't called.
Instead of putting the finalizer on the class requiring finalization, put the finalizer in an anonymous class whose sole purpose is to finalize its enclosing instance. A single instance of the anonymous class, called a finalizer guardian, is created for each instance if the enclosing class.
public class Foo{
private final Object finalizerGuardian = new Object(){
protected void finalize() throws Throwable{
}
};
}
Extra:
Don't use finalizers except as a safety net or to terminate noncritical native resources. If you use finalizer then remember to invoke super.finalize.
If you need to associate a finalizer with a public, nonfinal class, consider using a finalizer guardian to ensure that the finalizer is executed, even if a subclass finalizer fails to invoke super.finalize.