Foo foo = Foo.builder()
    .setColor(red)
    .setName("Fred")
    .setSize(42)
    .build();

所以我知道有以下“Builder”解决方案用于在调用方法时创建命名参数。虽然,这似乎只适用于作为构建器的内部静态类,还是我错了?我查看了一些关于构建器模式的教程,但对于我尝试做的事情来说,它们似乎非常复杂。有没有什么办法可以让 Foo 类和 Builder 类分开,同时还能像上面的代码一样享受命名参数的好处?

下面是一个典型的设置:
public class Foo {
    public static class Builder {
        public Foo build() {
            return new Foo(this);
        }

        public Builder setSize(int size) {
            this.size = size;
            return this;
        }

        public Builder setColor(Color color) {
            this.color = color;
            return this;
        }

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

        // you can set defaults for these here
        private int size;
        private Color color;
        private String name;
    }

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

    private Foo(Builder builder) {
        size = builder.size;
        color = builder.color;
        name = builder.name;
    }

    private final int size;
    private final Color color;
    private final String name;
}

最佳答案

使用组合。为了使事情更容易和更清晰,不要复制源( Foo )和构建器( Builder )类中的所有属性。

例如,在 Foo 中有 Builder 类而不是每个 Foo 属性。

简单的代码片段:

import java.util.*;

class UserBasicInfo{
    String nickName;
    String birthDate;
    String gender;

    public UserBasicInfo(String name,String date,String gender){
        this.nickName = name;
        this.birthDate = date;
        this.gender = gender;
    }

    public String toString(){
        StringBuilder sb = new StringBuilder();
        sb.append("Name:DOB:Gender:").append(nickName).append(":").append(birthDate).append(":").
        append(gender);
        return sb.toString();
    }
}

class ContactInfo{
    String eMail;
    String mobileHome;
    String mobileWork;

    public ContactInfo(String mail, String homeNo, String mobileOff){
        this.eMail = mail;
        this.mobileHome = homeNo;
        this.mobileWork = mobileOff;
    }
    public String toString(){
        StringBuilder sb = new StringBuilder();
        sb.append("email:mobile(H):mobile(W):").append(eMail).append(":").append(mobileHome).append(":").append(mobileWork);
        return sb.toString();
    }
}
class FaceBookUser {
    String userName;
    UserBasicInfo userInfo;
    ContactInfo contactInfo;

    public FaceBookUser(String uName){
        this.userName = uName;
    }
    public void setUserBasicInfo(UserBasicInfo info){
        this.userInfo = info;
    }
    public void setContactInfo(ContactInfo info){
        this.contactInfo = info;
    }
    public String getUserName(){
        return userName;
    }
    public UserBasicInfo getUserBasicInfo(){
        return userInfo;
    }
    public ContactInfo getContactInfo(){
        return contactInfo;
    }

    public String toString(){
        StringBuilder sb = new StringBuilder();
        sb.append("|User|").append(userName).append("|UserInfo|").append(userInfo).append("|ContactInfo|").append(contactInfo);
        return sb.toString();
    }

    static class FaceBookUserBuilder{
        FaceBookUser user;
        public FaceBookUserBuilder(String userName){
            this.user = new FaceBookUser(userName);
        }
        public FaceBookUserBuilder setUserBasicInfo(UserBasicInfo info){
            user.setUserBasicInfo(info);
            return this;
        }
        public FaceBookUserBuilder setContactInfo(ContactInfo info){
            user.setContactInfo(info);
            return this;
        }
        public FaceBookUser build(){
            return user;
        }
    }
}
public class BuilderPattern{
    public static void main(String args[]){
        FaceBookUser fbUser1 = new FaceBookUser.FaceBookUserBuilder("Ravindra").build(); // Mandatory parameters
        UserBasicInfo info = new UserBasicInfo("sunrise","25-May-1975","M");

        // Build User name + Optional Basic Info
        FaceBookUser fbUser2 = new FaceBookUser.FaceBookUserBuilder("Ravindra").
                                                setUserBasicInfo(info).build();

        // Build User name + Optional Basic Info + Optional Contact Info
        ContactInfo cInfo = new ContactInfo("[email protected]","1111111111","2222222222");
        FaceBookUser fbUser3 = new FaceBookUser.FaceBookUserBuilder("Ravindra").
                                                setUserBasicInfo(info).
                                                setContactInfo(cInfo).build();

        System.out.println("Facebook user 1:"+fbUser1);
        System.out.println("Facebook user 2:"+fbUser2);
        System.out.println("Facebook user 3:"+fbUser3);
    }
}

输出:
Facebook user 1:|User|Ravindra|UserInfo|null|ContactInfo|null
Facebook user 2:|User|Ravindra|UserInfo|Name:DOB:Gender:sunrise:25-May-1975:M|ContactInfo|null
Facebook user 3:|User|Ravindra|UserInfo|Name:DOB:Gender:sunrise:25-May-1975:M|ContactInfo|email:mobile(H):mobile(W):[email protected]:1111111111:2222222222

解释:
  • FaceBookUser 是一个复杂的对象,使用组合具有以下属性:
    String userName;
    UserBasicInfo userInfo;
    ContactInfo contactInfo;
    
  • FaceBookUserBuilder 是一个静态构建器类,它包含并构建 FaceBookUser
  • userName 只是构建 FaceBookUser 的强制参数
  • FaceBookUserBuilder 通过设置可选参数来构建 FaceBookUser:UserBasicInfoContactInfo
  • 这个例子说明了三个不同的 FaceBookUsers 具有不同的属性,由 Builder 构建。
  • fbUser1 作为 FaceBookUser 构建,只有 userName 属性
  • fbUser2 被构建为 FaceBookUser,带有 userName 和 UserBasicInfo
  • fbUser3 作为 FaceBookUser 构建,包含 userName、UserBasicInfo 和 ContactInfo

  • 在此示例中,使用组合而不是复制 Builder 类中 FaceBookUser 的所有属性。

    编辑:

    将所有相关属性分组为逻辑类。在 FaceBookUser 中定义所有这些类。不要在 Builder 中再次添加所有这些成员变量,而是在 FaceBookUser 类中包含 Builder

    为简单起见,我添加了两个类: UserBasicInfo 和 ContactInfo 。现在用其他属性分解这个 FaceBookUser 类,例如
    NewsFeed
    Messages
    Friends
    Albums
    Events
    Games
    Pages
    Ads
    

    等等。

    如果在 BuilderFaceBookUser 中复制所有这些属性,代码将变得难以管理。相反,通过在 FaceBookUser 本身中使用 FaceBookUserBuilder 的组合,您可以简单地构建过程。

    添加上述属性后,您将像往常一样逐步构建 FaceBookUser

    它会是这样的:
    FaceBookUser fbUser3 = new FaceBookUser.FaceBookUserBuilder("Ravindra").
                                            setUserBasicInfo(info).
                                            setNewsFeed(newsFeed).
                                            setMessages(messages).
                                            setFriends(friends).
                                            setAlbums(albums).
                                            setEvents(events).
                                            setGames(games).
                                            setAds(ads).build();
    

    关于java - 将构建器保留在单独的类中(流畅的界面),我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/39708728/

    10-09 15:58