Builder模式 和 Fluent Interface

Posted ~无关风月~

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Builder模式 和 Fluent Interface相关的知识,希望对你有一定的参考价值。

Builder模式

建造者模式(Builder Pattern)也叫做生成器模式。

Separate the construction of a complex object from its representation so that the same construction precess can create different representaions.(将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。)

详见:
https://lovezxm.blog.csdn.net/article/details/118276586

Fluent Interface

连贯接口fluent interfaces)不仅仅能提供 类型 method chainingBuilder模式的方法级联调用,更重要的是能限定方法调用的顺序。

连贯接口不仅仅在提供API,其连贯性带来的可读性和可理解性,也是一种领域语言,是一种Internal DSL。
DSL的核心价值——更加清晰地表达系统中,某一部分的设计意图和业务语义。

本文将介绍,如何通过连贯接口来使用和实现Builder模式。

当我们在构造一个超级复杂的Object的时候。比如某企业级Order订单类这个非常核心而且非常重要,不允许出错的实体类。可能会在编写的过程中漏掉某个setter,从而缺失了某个属性值。
所以我们需要使用这种Fluent Builder模式来避免这类问题:
以邮件实体类为例,我们需要定义一下重要(必需)和可选属性,强制必须填写的是from、to、subject和content,抄送bcc和cc是可选的。

我们需要根据流畅接口的下一个行为(fluent action)去选择返回类型。这种风格的一个很好的优点是方法补完后(intellisense)有助于告诉你接下来要键入什么 —— 有点像 IDE 中的智能提示。

public final class Email {
    // To Address. Multiple Address separated by ","
    String to;
    // From Address
    String from;
    // Subject of the email
    String subject;
    // Content of the email
    String content;
    // BCC optional
    String bcc;
    // CC Optional
    String cc;

    /**
     * Private constructor to prevent the object initialization
     */
    private Email(String to, String from, String subject, String content, String bcc, String cc) {
        this.to = to;
        this.from = from;
        this.subject = subject;
        this.content = content;
        this.bcc = bcc;
        this.cc = cc;
    }

    public String getTo() {
        return to;
    }
    public String getFrom() {
        return from;
    }
    public String getSubject() {
        return subject;
    }
    public String getContent() {
        return content;
    }
    public String getBcc() {
        return bcc;
    }
    public String getCc() {
        return cc;
    }

    @Override
    public String toString() {
        return "Email{" +
            "to='" + to + '\\'' +
            ", from='" + from + '\\'' +
            ", subject='" + subject + '\\'' +
            ", content='" + content + '\\'' +
            ", bcc='" + bcc + '\\'' +
            ", cc='" + cc + '\\'' +
            '}';
    }
    
    // 为设置属性创建一条接口链,每个方法返回类型是接口链的下一个接口
    // Interface to Set From
    interface EmailFrom {
        EmailTo setFrom(String from);
    }
    // Interface to Set To
    interface EmailTo {
        EmailSubject setTo(String to);
    }
    // Interface to Set subject
    interface EmailSubject {
        EmailContent setSubject(String subject);
    }
    // Interface to set Content
    interface EmailContent {
        EmailCreator setContent(String content);
    }
    // 对于所有可选属性,只需要在链的最后一个接口创建方法和build方法
    // Final Email Creator Class
    interface EmailCreator {
        EmailCreator setBCC(String bcc);
        EmailCreator setCC(String cc);
        Email build();
    }

    /**
     * Static class for building the email object
     */
    public static class EmailBuilder implements EmailFrom, EmailTo, EmailSubject, EmailContent, EmailCreator {
        String to;
        String from;
        String subject;
        String content;
        String bcc;
        String cc;

        /**
         * Private emailbuilder to prevent direct object creation
         */
        private EmailBuilder() {
        }

        /**
         * Getting the instance method
         * @return
         */
        public static EmailFrom getInstance() {
            return new EmailBuilder();
        }

        @Override
        public EmailTo setFrom(String from) {
            this.from = from;
            return this;
        }
        @Override
        public EmailSubject setTo(String to) {
            this.to = to;
            return this;
        }
        @Override
        public EmailContent setSubject(String subject) {
            this.subject = subject;
            return this;
        }
        @Override
        public EmailCreator setContent(String content) {
            this.content = content;
            return this;
        }
        @Override
        public EmailBuilder setBCC(String bcc) {
            this.bcc = bcc;
            return this;
        }
        @Override
        public EmailBuilder setCC(String cc) {
            this.cc = cc;
            return this;
        }
        @Override
        public Email build() {
            return new Email(to, from, subject, content, bcc, cc);
        }
    }
}

/**
 * Test Class
 */
public class EmailTest {
    public static void main(String args[]){
        //Creating basic email object without cc and bcc
        Email email =  Email.EmailBuilder.getInstance().setFrom("Test@gmail.com").setTo("mail@gmail.com")
                .setSubject("Test with only required Fields").setContent(" Required Field Test").build();
        System.out.println(email);

        //Creating the full Email Object with cc and bcc
        email =  Email.EmailBuilder.getInstance().setFrom("Test@gmail.com").setTo("mail@gmail.com")
                .setSubject("Test with ALL Fields").setContent(" ALL Field Test").setBCC("bcc@gmail.com")
                .setCC("cc@gmail.com").build();
        System.out.println(email);
    }
}

参考:
【1】Introduction to the Fluent Builder Pattern
【2】Builder Pattern and Fluent Interface
【3】FluentInterface

以上是关于Builder模式 和 Fluent Interface的主要内容,如果未能解决你的问题,请参考以下文章

Builder模式 和 Fluent Interface

Builder模式 和 Fluent Interface

Builder模式 和 Fluent Interface

UIView 的子类。如何通过 Interface Builder 添加?

Fluent NHibernate - 仅在不存在时创建数据库模式

流畅的界面和 Builder 模式有啥区别?