11/12/2007

Double Dispatch

A typical runtime polymorphism works on method invocations where the call is on supertype but the actual method comes from the runtime subtype. However, the method selection is not polymorphic in itself, meaning only the method whose signature exactly matches the signature of the call can be invoked.

Double dispatch is a way to achieve runtime polymorphism where method implementation is selected based on both the callee object and actual argument object.

e.g. Consider this class hierarchy:

class A { method(E){} method(F){} }<--class B<--class C
class E<-- class F


A, B, C have overloaded methods. Note that overloading is early-binding (compile-time polymorphism).

So, a call like

A a = new B();
E e = new F();
a.method(e);

would result in B.method(E) invocation. Which is a classic runtime polymorphism case. A double dispatch would however would result in B.method(F) invocation.

Implementation of Double Dispatch
The idea is to use reference-types for callee and the argument before the method call is dispatched to its implementation, as every invocation on the reference-type would show a runtime polymrphism.

In order to do this, we introduce a new method in E/F as follows:

method(A a) {
a.method(this);
}

and change the calling program to

A a = new B();
E e = new F();
e.method(a);


This would first dispatch the call to F's implementation of method(A) and from there B's implementation of the method where the argument type is F i.e. B.method(F) .

thats all we set out to do!

Visitor Pattern and Double Dispatch
A visitor pattern is applicabe where we want to add a method to elements of a object hierarchy without changing the classes of the constituents.

We add methods to the visitor not to the classes it visits. The visited objects call back the visitor passing themselves. The visitor would have implementations for all the classes it can visit.

In the example given above A,B,C act as visitors to E,F.
If you have added a new type (e.g. G) in the structure, all you need is to add a method that accepts that type as argument in one of the visitors or a new visitor (e.g. method(G){}) and this method will be invoked whenever an object of G is visited.

Typically, the methods take the following form

visitable.accept(visitor);
...
accept(Visitor vistitor) {
visitor.visit(this);
}

Which is analogous to

e.method(a);
...
method(A a) {
a.method(this);
}

10/01/2007

unix shellscript for renaming multiple files by removing a string from all filenames


# folder: no trailing slash $1
# str: string to remove $2

folder=$1
str=$2
echo $folder $str

files=`ls -1 $folder`
for file in $files ; do
echo $file
tc=`echo $file | sed s/$str//`
echo $tc
if [ -f $folder/$file ];
then
mv $folder/$file $folder/$tc
#echo $tc
#echo $folder/$file $folder/$tc
fi
done

exit 1

8/26/2007

Factory Method Pattern

If you are asked to create a simle factory for creating objects,
you would start (or rather end up ) with something like this:
ProductFactory {
Product getProduct(int case) {
if(case== 1)
return new getProduct1();
else
return new getProduct2();
}
}

However, more often than not, from a requester's perspective, the product that he is looking for will be more polished than 'new Product()' that is to say the 'new Product()' would undergo some process before it is delivered.
ProductFactory {
Product getProduct(int case) {
Product ins = null;
if(case== 1)
ins = new Product();
else
ins = new Product1();
doSomethingWithProduct(ins);
doSomethingElseWithProduct(ins);
return ins;
}
doSomethingWithProduct(AbstractProduct ... ) {
}
doSomethingElseWithProduct(AbstractProduct ... ) {
}
}

We are using AbstractProduct instead of the actual Product, why?
It's for the same reason that we prefer
List l = new ArrayList() to
ArrayList l = new ArrayList();

AbstractProduct is an abstraction of Product which is of interest to the factory and
its users. It makes sure the same factory can work when new Products are introduced as long as they are instances of the same abstraction. It also means the factory returns abstractions not actual implementations so users of this factory are also lightly coupled.
Once we have an implementation like above, it can be used as
ProductFactory pf = new ProductFactory();
pf.getProduct();

Observe that the factory is tightly coupled with actual implementations of Products.
Now consider introducing a new factory, so that a client (requester) has the option to choose one of these factories where he wants the product from. That choice should be construed as the Context in which the product is created/requested.
e.g. a Spreadsheet instance from MSOffice or one from OpenOffice. Client would makje a decision to go for one of these. The choice is basically boils down to selecting one of MSOfficeSpreadsheetFactory or OOfficeSpreadsheetFactory.
However, before the spreadsheet is returned, it should be assigned a default name and should also be saved in a temporary location (this post-process is henceforth referred as polishing). This has to happen irrespective of whether it is MSO or OO spreadsheet.
At this stage we will have these two factories:
class MSOfficeSpreadsheetFactory {
...
}
class OOfficeSpreadsheetFactory {
...
}

We can also see two methods working on spreadsheets:
assignName(Spreadheet ...){}
tempSave(Spreadsheet ...){}

As we can see these methods work on Spreadsheet (an abstraction like AbstractProduct)
so we should definitely abstract it out of MS and OO factory classes and thus make it reusable.
SpreadsheetFactory {
assignName(Spreadheet ... ) {
}
tempSave(Spreadheet ... ) {
}
}
MSOfficeSpreadsheetFactory extends SpreadsheetFactory {
Spreadsheet createSpreadsheet(int type) () {
Spreadsheet s = new Excel();
assignName(s);
tempSave(s);
}
}
}
OOfficeSpreadsheetFactory extends SpreadsheetFactory {
Spreadsheet createSpreadsheet(int type) () {
Spreadsheet s = new Calc();
assignName(s);
tempSave(s);
}
}

At this stage, the requester would look something like this:
MSOfficeSpreadsheetFactory msf =
new MSOfficeSpreadsheetFactory();
Spreadsheet spr1 = msf.createSpreadsheet(...);
OOfficeSpreadsheetFactory osf =
new OOfficeSpreadsheetFactory();
Spreadsheet spr2 = osf.createSpreadsheet(...);

