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