Интернет магазин китайских планшетных компьютеров |
|
Компьютеры - Fluent interface - Примеры13 мая 2011Оглавление: 1. Fluent interface 2. Примеры DelphiСледующий пример показывает обычный класс и класс, реализующий текучий интерфейс, и различия в использовании. Пример написан на Delphi Object Pascal:
unit FluentInterface;
interface
type
IConfiguration = interface
procedure SetColor;
procedure SetHeight;
procedure SetLength;
procedure SetDepth;
end;
IConfigurationFluent = interface
function SetColor: IConfigurationFluent;
function SetHeight: IConfigurationFluent;
function SetLength: IConfigurationFluent;
function SetDepth: IConfigurationFluent;
end;
TConfiguration = class
private
FColor: string;
FHeight: integer;
FLength: integer;
FDepth: integer;
protected
procedure SetColor;
procedure SetHeight;
procedure SetLength;
procedure SetDepth;
end;
TConfigurationFluent = class
private
FColor: string;
FHeight: integer;
FLength: integer;
FDepth: integer;
protected
function SetColor: IConfigurationFluent;
function SetHeight: IConfigurationFluent;
function SetLength: IConfigurationFluent;
function SetDepth: IConfigurationFluent;
public
class function New: IConfigurationFluent;
end;
implementation
procedure TConfiguration.SetColor;
begin
FColor := Color;
end;
procedure TConfiguration.SetDepth;
begin
FDepth := depth;
end;
procedure TConfiguration.SetHeight;
begin
FHeight := height;
end;
procedure TConfiguration.SetLength;
begin
FLength := length;
end;
class function TConfigurationFluent.New: IConfigurationFluent;
begin
Result := Create;
end;
function TConfigurationFluent.SetColor: IConfigurationFluent;
begin
FColor := Color;
Result := Self;
end;
function TConfigurationFluent.SetDepth: IConfigurationFluent;
begin
FDepth := depth;
Result := Self;
end;
function TConfigurationFluent.SetHeight: IConfigurationFluent;
begin
FHeight := height;
Result := Self;
end;
function TConfigurationFluent.SetLength: IConfigurationFluent;
begin
FLength := length;
Result := Self;
end;
end.
var C, D: IConfiguration;
E: IConfigurationFluent;
begin
{ Обычное использование:}
C := TConfiguration.Create;
C.SetColor;
C.SetHeight;
C.SetLength;
C.SetDepth;
{ обычная реализация, упрощенная с помощью инструкции with }
D := TConfiguration.Create;
with D do begin
SetColor;
SetHeight;
SetLength;
SetDepth
end;
{ использование реализации с текучим интерфейсом }
E := TConfigurationFluent.New
.SetColor
.SetHeight
.SetLength
.SetDepth;
end;
C#Начиная с C#3.5 и выше введены продвинутые способы реализации текучего интерфейса. Этот пример написан на C#:
namespace Example.FluentInterfaces
{
#region Standard Example
public interface IConfiguration
{
string Color { set; }
int Height { set; }
int Length { set; }
int Depth { set; }
}
public class Configuration : IConfiguration
{
string color;
int height;
int length;
int depth;
public string Color
{
set { color = value; }
}
public int Height
{
set { height = value; }
}
public int Length
{
set { length = value; }
}
public int Depth
{
set { depth = value; }
}
}
#endregion
#region Fluent Example
public interface IConfigurationFluent
{
IConfigurationFluent SetColor;
IConfigurationFluent SetHeight;
IConfigurationFluent SetLength;
IConfigurationFluent SetDepth;
}
public class ConfigurationFluent : IConfigurationFluent
{
string color;
int height;
int length;
int depth;
public IConfigurationFluent SetColor
{
this.color = color;
return this;
}
public IConfigurationFluent SetHeight
{
this.height = height;
return this;
}
public IConfigurationFluent SetLength
{
this.length = length;
return this;
}
public IConfigurationFluent SetDepth
{
this.depth = depth;
return this;
}
}
#endregion
public class ExampleProgram
{
public static void Main
{
// Обычный пример
IConfiguration config = new Configuration
{
Color = "blue",
Height = 1,
Length = 2,
Depth = 3
};
// Пример текучего интерфейса
IConfigurationFluent fluentConfig =
new ConfigurationFluent.SetColor
.SetHeight
.SetLength
.SetDepth;
}
}
}
C++Банальный пример в C++ стандартный iostream, где текучесть обеспечивается перегрузкой операторов. Пример обертки текучего интерфейса в C++:
// обычное задание
class GlutApp {
private:
int w_, h_, x_, y_, argc_, display_mode_;
char **argv_;
char *title_;
public:
GlutApp {
argc_ = argc;
argv_ = argv;
}
void setDisplayMode {
display_mode_ = mode;
}
int getDisplayMode {
return display_mode_;
}
void setWindowSize {
w_ = w;
h_ = h;
}
void setWindowPosition {
x_ = x;
y_ = y;
}
void setTitle {
title_ = title;
}
void create;
};
// обычное использование
int main {
GlutApp app;
app.setDisplayMode; // Set framebuffer params
app.setWindowSize; // Set window params
app.setWindowPosition;
app.setTitle;
app.create;
}
// Обертка текучего интерфейса
class FluentGlutApp : private GlutApp {
public:
FluentGlutApp : GlutApp {} // наследуем родительский конструктор
FluentGlutApp &withDoubleBuffer {
setDisplayMode | GLUT_DOUBLE);
return *this;
}
FluentGlutApp &withRGBA {
setDisplayMode | GLUT_RGBA);
return *this;
}
FluentGlutApp &withAlpha {
setDisplayMode | GLUT_ALPHA);
return *this;
}
FluentGlutApp &withDepth {
setDisplayMode | GLUT_DEPTH);
return *this;
}
FluentGlutApp &across {
setWindowSize;
return *this;
}
FluentGlutApp &at {
setWindowPosition;
return *this;
}
FluentGlutApp &named {
setTitle;
return *this;
}
// без разницы, вести ли цепь после вызова create, поэтому не возвращаем *this
void create {
GlutApp::create;
}
};
// используем текучий интерфейс
int main {
FluentGlutApp app
.withDoubleBuffer.withRGBA.withAlpha.withDepth
.at.across
.named;
app.create;
}
JavaНекоторые API в Java реализуют такой интерфейс, например Java Persistence API:
public Collection<Student> findByNameAgeGender {
return em.createNamedQuery
.setParameter
.setParameter
.setParameter
.setFirstResult
.setMaxResults
.setHint
.getResultList;
}
String datesStr = new String {"12-10-1492", "06-12-1978" };
...
List<Calendar> dates =
Op.on.toList.map).get;
Collection mockCollection = EasyMock.createMock; EasyMock.expect).andThrow).atLeastOnce; PHPПример реализации класса с текучим интерфейсом в PHP:
class Car {
private $speed;
private $color;
private $doors;
public function setSpeed{
$this->speed = $speed;
return $this;
}
public function setColor {
$this->color = $color;
return $this;
}
public function setDoors {
$this->doors = $doors;
return $this;
}
}
// Обычная реализация
$myCar2 = new Car;
$myCar2->setSpeed;
$myCar2->setColor;
$myCar2->setDoors;
// Текучий интерфейс
$myCar = new Car;
$myCar->setSpeed->setColor->setDoors;
JavaScriptПример реализации класса с текучим интерфейсом в JavaScript:
var Car = {
var speed, color, doors, pub;
function setSpeed {
speed = new_speed;
return pub;
}
function setColor {
color = new_color;
return pub;
}
function setDoors {
doors = new_doors;
return pub;
}
pub = {
'setSpeed': setSpeed,
'setColor': setColor,
'setDoors': setDoors,
};
return pub;
})
// Обычная реализация
myCar2 = Car;
myCar2.setSpeed;
myCar2.setColor;
myCar2.setDoors;
// Текучий интерфейс
myCar = Car;
myCar.setSpeed.setColor.setDoors;
Также можно использовать иной подход:
var $ = function {
if {
return new $;
}
if {
this.init = document.getElementById;
}
};
$.prototype = {
text: function {
if{
this.init.innerHTML;
}
this.init.innerHTML = text;
return this;
},
css: function {
for{
this.init.style = style;
}
return this;
}
};
//пример использования:
$.text.css;
Пример реализации независящей от возвращаемого типа объекта:
({
foo: function {
return a;
}
}).foo.toUpperCase;
Просмотров: 2209
|