JavaMessage Chains与Fluent Interface

马丁 Fowler在其名作《重构》一书,提到了Message
Chains坏味道。这种坏味道的展现特征是当调用者须求履行有些意义时,须要调用一而再的多少个点子,才能最后达到目标。这种调用方法的新闻传递就如链条一样,因而Fowler将其命名为Message
Chains。

 

那种坏味道暴光了过多达成细节。它将收获最后结出的凡事进程暴光无遗。它乐此不疲地陈述着:首先该得到怎么着指标,然后再调用重返结果的什么点子取得中间对象,接着,再调用中间对象的应和措施去赢得结果,如此传递下去,直到抵达咱们的目标地。服务的提供者弄错了调用者的剧中人物。调用者不是旅客,要求导游体现沿途的景观;调用者更像是餐厅的门下,只在乎菜品的色香味,却并不爱抚那道菜品是什么做出来的,那是炊事员的职责。

 

导致Message
Chains坏味道的由来是设计者没有很好地领悟封装的定义,他梦想劳动更周详一些,可那种周密带来的结果是自讨没趣。

 

在统一筹划中,有其它一种常见的情势与之相似,却能取得不一样的功用,那就是Fluent
Interface方式,它平时被翻译为“连贯接口”。Fluent
Interface首要行使在DSL(Domain Specific Language)中。MartinFowler将其定义为“能够为一种类措施调用中转或爱慕指令上下文的行为”。Fluent
Interface中定义的办法日常是回来该项目笔者的实例。Fluent
Interface方式在无数动态语言如php、ruby中获取多量采纳。C#的LINQ也采纳了该形式。ThoughtWorks的见解总领Neal
Ford在其多重小说埃沃lutionary architecture and emergent
design中,介绍了该方式的接纳。文中提供了之类代码,以演示Java中如何兑现Fluent
Interface:

public class Appointment {
    private String _name;
    private String _location;
    private Calendar _startTime;
    private Calendar _endTime;

    public Appointment(String name) {
        this._name = name;
    }

    public Appointment() {
    }

    public Appointment name(String name) {
        _name = name;
        return this;
    }
    public Appointment at(String location) {
        _location = location;
        return this;
    }

    public Appointment at(Calendar startTime) {
        _startTime = startTime;
        return this;
    }

    public Appointment from(Calendar startTime) {
        _startTime = startTime;
        return this;
    }

    public Appointment to(Calendar endTime) {
        _endTime = endTime;
        return this;
    }

    public String toString() {
        return "Appointment:"+ _name +
                ((_location != null && _location.length() > 0) ? 
                    ", location:" + _location : "") +
                ", Start time:" + _startTime.get(Calendar.HOUR_OF_DAY) +
                (_endTime != null? ", End time: " + 
                _endTime.get(Calendar.HOUR_OF_DAY) : "");
    }
}

 

以下是Fluent Interface的使用:

AppointmentCalendarChained calendar =
            new AppointmentCalendarChained();
calendar.add("dentist").
         from(fourPM).
         to(fivePM).
         at("123 main street");

其间,AppointmentCalendarChained类的add()方法再次来到的是实现了Fluent
Interface情势的Appointment对象。

 

行使Fluent
Interface方式的代码,具有自个儿演说领域逻辑的能力,它差别于Message
Chains,因为它的意向并不是要展现信息传递的进度。Fluent
Interface中各种方法都以调用者须求关切的。而且,Fluent
Interface方法能够自由组合,并不便宜封装。由于调用形式是完全一致的,只要有了合理的命名,代码的连贯性就像行云流水。领域驱动设计的布道者Eric埃文思曾提及,他所接触到的Fluent Interface都以用来装配Value Object。Value
Object没有兼具业务领域意义的实体与之相应,它们可以被随心创制随心抛掉。本例中的Appointment正是如此的Value
Object。有关Value Object的知识,请参考埃里克 埃文思的经文佳作Domain Driven
Design-Tackling Complexsity in the Heart of Software。

相关文章