Patrón constructor en java

Enstringmiento de métodos: en java, el enstringmiento de métodos se usa para invocar múltiples métodos en el mismo objeto que ocurre como una sola declaración. El enstringmiento de métodos se implementa mediante una serie de métodos que devuelven la referencia this para una instancia de clase.

Implementación: como los valores devueltos de los métodos en una string son esta referencia, esta implementación nos permite invocar métodos en string al tener la siguiente invocación del método en el valor devuelto del método anterior en la string.

// Java code to demonstrate method chaining
final class Student {
  
    // instance fields
    private int id;
    private String name;
    private String address;
  
    // Setter Methods
    // Note that all setters method
    // return this reference
    public Student setId(int id)
    {
        this.id = id;
        return this;
    }
  
    public Student setName(String name)
    {
        this.name = name;
        return this;
    }
  
    public Student setAddress(String address)
    {
        this.address = address;
        return this;
    }
  
    @Override
    public String toString()
    {
        return "id = " + this.id + ", name = " + this.name + 
                               ", address = " + this.address;
    }
}
  
// Driver class
public class MethodChainingDemo {
    public static void main(String args[])
    {
        Student student1 = new Student();
        Student student2 = new Student();
  
        student1.setId(1).setName("Ram").setAddress("Noida");
        student2.setId(2).setName("Shyam").setAddress("Delhi");
  
        System.out.println(student1);
        System.out.println(student2);
    }
}

Producción:

id = 1, name = Ram, address = Noida
id = 2, name = Shyam, address = Delhi

Necesidad de patrón de generador: el enstringmiento de métodos es un patrón de diseño útil pero, sin embargo, si se accede al mismo tiempo , un subproceso puede observar que algunos campos contienen valores inconsistentes. Aunque todos los métodos de establecimiento en el ejemplo anterior son atómicos , las llamadas en el enstringmiento de métodos pueden conducir a un estado de objeto inconsistente cuando el objeto se modifica simultáneamente. El siguiente ejemplo puede llevarnos a una instancia de Estudiante en un estado inconsistente , por ejemplo, un estudiante con nombre Ram y dirección Delhi .

// Java code to demonstrate need of Builder Pattern
  
// Server Side Code
final class Student {
  
    // instance fields
    private int id;
    private String name;
    private String address;
  
    // Setter Methods
    // Note that all setters method
    // return this reference
    public Student setId(int id)
    {
        this.id = id;
        return this;
    }
  
    public Student setName(String name)
    {
        this.name = name;
        return this;
    }
  
    public Student setAddress(String address)
    {
        this.address = address;
        return this;
    }
  
    @Override
    public String toString()
    {
        return "id = " + this.id + ", name = " + this.name + 
                               ", address = " + this.address;
    }
}
  
// Client Side Code
class StudentReceiver {
  
    private final Student student = new Student();
  
    public StudentReceiver()
    {
  
        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run()
            {
                student.setId(1).setName("Ram").setAddress("Noida");
            }
        });
  
        Thread t2 = new Thread(new Runnable() {
            @Override
            public void run()
            {
                student.setId(2).setName("Shyam").setAddress("Delhi");
            }
        });
  
        t1.start();
        t2.start();
    }
  
    public Student getStudent()
    {
        return student;
    }
}
  
// Driver class
public class BuilderNeedDemo {
    public static void main(String args[])
    {
        StudentReceiver sr = new StudentReceiver();
        System.out.println(sr.getStudent());
    }
}

La salida puede ser:

id = 2, name = Shyam, address = Noida

Otra salida inconsistente puede ser

id = 0, name = null, address = null

Nota: intente ejecutar las declaraciones del método principal en bucle (es decir, varias requests al servidor simultáneamente).

Para resolver este problema, existe un patrón Builder para garantizar la seguridad de subprocesos y la atomicidad de la creación de objetos.

Implementación: en el patrón Builder, tenemos una clase estática interna llamada Builder dentro de nuestra clase Server con campos de instancia para esa clase y también tenemos un método de fábrica para devolver una nueva instancia de la clase Builder en cada invocación. Los métodos setter ahora devolverán la referencia de la clase Builder . También tendremos un método de compilación para devolver instancias de la clase del lado del servidor, es decir, la clase externa.

// Java code to demonstrate Builder Pattern
  
// Server Side Code
final class Student {
  
    // final instance fields
    private final int id;
    private final String name;
    private final String address;
  
    public Student(Builder builder)
    {
        this.id = builder.id;
        this.name = builder.name;
        this.address = builder.address;
    }
  
    // Static class Builder
    public static class Builder {
  
        /// instance fields
        private int id;
        private String name;
        private String address;
  
        public static Builder newInstance()
        {
            return new Builder();
        }
  
        private Builder() {}
  
        // Setter methods
        public Builder setId(int id)
        {
            this.id = id;
            return this;
        }
        public Builder setName(String name)
        {
            this.name = name;
            return this;
        }
        public Builder setAddress(String address)
        {
            this.address = address;
            return this;
        }
  
        // build method to deal with outer class
        // to return outer instance
        public Student build()
        {
            return new Student(this);
        }
    }
  
    @Override
    public String toString()
    {
        return "id = " + this.id + ", name = " + this.name + 
                               ", address = " + this.address;
    }
}
  
// Client Side Code
class StudentReceiver {
  
    // volatile student instance to ensure visibility
    // of shared reference to immutable objects
    private volatile Student student;
  
    public StudentReceiver()
    {
  
        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run()
            {
                student = Student.Builder.newInstance()
                              .setId(1)
                              .setName("Ram")
                              .setAddress("Noida")
                              .build();
            }
        });
  
        Thread t2 = new Thread(new Runnable() {
            @Override
            public void run()
            {
                student = Student.Builder.newInstance()
                              .setId(2)
                              .setName("Shyam")
                              .setAddress("Delhi")
                              .build();
            }
        });
  
        t1.start();
        t2.start();
    }
  
    public Student getStudent()
    {
        return student;
    }
}
  
// Driver class
public class BuilderDemo {
    public static void main(String args[])
    {
        StudentReceiver sr = new StudentReceiver();
        System.out.println(sr.getStudent());
    }
}

Se garantiza que la salida será una de las siguientes:

id = 1, name = Ram, address = Noida

O

id = 2, name = Shyam, address = Delhi

El método de fábrica Builder.newInstance() también se puede llamar con los argumentos necesarios para obtener una instancia de Builder sobrecargándola. El objeto de la clase Student se construye con la invocación del método build() .
La implementación anterior del patrón Builder hace que la clase Student sea inmutable y, en consecuencia , segura para subprocesos .

También tenga en cuenta que el campo de estudiante en el código del lado del cliente no se puede declarar final porque se le asigna un nuevo objeto inmutable. Pero debe declararse volátil para garantizar la visibilidad de la referencia compartida a objetos inmutables. También los miembros privados de la clase Builder mantienen la encapsulación.

Eche un vistazo al método de adición de la clase StringBuilder en el paquete java.lang para comprender mejor las implementaciones del patrón Builder.

Publicación traducida automáticamente

Artículo escrito por gaurav miglani y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *