빌더

4833 단어 java
엔 엘 post anterior vimos cómo usar Factorias y las ventajas que estas pueden aportar sobre los constructores

En este post vamos a ver otra forma de construir objetos, los Builders.

"많은 생성자 매개변수에 직면했을 때 빌더를 고려하십시오."



Tanto el uso de factorías como el de constructores tienen un problema cuando el número de parametros para construir una clase empieza a ser elevado

노트

당신은 얼마나 높은가? pues cada cual tendrá su opinión pero en mi opinión más de tres parametros ya es una
señal de que esa clase va a necesitar más bien pronto que tarde otro parametro más y sería buena 아이디어 aplicar
유엔 빌더

정보

Cuando, tanto con factorías como constructores, empiezas a crear métodos con parametros necesarios y
luego otros métodos en los que vas añadiendo cada vez un parametro opcional se llama "망원 건설자"



class A{
    public static A newInstance(){
        return new A();
    }
    public static A newInstance(String nombre){
        return new A(nombre);
    }
    public static A newInstance(String nombre, int edad){
        return new A(nombre, edad...);
    }
    public static A newInstance(String nombre, int edad, Date nacimiento){
        return new A(nombre, edad...);
    }
    public static A newInstance(String nombre, int edad, Date nacimiento, Ciudad ciudad){
        return new A(nombre, edad...);
    }
    ...
}


Otra forma de inicializar objetos cuando el número de parametros es numeroso es aplicando la aproximación de JavaBeans creando métodos get/set para cada propiedad de la instancia. Sin embargo esta forma tiene muchos problemas como por ejemplo la validation de que todos los parametros han sido proporcionados, es muy "verbose", dificil de seguir y no puede crear objetos inmutables.

빌더



Por todo ello el otro patrón que se aplica es creando un Builder
class A{

    private final int prp1;
    private final int prp2;
    ...
    private final int prpn;

    public int getPrp1() { return prp1;}
    // NO tenemos metodo setPrp1

    public static class Builder{
        private final int prp1;
        private final int prp2;
        ...
        private final int prpn;

        public Builder(){}

        public Builder prp1(int p){ prp1 = p; return this;}
        ...
        public Builder prpn(int p){ prpn = p; return this;}

        public A build(){
            // validar que tenemos todos los parametros necesarios
            return new A(this);
        }
    }
    private A(Builder builder){
        prp1 = builder.prp1;
        ...
        prpn = builder.prpn;
    }
}


y el código para crear una instancia A sería:

A a = new A.Builder().prpn(n).prp2(2).prp1(1).build();





Si por ejemplo la clase requiere de unos parametros requeridos es fácil pedirlos
en el 생성자 del Builder y 선언은 명시적 요구 사항으로 간주됩니다.

"빌더 패턴은 클래스 계층 구조에 적합합니다."



Esta capacidad del patrón Builder no es fácil de ver de primeras (al menos a mí) pero es muy potente

Cuando tenemos una jerarquía de objetos tipo clase base "A"y otras clases que extienden de ella, "B"y "C", podemos aplicar el patrón Builder usando genéricos de tal forma que reutilizemos al máximo los builders

public abstract class A{

    abstract static class Builder<T extends Builder<T>>{

        public Builder(){
        }

        public T prp1(int prp1){
            this.prp1 = prp1;
            return self();
        }

        abstract A build();

        protected abstract T self();
    }

    private A(Builder<?> builder){
        // copio los atributos de A
    }

}

public class B extends A{

    public static class Builder extends A.Builder<Builder>{

        public Builder(){
        }

        @Override public B build(){
            return new B(this)
        }

        public T prp2(int prp2){
            this.prp2 = prp2;
            return self();
        }

        @Override protected Builder self(){ return this;}
    }

    private B(Builder builder){
        // copio los atributos de B
    }
}


El "truco"se encuentra en el Generic de la clase A: Builder<T extends Builder<T> > así como en el método self . Este es usado internamente por el builder para permitir al compilador poder concatenar las llamadas
A a = new B.Builder().prp1(1).prp2(2).build

좋은 웹페이지 즐겨찾기