Revision as of 12:00, 18 August 2009 editCrashthe2nd (talk | contribs)1 edit →C#: Modified C# source code so that it compiles← Previous edit | Revision as of 05:36, 25 August 2009 edit undoWipeouter (talk | contribs)1 edit →External linksNext edit → | ||
Line 274: | Line 274: | ||
==External links== | ==External links== | ||
* | * | ||
* | |||
* | * | ||
* | * |
Revision as of 05:36, 25 August 2009
In software engineering, a fluent interface (as first coined by Eric Evans and Martin Fowler) is a way of implementing an object oriented API in a way that aims to provide for more readable code.
A fluent interface is normally implemented by using method chaining to relay the instruction context of a subsequent call (but a fluent interface entails more than just method chaining ). Generally, the context is
- defined through the return value of a called method
- self referential, where the new context is equivalent to the last context
- terminated through the return of a void context.
This style is beneficial due to its ability to provide a more fluid feel to the code.
Examples
C#
The following example shows a class implementing a non-fluent interface, another class implementing a fluent counterpart of the aforementioned non-fluent interface, and differences in usage. The example is written in C#:
namespace Example.FluentInterfaces { using System; public interface IConfiguration { void SetColor(string color); void SetHeight(int height); void SetLength(int length); void SetDepth(int depth); } public interface IConfigurationFluent { IConfigurationFluent SetColor(string color); IConfigurationFluent SetHeight(int height); IConfigurationFluent SetLength(int length); IConfigurationFluent SetDepth(int depth); } public class Configuration : IConfiguration { string color; int height; int length; int depth; public void SetColor(string color) { this.color = color; } public void SetHeight(int height) { this.height = height; } public void SetLength(int length) { this.length = length; } public void SetDepth(int depth) { this.depth = depth; } } public class ConfigurationFluent : IConfigurationFluent { string color; int height; int length; int depth; public IConfigurationFluent SetColor(string color) { this.color = color; return this; } public IConfigurationFluent SetHeight(int height) { this.height = height; return this; } public IConfigurationFluent SetLength(int length) { this.length = length; return this; } public IConfigurationFluent SetDepth(int depth) { this.depth = depth; return this; } } public class ExampleProgram { public static void Main(string args) { //Standard Example IConfiguration config = new Configuration(); config.SetColor("blue"); config.SetHeight(1); config.SetLength(2); config.SetDepth(3); //FluentExample IConfigurationFluent fluentConfig = new ConfigurationFluent().SetColor("blue") .SetHeight(1) .SetLength(2) .SetDepth(3); } } }
C++
The following is an example of providing a fluent interface wrapper on top of a more traditional interface in C++:
// basic definition class GlutApp { private: int w_, h_, x_, y_, argc_, display_mode_; char **argv_; char *title_; public: GlutApp(int argc, char** argv) { argc_ = argc; argv_ = argv; } void setDisplayMode(int mode) { display_mode_ = mode; } int getDisplayMode() { return display_mode_; } void setWindowSize(int w, int h) { w_ = w; h_ = h; } void setWindowPosition(int x, int y) { x_ = x; y_ = y; } void setTitle(const char *title) { title_ = title; } void create(); }; // basic usage int main(int argc, char **argv) { GlutApp app(argc, argv); app.setDisplayMode(GLUT_DOUBLE|GLUT_RGBA|GLUT_ALPHA|GLUT_DEPTH); // Set framebuffer params app.setWindowSize(500, 500); // Set window params app.setWindowPosition(200, 200); app.setTitle("My OpenGL/GLUT App"); app.create(); } // Fluent wrapper class FluentGlutApp : private GlutApp { public: FluentGlutApp(int argc, char **argv) : GlutApp(argc, argv) {} // inherit parent constructor FluentGlutApp &withDoubleBuffer() { setDisplayMode(getDisplayMode() | GLUT_DOUBLE); return *this; } FluentGlutApp &withRGBA() { setDisplayMode(getDisplayMode() | GLUT_RGBA); return *this; } FluentGlutApp &withAlpha() { setDisplayMode(getDisplayMode() | GLUT_ALPHA); return *this; } FluentGlutApp &withDepth() { setDisplayMode(getDisplayMode() | GLUT_DEPTH); return *this; } FluentGlutApp &across(int w, int h) { setWindowSize(w, h); return *this; } FluentGlutApp &at(int x, int y) { setWindowPosition(x, y); return *this; } FluentGlutApp &named(const char *title) { setTitle(title); return *this; } // it doesn't make sense to chain after create(), so don't return *this void create() { GlutApp::create(); } }; // basic usage int main(int argc, char **argv) { FluentGlutApp app(argc, argv) .withDouble().withRGBA().withAlpha().withDepth() .at(200, 200).across(500, 500) .named("My OpenGL/GLUT App"); app.create(); }
Java
Some APIs in Java follow this practice, like Java Persistence API:
public Collection<Student> findByNameAgeGender(String name, int age, Gender gender) { return em.createNamedQuery("Student.findByNameAgeGender") .setParameter("name", name) .setParameter("age", age) .setParameter("gender", gender) .setFirstResult(1) .setMaxResults(30) .setHint("hintName", "hintValue") .getResultList(); }
PHP
The following is an example of providing fluent interface in PHP:
<?php session_start(); error_reporting(E_ALL | E_USER_NOTICE); require_once 'classes/Loader.php'; require_once 'config.php'; ?> <?php class car { private $speed; private $color; private $doors; public function setSpeed($speed){ $this->speed = $speed; return $this; } public function setColor($color) { $this->color = $color; return $this; } public function setDoors($doors) { $this->doors = $doors; return $this; } } // Fluent interface $myCar = new car(); $myCar->setSpeed(100)->setColor('blue')->setDoors(5); // Example withouth fluent interface $myCar2 = new car(); $myCar2->setSpeed(100); $myCar2->setColor('blue'); $myCar2->setDoors(5); ?>
See also
External links
- Martin Fowler's original bliki entry coining the term
- http://www.fluent-interfaces.com
- A Delphi example of writing XML with a fluent interface
- A .NET Fluent validation library written in C#
Software design patterns | |||||||
---|---|---|---|---|---|---|---|
Gang of Four patterns |
| ||||||
Concurrency patterns | |||||||
Architectural patterns | |||||||
Other patterns | |||||||
Books | |||||||
People | |||||||
Communities | |||||||
See also |