Diseño de objeto "Solicitud de asignación variable"

Tengo varias clases que no pueden modificar los campos de los demás, sino que deben solicitar la modificación agregando un objeto de solicitud a la cola de la clase Principal. La clase Main, al final de cada ciclo, realizará las modificaciones solicitadas.

public class Main {

    public static ClassA a = new ClassA();
    public static ClassB b = new ClassB();

    private static List<Request> requestQueue = new ArrayList<Request>(); // List holds all requests

    public static void main(String args[]) {
        while (true) {
            a.tick();
            b.tick();
            for (Request r : requestQueue) {
                r.field = r.value; // All requests are fulfilled 
            }
            requestQueue.clear();
        }
    }

    public static <ValueType> void addModificationRequest(ValueType field,
            ValueType value) {
        requestQueue.add(new Request<ValueType>(field, value));
    }
}

// Request Object
public class Request<ValueType> {

    ValueType field;
    ValueType value;

    public Request(ValueType field, ValueType value) {
        this.field = field;
        this.value = value;
    }
}

// Classes
public class ClassA {
    String name = "A";

    public void tick() {
        Main.addModificationRequest(Main.b.name, "NewNameB"); // Try to change b name
    }
}

public class ClassB {
    String name = "B";

    public void tick() {
        // Nothing
    }
}

Sé que el código es desordenado, pero es la forma más simple que he pensado hasta ahora. ¿Alguien conoce algún buen patrón de diseño que pueda lograr esto de una manera más simple y robusta? (Nota: debo tenerlo de esta manera, no hay posibilidad de permitir que las clases se modifiquen directamente entre sí).

Editar: Las clases tendrán más de una variable modificable. También necesito determinar si alguna solicitud intenta modificar la misma variable, para poder ignorar una o ambas.

Editar: Gracias por toda la ayuda, ¡realmente lo aprecio! He decidido dejar que las clases hagan un seguimiento de sus propias modificaciones. También voy a usar el mismo objeto Request que he estado usando porque es simple y directo. Una vez más, gracias.

Respuesta 1

Tal vez esto no se aplique a su caso de uso, pero podría hacer que los objetos mismos realicen un seguimiento de las modificaciones pendientes, y luego hacer una llamada, hecha desde su clase principal, que modifica los campos reales.

Si solo necesita la operación de configuración, realizar un seguimiento de las modificaciones es tan fácil como mantener un campo adicional para cada campo de la clase. Si necesita una serie de, por ejemplo, operaciones aritméticas, puede usar una lista de modificaciones.

public class DelayedModificationField<T> {
    private T field;
    private T newValue;
    public T get() { return field;}
    public delayedSet(T value) {
        if (newValue != null) throw new ConcurrentModificationException("error");
        newValue = value;
    }
    public void performSet() {
        field = newValue;
        newValue = null;
    }

public ExampleClass {
    private DelayedModificationField<String> myField = new DelayedModificationField<String>();
    public void setMyField(String s) { myField.delayedSet(s);}
    public String getMyField() { return myField.get();}
    public void performSet() { myField.performSet();}
}

Su clase principal debe realizar un seguimiento de todos los objetos que admiten modificaciones retrasadas y llamar a performSet en cada tic. Haz que implementen una interfaz y mantenlos en una lista.

Respuesta: 2

Esto no va a funcionar. No conozco los parámetros exactos de su asignación, pero definiría una interfaz Modifiablecon un único método void setField(ValueType newValue). Entonces declararía ClassAy ClassBpara implementar Modifiable. Finalmente, redefina su Requestclase para que sea ay Modifiableen ValueTypelugar de dos ValueTypecampos. Su ciclo de cola sería:

for (Request r : requestQueue) {
    r.modifiable.setField(r.value);
}

EDITAR:

Aquí hay una modificación de este enfoque que es extensible a múltiples campos:

interface Modifiable {
    void setName(String newName);
    void setAge(Integer newAge); // I wish
}

abstract class Request<ValueType> {
    Modifiable object;
    ValueType value;

    public Request(Modifiable object, ValueType value) {
        this.object = object;
        this.value = value;
    }

    abstract void execute();
}

class RequestNameChange extends Request<String> {
    public RequestNameChange(Modifiable object, String name) {
        super(object, name);
    }

    void execute() {
        object.setName(name);
    }
}

// etc.

Otro enfoque sería utilizar la reflexión, pero sospecho que de eso no se trata su tarea.

Respuesta: 3

Digamos que tengo dos Listas (o Vectores), quiero que uno incluya todos los elementos del otro, incluso si el segundo puede obtener más elementos más tarde, deben agregarse al primero automáticamente. Por ...

clase Y {public static void main (String [] args) lanza RuntimeException {// Línea 1 try {doSomething (); } catch (RuntimeException e) {System.out ....

Estoy tratando de crear una lista de pares clave-valor. Esto es lo que tengo hasta ahora: Map <Integer, String> map = new HashMap <Integer, String> (). Put (songID, songList.get (i) .name); Esto me da el ...

Me encanta el control de acceso en cualquier lenguaje, pero encuentro que en Java casi nunca (si es que alguna vez) uso el modificador de acceso de paquete privado (o la falta del mismo). Me doy cuenta de que las clases internas pueden ser privadas, ...