java链式编程/级联式编程

Posted 菠萝科技

tags:

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

链式编程,也叫级联式编程,调用对象的函数时返回一个this对象指向对象本身,达到链式效果,可以级联调用。

链式编程: 通过高阶函数以点为连接将多个函数连接在一起完成参数传递和复杂的操作!通俗的说是通过点号(.)链接在一起成为一句代码。

链式编程的优点是:编程性强、可读性强、代码简洁。

举例:

StringBuilder builder = new StringBuilder(96);
builder.append("select id, name from ")
    .append(T_USER)
    .append(" where id = ")
    .append(userId)
    .append(";");

简单举例:

public class User {
    private Integer id;
    private String userName;
    private String password;
    private String nikeName;
    private String email;
    private String phoneNum;

    public Integer getId() {
        return id;
    }

    public User setId(Integer id) {
        this.id = id;
        return this;
    }

    public String getUserName() {
        return userName;
    }

    public User setUserName(String userName) {
        this.userName = userName;
        return this;
    }

    public String getPassword() {
        return password;
    }

    public String getNikeName() {
        return nikeName;
    }

    public User setNikeName(String nikeName) {
        this.nikeName = nikeName;
        return this;
    }

    public String getEmail() {
        return email;
    }

    public User setEmail(String email) {
        this.email = email;
        return this;
    }

    public String getPhoneNum() {
        return phoneNum;
    }

    public User setPhoneNum(String phoneNum) {
        this.phoneNum = phoneNum;
        return this;
    }

    public User setPassword(String password) {
        this.password = password;
        return this;
    }
}

调用:

User user = new User();
user.setId(1).setUserName("name").setPhoneNum("pNo").setNikeName("NikeName").setEmail("xxxxx").setPassword("122");

经典模式

package builder;

/**
 * Builder模式,链式调用Demo<br>
 * 
 * @author junehappylove
 *
 */
public class User {

	private final String firstName;
	private final String lastName;
	private final int age;
	private final String phone;
	private final String address;

	private User(UserBuilder builder) {
		this.firstName = builder.firstName;
		this.lastName = builder.lastName;
		this.age = builder.age;
		this.phone = builder.phone;
		this.address = builder.address;
	}

	public String getFirstName() {
		return firstName;
	}

	public String getLastName() {
		return lastName;
	}

	public int getAge() {
		return age;
	}

	public String getPhone() {
		return phone;
	}

	public String getAddress() {
		return address;
	}
	
	//Builder
	public static class UserBuilder {
		private final String firstName;
		private final String lastName;
		private int age;
		private String phone;
		private String address;

		public UserBuilder(String firstName, String lastName) {
			this.firstName = firstName;
			this.lastName = lastName;
		}

		public UserBuilder age(int age) {
			this.age = age;
			return this;
		}

		public UserBuilder phone(String phone) {
			this.phone = phone;
			return this;
		}

		public UserBuilder address(String address) {
			this.address = address;
			return this;
		}

		public User build() {
			// 由于Builder是非线程安全的,所以如果要在Builder内部类中检查一个参数的合法性,
			// 必需要在对象创建完成之后再检查
			User user = new User(this);
			if (user.getAge() < 0 || user.getAge() > 255) {
				throw new IllegalStateException("Age out of range:" + user.getAge());// 线程安全
			}
			return user;
		}
	}

	public static void main(String[] args) {
		User june = new User.UserBuilder("Wang", "wei").age(18).address("qdao").build();
		System.out.println(june.getAddress());
	}
}
原文链接:https://blog.csdn.net/junehappylove/article/details/85236946
有几个重要的地方需要强调一下:

User类的构造方法是私有的。也就是说调用者不能直接创建User对象。
User类的属性都是不可变的。所有的属性都添加了final修饰符,并且在构造方法中设置了值。并且,对外只提供getters方法。
Builder模式使用了链式调用。可读性更佳。
Builder的内部类构造方法中只接收必传的参数,并且该必传的参数使用了final修饰符。

再看一下一些变种的链式调用:
public class User {
    private String username;
    private String password;

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

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

    private User(Builder builder) {
        this.username = builder.username;
        this.password = builder.password;
    }

    public static class Builder {
        private String username;
        private String password;

        public Builder setUserName(String username) {
            this.username = username;
            return this;
        }
        public Builder setPassword(String password){
            this.password=password;
            return this;
        }
        public User build() {
            return new User(this);
        }

        @Override
        public String toString() {
            return "Builder{" +
                    "username='" + username + '\\'' +
                    ", password='" + password + '\\'' +
                    '}';
        }
    }
    @Override
    public String toString() {
        return "User{" +
                "username='" + username + '\\'' +
                ", password='" + password + '\\'' +
                '}';
    }

    public static void main(String[] args) {
        Builder builder = new User.Builder();
        builder.setUserName("lss0555")
                .setPassword("12345")
                .build();
        //或者
        User user = new User.Builder().setUserName("lss0555").setPassword("123123").build();
        //或者
        User user1 = User.builder().setUserName("lss0555").setPassword("654321").build();

        System.out.println("builder结果:"+builder.toString());
        System.out.println("User结果:"+user.toString());
        System.out.println("User2结果:"+user1.toString());
    }
}

上面这个大架子基本不变,但是

User的属性,没有用final修饰
提供了setters方法
提供了一个静态的builder方法,用于在User中获取Builder对象

Java8 Builder 链式调用示例

public class GenericBuilder<T> {

    private final Supplier<T> instantiator;
    private List<Consumer<T>> instantiatorModifiers = new ArrayList<>();
    private List<Consumer<T>> keyValueModifiers = new ArrayList<>();

    public GenericBuilder(Supplier<T> instantiator) {
        this.instantiator = instantiator;
    }

    public static <T> GenericBuilder<T> of(Supplier<T> instantiator) {
        return new GenericBuilder<T>(instantiator);
    }

    public <U> GenericBuilder<T> with(BiConsumer<T, U> consumer, U value) {
        Consumer<T> c = instance -> consumer.accept(instance, value);
        instantiatorModifiers.add(c);
        return this;
    }

    public <K, V> GenericBuilder<T> with(KeyValueConsumer<T, K, V> consumer, K key, V value) {
        Consumer<T> c = instance -> consumer.accept(instance, key, value);
        keyValueModifiers.add(c);
        return this;
    }

    public T build() {
        T value = instantiator.get();
        instantiatorModifiers.forEach(modifier -> modifier.accept(value));
        keyValueModifiers.forEach(keyValueModifier -> keyValueModifier.accept(value));
        instantiatorModifiers.clear();
        keyValueModifiers.clear();
        return value;
    }

    @FunctionalInterface
    interface KeyValueConsumer<T, K, V> {
        void accept(T t, K k, V v);

        default KeyValueConsumer<T, K, V> andThen(KeyValueConsumer<? super T, ? super K, ? super V> after) {
            Objects.requireNonNull(after);

            return (t, k, v) -> {
                accept(t, k, v);
                after.accept(t, k, v);
            };
        }
    }
}

调用方式

/**
 * @author caishen
 * @version 1.0
 * @className Order
 * @date 2019/12/17 11:15
 * 自分で書いたコードの各行を担当する
 **/
public class Order {

    private String code;

    private List<String> offers;

    private Map<String, Object> features;

    public void addOffer(String offer) {
        offers = Optional.ofNullable(offers).orElseGet(ArrayList::new);
        offers.add(offer);
    }

    public <T> void addFeature(String key, T value) {
        features = Optional.ofNullable(features).orElseGet(HashMap::new);
        features.put(key, value);
    }

    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }

    public List<String> getOffers() {
        return offers;
    }

    public void setOffers(List<String> offers) {
        this.offers = offers;
    }

    public Map<String, Object> getFeatures() {
        return features;
    }

    public void setFeatures(Map<String, Object> features) {
        this.features = features;
    }

    @Override
    public String toString() {
        return "Order{" +
                "code='" + code + '\\'' +
                ", offers=" + offers +
                ", features=" + features +
                '}';
    }

    public static void main(String[] args) {
        Order order = GenericBuilder.of(Order::new).with(Order::setCode, "123").with(Order::addOffer, "满100减50")
                .with(Order::addFeature, "category", "shoe").with(Order::addFeature, "color", "red").build();

        System.out.println(order);
    }
}

其他还有用lombok

Lombok @Builder @Singular 注解 链式调用示例

/**
 * @author caishen
 * @version 1.0
 * @className User
 * @date 2019/12/17 11:37
 * 自分で書いたコードの各行を担当する
 * @Singular注解 必须在@Builder类 里面才生效
 **/
@Setter
@Getter
@NoArgsConstructor
@AllArgsConstructor
@ToString
@Builder
public class User {
    /**
     * id  @Builder.Default 指定默认值
     */
    @Builder.Default
    private int id;
    /**
     * 用户名
     */
    private String userName;
    /**
     * 密码
     */
    private String password;
    /**
     * 年龄
     */
    private int age;
    /**
     * 集合 value属性指定调用名称
     */
    @Singular(value = "add")
    private List<String> keys;
    /**
     * 集合 value属性指定调用名称
     */
    @Singular(value = "put")
    private Map<String,String> maps;

    public static void main(String[] args) {
        User user = User.builder()
                .age(12)
                .id(1)
                .userName("zhangsan")
                .password("123")
                .add("333")
                .add("999")
                .add("123")
                .put("123","234")
                .build();
        System.out.println(user);
    }
}

反编译之后的代码

public class User {
    private int id;
    private String userName;
    private String password;
    private int age;
    private List<String> keys;
    private Map<String, String> maps;

    public static void main(String[] args) {
        User user = builder().age(12).userName("zhangsan").password("123").add("333").add("999").add("123").put("123", "234").build();
        System.out.println(user);
    }

    public static User.UserBuilder builder() {
        return new User.UserBuilder();
    }

