许可优化
许可优化
产品
产品
解决方案
解决方案
服务支持
服务支持
关于
关于
软件库
当前位置:服务支持 >  软件文章 >  Fluent Interface是什么?语义正确性与连贯性保证方法

Fluent Interface是什么?语义正确性与连贯性保证方法

阅读数 3
点赞 0
article_banner

Fluent Interface(流畅接口)是一种编程模式,旨在创建易于阅读和使用的 代码 。它通过使用方法链(method chaining)来实现连续的调用。

在使用流畅接口时,每个方法调用都返回当前对象的引用,以实现链式调用。这样的设计使得代码更加清晰和可读,提供了一种自然的、连贯的 交互 方式。

以下是一个使用流畅接口的示例,假设存在一个名为Person的 类  

public class Person {
    private String name;
    private Integer age;

    public Person setName(String name) {
        this.name = name;
        return this;
    }

    public Person setAge(Integer age) {
        this.age = age;
        return this;
    }

    public String getName() {
        return name;
    }

    public Integer getAge() {
        return age;
    }
}

使用流畅接口,可以这样调用:

Person person = new Person()
      .setName("John")
      .setAge(25);

在上述示例中,setName()和setAge()方法都返回Person对象的引用,因此可以通过链式调用来设置属性值。

那如何让 setName 只能在 setAge 之后调用呢?

要实现在调用setName()之前必须先调用setAge()的限制,可以使用一种叫做"Builder模式"的设计模式来实现。

   我们对 Person 类进行改造:

public class Person {
    private String name;
    private Integer age;

    private Person() {
    }

    public static Builder newBuilder() {
        return new Builder();
    }

    public String getName() {
        return name;
    }

    public Integer getAge() {
        return age;
    }

    public static class Builder {
        private Person person;

        private Builder() {
            person = new Person();
        }

        public Builder setAge(Integer age) {
            person.age = age;
            return this;
        }

        public Builder setName(String name) {
            if (person.age != null) {
                person.name = name;
            } else {
                throw new IllegalStateException("Please set age before setting the name.");
            }
            return this;
        }

        public Person build() {
            return person;
        }
    }
}

使用Builder模式,现在可以这样调用:

Person person = Person.newBuilder()
        .setAge(25)
        .setName("John")
        .build();

在这个示例中,只有在先调用setAge()方法之后,才能调用setName()方法。如果尝试在没有调用setAge()的情况下调用setName(),会抛出IllegalStateException异常。

Builder模式的好处是可以提供更多的约束和校验逻辑,确保对象的正确创建。同时,它也提供了一种流畅的接口,使代码更易读和易用。

抛出异常不优雅,能否强制指定调用的顺序?

我们可以通过利用接口来实现这个需求,以下是 优化 后的代码:

public interface Step1 {
    Step2 setAge(Integer age);
}

public interface Step2 {
    Person.Builder setName(String name);
}

public class Person {
    private String name;
    private Integer age;

    private Person() {
    }

    public static Step1 newBuilder() {
        return new Builder();
    }

    public String getName() {
        return name;
    }

    public Integer getAge() {
        return age;
    }

    public static class Builder implements Step1, Step2 {
        private final Person person;

        private Builder() {
            person = new Person();
        }

        public Step2 setAge(Integer age) {
            person.age = age;
            return this;
        }

        public Builder setName(String name) {
            person.name = name;
            return this;
        }

        public Person build() {
            return person;
        }
    }

    public static void main(String[] args) {
        Person person = Person.newBuilder().setAge(25).setName("Tom").build();
        // 格式化输出
        System.out.printf("age: %d, name: %s", person.getAge(), person.getName());
    }
}

优化后我们可以看到,在代码提示里只会出现指定的方法,满足了按顺序调用的需求。
在这里插入图片描述
免责声明:本文系网络转载或改编,未找到原创作者,版权归原作者所有。如涉及版权,请联系删


相关文章
技术文档
QR Code
微信扫一扫,欢迎咨询~
customer

online

联系我们
武汉格发信息技术有限公司
湖北省武汉市经开区科技园西路6号103孵化器
电话:155-2731-8020 座机:027-59821821
邮件:tanzw@gofarlic.com
Copyright © 2023 Gofarsoft Co.,Ltd. 保留所有权利
遇到许可问题?该如何解决!?
评估许可证实际采购量? 
不清楚软件许可证使用数据? 
收到软件厂商律师函!?  
想要少购买点许可证,节省费用? 
收到软件厂商侵权通告!?  
有正版license,但许可证不够用,需要新购? 
联系方式 board-phone 155-2731-8020
close1
预留信息,一起解决您的问题
* 姓名:
* 手机:

* 公司名称:

姓名不为空

姓名不为空

姓名不为空
手机不正确

手机不正确

手机不正确
公司不为空

公司不为空

公司不为空