If we abstract out createSpreadsheet(...) we can reduce our dependency on actual Factory implementations.
SpreadsheetFactory {
assignName(Spreadheet ... ) {
}
tempSave(Spreadheet ... ) {
}
public abstract Spreadsheet createSpreadsheet(...);
}
...
SpreadsheetFactory msf =
new MSOfficeSpreadsheetFactory();
Spreadsheet spr1 =
msf.createSpreadsheet(...);
SpreadsheetFactory osf =
new OOfficeSpreadsheetFactory();
Spreadsheet spr2 =
osf.createSpreadsheet(...);

So far so good. Lets take a moment and analyze where things could get complicated with this approach.
What happens when a new Factory is introduced and/or and new polishing procedure is introduced. This would require a change in the SpreadsheetFactory and all its concrete implementations as implementations are using superclass methods. We can work this out by moving the polishing out of implementations and thus leaving them responsible for creation alone.
Instead of invoking createSpreadsheet() which is implemented in the subclass
introduce another method getSpreadsheet() in SpreadsheetFactory. This moves back the creation control to the SpreadsheetFactory, the superclass.
SpreadsheetFactory {
assignName(Spreadheet ... ) {
}
tempSave(Spreadheet ... ) {
}
public Spreadsheet getSpreadsheet() {
Spreadsheet s = createSpreadsheet();
assignName(s);
tempSave(s);
return s;
}
abstract Spreadsheet createSpreadsheet();
}

What we gain from this approach:
The factory SpreadsheetFactory is not dependent on actual implementations of Spreadsheets. Still, the factory knows how to create and return implementations of Spreadsheets. How does that happen...
The factory is delegating the actual instantiation to its subclass. The subclass is selected by the requester (which is basically the Context selection). The SpreadsheetFactory class would not be impacted by addition of new implementations.
It's important to note that the essence of this pattern lies in how the factory should be designed so that the factory itself is not coupled with what it creates and hence can be used to create products depending on the context that it operates in. See it from the point of view of the getSpreadsheet() method, not from the point of view of the client.
This pattern is usually applied to scenarios where factories return a certain type of product.

8/15/2007

JavaBeans

JavaBeans technology is the component architecture for the Java Platform. The other component architecture is EJB, but JavaBeans and EJBs are entirely different beasts.

A JavaBean is a reusable software component. It is a Java class that defines properties and that communicates with other Beans via events. Properties can be defined within the JavaBean class definition, or they can be inherited from other classes. A Bean, however, is not required to inherit from any particular class or interface. The idea behind JavaBeans is to help develop and use reusable components and that is backed by specifications by which 'beans' abide. It's
the specification that ensures 'beans' integrability. Apart from the sepcificaitons, beans are just regular java classes (unlike ejbs!).

The major benifits of JavaBeans is that beans' properties can be manipulated in a visual builder tool like NetBeans. It can be simple, such as buttons, text fields, list boxes, scrollbars, and dialogs. Or they may be more complex software components to handle business logic or a spell-checker.

You certainly can use other pre-built objects in Java, but for that we must have an intimate knowledge of the object's interface at the code level. Additionally, you must integrate the object into your code programmatically.

JavaBeans components expose their own interfaces visually, enabling you to edit their properties without programming. Furthermore, you can use a visual editor to simply "drop" a JavaBeans component directly into an application without writing any code. This is an entirely new level of flexibility and reuse not previously attainable in Java alone.

The real value of JavaBeans is while designing/developing a software which uses these components, you can visually integrate these components with the rest of the system.The component need not be visible in a running application; they only need to be visible in the builder tools when the application is constructed by a builder tool. A programmer can move, query, or visually hook together components while operating a builder tool. Often, such components do their work while the application is running, though they are invisible to the user.

JavaBeans that represent graphical components and that are meant to be visible must inherit from a java.awt. Component such as the java.awt.Canvas class, so that they can be added to visual containers.

The following list briefly describes key bean concepts:

Introspection: Builder tools discover a bean's features (that is, its properties, methods, and events) by a process known as introspection. Beans support introspection in two ways:
By adhering to specific rules, known as design patterns, when naming bean features. The Introspector class examines beans for these design patterns to discover bean features. The Introspector class relies on the core reflection API.
By explicitly providing property, method, and event information with a related bean information class. A bean information class implements the BeanInfo interface. A BeanInfo class explicitly lists those bean features that are to be exposed to application builder tools.

Properties: Properties are the appearance and behavior characteristics of a bean that can be changed at design time. Builder tools introspect on a bean to discover its properties and expose those properties for manipulation.

Customization: Beans expose properties so they can be customized at design time. Customization is supported in two ways: by using property editors, or by using more sophisticated bean customizers.

Events: Beans use events to communicate with other beans. A bean that is to receive events (a listener bean) registers with the bean that fires the event (a source bean). Builder tools can examine a bean and determine which events that bean can fire (send) and which it can handle (receive).

Persistence: Persistence enables beans to save and restore their state. After changing a bean's properties, you can save the state of the bean and restore that bean at a later time with the property changes intact. The JavaBeans architecture uses Java Object Serialization to support persistence.

References:
java.sun.com  docs.rinet.ru  forum.java.sun.com

Property, Attribute and Field
(This is just an opinion and there is no Standard way of distinguishing the three.)
JavaBeans conventions for getters and setters allows us to expose properties. Those properties don’t have to be backed up by fields, but in many cases they are.
e.g. Circle's radius, diameter, circumference. We may have only one variable (field) 'radius' and can still expose all other properties. Attribute is more synonymous to Property.

References:
clintshank.javadevelopersjournal.com