    public void setId(int id) {
        this.id = id;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public void setKeys(List<String> keys) {
        this.keys = keys;
    }

    public void setMaps(Map<String, String> maps) {
        this.maps = maps;
    }

    public int getId() {
        return this.id;
    }

    public String getUserName() {
        return this.userName;
    }

    public String getPassword() {
        return this.password;
    }

    public int getAge() {
        return this.age;
    }

    public List<String> getKeys() {
        return this.keys;
    }

    public Map<String, String> getMaps() {
        return this.maps;
    }

    public User() {
    }

    @ConstructorProperties({"id", "userName", "password", "age", "keys", "maps"})
    public User(int id, String userName, String password, int age, List<String> keys, Map<String, String> maps) {
        this.id = id;
        this.userName = userName;
        this.password = password;
        this.age = age;
        this.keys = keys;
        this.maps = maps;
    }

    public String toString() {
        return "User(id=" + this.getId() + ", userName=" + this.getUserName() + ", password=" + this.getPassword() + ", age=" + this.getAge() + ", keys=" + this.getKeys() + ", maps=" + this.getMaps() + ")";
    }

    public static class UserBuilder {
        private int id;
        private String userName;
        private String password;
        private int age;
        private ArrayList<String> keys;
        private ArrayList<String> maps$key;
        private ArrayList<String> maps$value;

        UserBuilder() {
        }

        public User.UserBuilder id(int id) {
            this.id = id;
            return this;
        }

        public User.UserBuilder userName(String userName) {
            this.userName = userName;
            return this;
        }

        public User.UserBuilder password(String password) {
            this.password = password;
            return this;
        }

        public User.UserBuilder age(int age) {
            this.age = age;
            return this;
        }

        public User.UserBuilder add(String add) {
            if (this.keys == null) {
                this.keys = new ArrayList();
            }

            this.keys.add(add);
            return this;
        }

        public User.UserBuilder keys(Collection<? extends String> keys) {
            if (this.keys == null) {
                this.keys = new ArrayList();
            }

            this.keys.addAll(keys);
            return this;
        }

        public User.UserBuilder clearKeys() {
            if (this.keys != null) {
                this.keys.clear();
            }

            return this;
        }

        public User.UserBuilder put(String putKey, String putValue) {
            if (this.maps$key == null) {
                this.maps$key = new ArrayList();
                this.maps$value = new ArrayList();
            }

            this.maps$key.add(putKey);
            this.maps$value.add(putValue);
            return this;
        }

        public User.UserBuilder maps(Map<? extends String, ? extends String> maps) {
            if (this.maps$key == null) {
                this.maps$key = new ArrayList();
                this.maps$value = new ArrayList();
            }

            Iterator var2 = maps.entrySet().iterator();

            while(var2.hasNext()) {
                Entry<? extends String, ? extends String> $lombokEntry = (Entry)var2.next();
                this.maps$key.add($lombokEntry.getKey());
                this.maps$value.add($lombokEntry.getValue());
            }

            return this;
        }

        public User.UserBuilder clearMaps() {
            if (this.maps$key != null) {
                this.maps$key.clear();
                this.maps$value.clear();
            }

            return this;
        }

        public User build() {
            List keys;
            switch(this.keys == null ? 0 : this.keys.size()) {
            case 0:
                keys = Collections.emptyList();
                break;
            case 1:
                keys = Collections.singletonList(this.keys.get(0));
                break;
            default:
                keys = Collections.unmodifiableList(new ArrayList(this.keys));
            }

            Map maps;
            switch(this.maps$key == null ? 0 : this.maps$key.size()) {
            case 0:
                maps = Collections.emptyMap();
                break;
            case 1:
                maps = Collections.singletonMap(this.maps$key.get(0), this.maps$value.get(0));
                break;
            default:
                Map<String, String> maps = new LinkedHashMap(this.maps$key.size() < 1073741824 ? 1 + this.maps$key.size() + (this.maps$key.size() - 3) / 3 : 2147483647);

                for(int $i = 0; $i < this.maps$key.size(); ++$i) {
                    maps.put(this.maps$key.get($i), (String)this.maps$value.get($i));
                }

                maps = Collections.unmodifiableMap(maps);
            }

            return new User(this.id, this.userName, this.password, this.age, keys, maps);
        }

        public String toString() {
            return "User.UserBuilder(id=" + this.id + ", userName=" + this.userName + ", password=" + this.password + ", age=" + this.age + ", keys=" + this.keys + ", maps$key=" + this.maps$key + ", maps$value=" + this.maps$value + ")";
        }
    }
}

参考:

https://blog.csdn.net/junehappylove/article/details/85236946

https://www.cnblogs.com/ButterflyStars/p/13211378.html

https://zhuanlan.zhihu.com/p/98005320

以上是关于java链式编程/级联式编程的主要内容,如果未能解决你的问题,请参考以下文章

代码讲解——用diffusion models级联式超分辨重建

代码讲解——用diffusion models级联式超分辨重建

E72模块化级联式压电控制器

级联式高压变频的单元故障处理以及FPGA的模拟内存

java之Lambda函数式编程最佳应用举例,链式语法「真干货来拿走」

JQuery的链式编程,隐式迭代是什么意思