SDN Featured Content

Do you Think Hibernate is better technology that EJB

Java/J2EE blogs

Welcome to my java /J2EE blogs.


Thursday, June 18, 2009


Factory Patterns in Math Computation
Most people who use Factory patterns tend to think of them as tools
for simplifying tangled programming classes. But it is perfectly possible to
use them in programs that simply perform mathematical computations. For
example, in the Fast Fourier Transform (FFT), you evaluate the following
four equations repeatedly for a large number of point pairs over many passes
through the array you are transforming. Because of the way the graphs of
these computations are drawn, these equations constitute one instance of the
FFT “butterfly.” These are shown as Equations 1--4.




So it is not unreasonable to package this computation in a couple of
classes doing the simple or the expensive computation depending on the
angle y. We’ll start by creating a Complex class that allows us to manipulate
real and imaginary number pairs:
class Complex {
float real;
float imag;
}


Then we’ll create our Butterfly class as an abstract class that we’ll fill
in with specific descendants:
abstract class Butterfly {
float y;
public Butterfly() {
}
public Butterfly(float angle) {
y = angle;
}
abstract public void Execute(Complex x, Complex y);
}
Our two actual classes for carrying out the math are called
addButterfly and trigButterfly. They implement the computations shown in
equations (1--4) and (5--8) above.
class addButterfly extends Butterfly {
float oldr1, oldi1;
public addButterfly(float angle) {
}
public void Execute(Complex xi, Complex xj) {
oldr1 = xi.getReal();
oldi1 = xi.getImag();
xi.setReal(oldr1 + xj.getReal()); //add and subtract
xj.setReal(oldr1 - xj.getReal());
xi.setImag(oldi1 + xj.getImag());
xj.setImag(oldi1 - xj.getImag());
}
}
and for the trigonometic version:
class trigButterfly extends Butterfly {
float y;
float oldr1, oldi1;
float cosy, siny;
float r2cosy, r2siny, i2cosy, i2siny;
public trigButterfly(float angle) {
y = angle;
cosy = (float) Math.cos(y); //precompute sine and cosine
siny = (float)Math.sin(y);
}
public void Execute(Complex xi, Complex xj) {
oldr1 = xi.getReal(); //multiply by cos and sin
oldi1 = xi.getImag();
r2cosy = xj.getReal() * cosy;
r2siny = xj.getReal() * siny;
i2cosy = xj.getImag()*cosy;
24
i2siny = xj.getImag()*siny;
xi.setReal(oldr1 + r2cosy +i2siny); //store sums
xi.setImag(oldi1 - r2siny +i2cosy);
xj.setReal(oldr1 - r2cosy - i2siny);
xj.setImag(oldi1 + r2siny - i2cosy);
}
}
Finally, we can make a simple factory class that decides which class
instance to return. Since we are making Butterflies, we’ll call our Factory a
Cocoon:
class Cocoon {
public Butterfly getButterfly(float y) {
if (y !=0)
return new trigButterfly(y); //get multiply class
else
return new addButterfly(y); //get add/sub class
}
}
You will find the complete FFT.java program on the example
CDROM.
When to Use a Factory Pattern
You should consider using a Factory pattern when
· A class can’t anticipate which kind of class of objects it must create.
· A class uses its subclasses to specify which objects it creates.
· You want to localize the knowledge of which class gets created.
There are several similar variations on the factory pattern to
recognize.
1. The base class is abstract and the pattern must return a complete working
class.
2. The base class contains default methods and is only subclassed for cases
where the default methods are insufficient.
3. Parameters are passed to the factory telling it which of several class types
to return. In this case the classes may share the same method names but
may do something quite different.

No comments: