Является ли это правильным способом создания шаблона компоновщика в реальной программной среде? Короче говоря, каков наилучший способ создать шаблон строителя в Java - PullRequest
0 голосов
/ 12 июня 2019

- это правильный способ создания шаблона компоновщика в Java, если нет возможных изменений.

пробовал со статическим классом


public class Multiverse {

    private UUID universeId;
    private String universeName;
    private String universeType;
    private Boolean humanExistence;

    public Boolean getHumanExistence() {
        return humanExistence;
    }

    private Multiverse() {
          throw new IllegalStateException("Can`t create object from constructor: try using builder");

    }


    private Multiverse(UUID universeId, String universeName, String universeType, Boolean humanExistence) {
        super();
        this.universeId = universeId;
        this.universeName = universeName;
        this.universeType = universeType;
        this.humanExistence = humanExistence;
    }


    public static class MultiverseBuilder{
            private UUID universeId;
            private String universeName;
            private String universeType;
            private Boolean humanExistence;

            public MultiverseBuilder makeUUId(UUID uuid) {
                this.universeId=uuid;
                return  this;
            }

            public MultiverseBuilder createUniverse(String univ) {
                this.universeName=univ;
                return this;

            }

            public MultiverseBuilder setUniverseType(String universeType ) {
                this.universeType=universeType;
                return this;
            }
            public MultiverseBuilder isHumanExists(Boolean humanExistence) {
                this.humanExistence=humanExistence;
                return this;
            }

        public Multiverse build() {
            return new Multiverse(universeId,universeName,universeType,humanExistence);
        }


    } 

    public UUID getUniverseId() {
        return universeId;
    }
    public String getUniverseName() {
        return universeName;
    }
    public String getUniverseType() {
        return universeType;
    }



}


Junit5 test

public class AssertionsTest6 {
    private static Logger logger=Logger.getLogger(AssertionsTest6.class.getName());

    Multiverse multiverse;

    @BeforeEach
    void init(){
        multiverse=new Multiverse.MultiverseBuilder()
                                 .makeUUId(UUID.randomUUID())
                                 .createUniverse("Earth")
                                 .setUniverseType("Big Bang")
                                 .isHumanExists(true)
                                 .build();  
        }

    @Test
    @DisplayName("Builder Testing")
    void TestBuilder() {
        assertEquals("Big Bang", multiverse.getUniverseType(), "test failed");
        logger.info("Builder testing");
    }



}

заблокировал отражение, чтобы сделать объект непосредственно из класса Multiverse, сделав это

private Multiverse() {
          throw new IllegalStateException("Can`t create object from constructor: try using builder");

    }

ожидаемым и фактическим, то же самое.но не уверен, что это лучший способ достичь цели.пожалуйста, исправьте или предложите мне это, [требуется консультация специалиста]

Ответы [ 2 ]

1 голос
/ 12 июня 2019

Особенности проектирования:

  • принудительное использование компоновщика (прямое создание экземпляров не разрешено)?
  • неизменность (что происходит, когдаВызов сеттеров на компоновщике после создания экземпляра)?
  • возможность повторного использования : разрешить компоновщику создавать несколько экземпляров?

Пример для многоразового компоновщикаможет использоваться для создания ровно одного экземпляра , который фактически неизменен :

public class Multiverse {

    private UUID universeId;
    private String universeName;
    private String universeType;
    private Boolean humanExistence;

    private Multiverse() {
    }

    public UUID getUniverseId() {
        return universeId;
    }

    public String getUniverseName() {
        return universeName;
    }

    public String getUniverseType() {
        return universeType;
    }

    public Boolean getHumanExistence() {
        return humanExistence;
    }

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

    public static class Builder {

        private final Multiverse instance = new Multiverse();
        private boolean consumed;

        private Builder set(Consumer<Multiverse> access) {
            if (consumed) {
                throw new IllegalStateException("already consumed");
            }
            access.accept(instance);
            return this;
        }

        public Builder universeId(UUID universeId) {
            return set(x -> x.universeId = universeId);
        }

        public Builder universeName(String universeName) {
            return set(x -> x.universeName = universeName);
        }

        public Builder universeType(String universeType) {
            return set(x -> x.universeType = universeType);
        }

        public Builder humanExistence(Boolean humanExistence) {
            return set(x -> x.humanExistence = humanExistence);
        }

        public Multiverse build() {
            consumed = true;
            return instance;
        }
    }
}

Соглашение о присвоении имен aMultiVerse() для доступа к компоновщику позволяет staticимпорт метода фабричного строителя без столкновения с другими фабричными методами строителя:

 Multiverse multiverse = aMultiverse()
     .universeId(UUID.randomUUID())
     .universeName("Earth")
     .universeType("Big Bang")
     .humanExistence(true)
     .build();
0 голосов
/ 12 июня 2019

Некоторые замечания о вашем подходе:

  • Не думаю, что имеет смысл «блокировать» пользователей от создания экземпляра с помощью отражения.Поскольку вы определили конструктор, в любом случае нет никакого конструктора без аргументов.Таким образом, экземпляры могут быть созданы только путем передачи компоновщика.
  • Мне нравится передавать экземпляр компоновщика конструктору.Таким образом, вы получите читаемый код, даже если в классе много полей.
  • Мне нравится называть моего строителя просто Builder.Это вложенный класс, и вы, вероятно, всегда будете писать Multiverse.Builder.
  • Мне нравится, что в настоящем классе есть метод фабрики для конструктора, поэтому я могу просто написать Multiverse.builder() и начать заполнять поля.
  • Методы класса построителя должны иметь согласованную схему именования.

Вот как обычно выглядят мои сборщики:

public class Multiverse {

    private final UUID universeId;

    private final String universeName;

    private final String universeType;

    private final Boolean humanExistence;

    private Multiverse(Builder builder) {
        this.universeId = builder.universeId;
        this.universeName = builder.universeName;
        this.universeType = builder.universeType;
        this.humanExistence = builder.humanExistence;
    }

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

    public UUID getUniverseId() {
        return universeId;
    }

    public String getUniverseName() {
        return universeName;
    }

    public String getUniverseType() {
        return universeType;
    }

    public Boolean getHumanExistence() {
        return humanExistence;
    }

    public Builder toBuilder() {
        return new Builder(this);
    }

    public static class Builder {

        private UUID universeId;

        private String universeName;

        private String universeType;

        private Boolean humanExistence;

        private Builder() {}

        private Builder(Multiverse multiverse) {
            this.universeId = multiverse.universeId;
            this.universeName = multiverse.universeName;
            this.universeType = multiverse.universeType;
            this.humanExistence = multiverse.humanExistence;
        }

        public Builder withUniverseId(UUID universeId) {
            this.universeId = universeId;
            return this;
        }

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

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

        public Builder withHumanExistence(Boolean humanExistence) {
            this.humanExistence = humanExistence;
            return this;
        }

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

    }

}

Создание мультиверсов работает следующим образом:

Multiverse multiverse1 = Multiverse.builder()
    .withUniverseId(UUID.fromString("550e8400-e29b-11d4-a716-446655440000"))
    .withUniverseName("my first multiverse")
    .withUniverseType("type a")
    .withHumanExistence(true)
    .build();

Если вы решите отредактировать этот мультиверс позже, вы можете сделать это следующим образом:

Multiverse multiverse2 = multiverse1.toBuilder()
    .withUniverseId(UUID.fromString("759e947a-7492-af67-87bd-87de9e7f5e95"))
    .withUniverseName("my second multiverse")
    .build();

Это будет соответствовать следующим утверждениям:

assert multiverse1.getUniverseId().equals("550e8400-e29b-11d4-a716-446655440000");
assert multiverse1.getUniverseName().equals("my first multiverse");
assert multiverse1.getUniverseType.equals("type a");
assert multiverse1.getHumanExistence == true;
assert multiverse2.getUniverseId().equals("759e947a-7492-af67-87bd-87de9e7f5e95");
assert multiverse2.getUniverseName().equals("my second multiverse");
assert multiverse2.getUniverseType.equals("type a");
assert multiverse2.getHumanExistence == true;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...