Java链式对象构造的正确姿势

开发业务代码过程中,如果能过类似JQuey那种链式编程或者Java中的Builder模式一样可以一直点下去,是一种非常爽的体验。

如果内部有一些类似Map、JSONObject的属性,怎样更表意呢?怎样隐藏内部数据结构呢?

普通的Builder模式应该外部创建Map或者JSONObject对象并赋值,能否有更好的解决方案呢?

当然也可以通过uilder中写一个put方法可以避免多出现一个对象但是如何更表意呢?

 public Builder put(String key, String value){
            data.put(key, value);
            return this;
        }

下面介绍一个不错的技巧

一、一个不错的技巧

借助Builder模式和中间类实现链式编程和淡化内部特殊类型(JSONObject)的属性的效果。



import com.alibaba.fastjson.JSONObject;
import lombok.Data;

/**
 * 明明如月
 * [email protected]
 */
@Data
public class MyConfig {
    private JSONObject data;

    private String appName;

    private Long logTime;

    private MyConfig(Builder builder) {
        this.data = builder.data;
        this.appName = builder.appName;
        this.logTime = builder.logTime;
    }

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

    public static class Builder {
        private JSONObject data = new JSONObject();

        private String appName;

        private Long logTime;

        public Builder appName(String appName) {
            this.appName = appName;
            return this;
        }

        public Builder logTime(Long logTime) {
            this.logTime = logTime;
            return this;
        }

        public SemiData key(String key) {
            return new SemiData(this, key);
        }

        public MyConfig build() {
            return new MyConfig(this);
        }

        public class SemiData {
            private String key;
            private Builder parent;

            private SemiData(Builder myConfig, String key) {
                this.parent = myConfig;
                this.key = key;
            }

            public Builder value(Object value) {
                parent.data.put(key, value);
                return parent;
            }
        }
    }

}

用法

 @Test
    void builder() {

        String appName = "test";
        Long currentTime = System.currentTimeMillis();
        MyConfig myConfig = MyConfig.builder()
                .appName(appName)
                .logTime(currentTime)
                .key("name").value("张三")
                .key("age").value(24)
                .key("sex").value("男")
                .build();

        assertEquals(appName, myConfig.getAppName());
        assertEquals(currentTime, myConfig.getLogTime());

        JSONObject data = myConfig.getData();
        assertEquals(data.get("name"),"张三");
    }

 

 

二、另外一种变种

不使用Builder模式,通过中间类实现链式编程和淡化内部特护类型(JSONObject)的属性的效果。



import com.alibaba.fastjson.JSONObject;
import lombok.Data;

/**
 * 明明如月
 * [email protected]
 */
@Data
public class MyConfig {
    private JSONObject data = new JSONObject();

    private String appName;

    private Long logTime;

    public MyConfig appName(String appName) {
        this.appName = appName;
        return this;
    }

    public MyConfig logTime(Long logTime) {
        this.logTime = logTime;
        return this;
    }

    public SemiData key(String key) {
        return new SemiData(this, key);
    }

    public class SemiData {
        private String key;
        private MyConfig parent;

        private SemiData(MyConfig myConfig, String key) {
            this.parent = myConfig;
            this.key = key;
        }

        public MyConfig value(Object value) {
            parent.data.put(key, value);
            return parent;
        }
    }

}

用法

@Test
    void builder() {

        String appName = "test";
        Long currentTime = System.currentTimeMillis();
        MyConfig myConfig = new MyConfig().appName(appName)
                .logTime(currentTime)
                .key("name").value("张三")
                .key("age").value(24)
                .key("sex").value("男");

        assertEquals(appName, myConfig.getAppName());
        assertEquals(currentTime, myConfig.getLogTime());

        JSONObject data = myConfig.getData();
        assertEquals(data.get("name"),"张三");

    }

 

 

 

 

你可能感兴趣的:(Java基础,通用方案)