Monday, May 18, 2009

Another Example of Fluent Interface

As in my previous blog posts, Fluent Interface pattern makes codes very simple and easy to read. The key point of FI is to define a class with methods returning a type of the class itself. As a result, you can continue to call its methods to manipulate data within the class. I have seen this pattern in jQuery and Dojo.

Normally, we define a class with a constructor to initialize its data members when an instance is created, and all those data members are not editable or no setters are defined. As a result, the class has its limitation only for one set of cases. If you want to define different set of data with manipulation by methods, you have to recreate objects again.

With FI pattern, here is another example to define a class to handle various data cases. Instead of passing data through CTOR, you can set data by using a method and the the return type of the class is the class itself, for example:

class MyFICalc {
private int _result;
private int _leftVal;
private int _rightVal;

public MyFICalc SetData(int val1, int val2) {
_leftVal = val1;
_rightVal = val2;
return this;
}

...
}


An instance is created by its default CTOR and data are set by the method SetData(). The method SetData() return a reference to itself. With this structure, further methods on data are defined to get expected result.

For example, I define a set of calculations:

  int  Add() {
return _leftVal + _rightVal;
}

int Subtract() {
return _leftVal - _rightVal;
}

int Multiply() {
return _leftVal * _rightVal;
}


Here are some example of uses:

int result;
MyFICalc calc = new MyFICalc();
result = calc.SetData(2, 3).Add(); // 5
result = calc.SetData(300, result).Subtract(); // 295
result = calc.SetData(result, 4).Multiply(); // 1180

Of course, this is a very simple example. In practice in one of data reading from database case, I have used FI in this manor in a loop for each row to set data and then continue to update data based on business logic. In this way, I would not need to constantly create instances. I just reuse my instance to set data and to get my result.

0 comments: