Tengo un class Carque tiene 2 propiedades: int pricey boolean inStock. También contiene un Listde abstract class State(clase vacía). Hay 2 estados que se pueden aplicar en el automóvil y cada uno está representado por su propia clase: class Upgrade extends Statey class Shipping extends State.
A Carpuede contener cualquier número de cada uno de los 2 estados. Los estados tienen las siguientes reglas:
- Upgrade: se suma- 1al precio de cada estado aplicado al automóvil después de sí mismo.
- Shipping: si hay al menos 1- Shippingestado en la lista,- inStockse establece en- false.
Por ejemplo, comenzando con price = 1y inStock = true:
add Shipping s1    --> price: 1, inStock: false
add Upgrade g1     --> price: 1, inStock: false
add Shipping s2    --> price: 2, inStock: false
add Shipping s3    --> price: 3, inStock: false
remove Shipping s2 --> price: 2, inStock: false
remove Upgrade g1  --> price: 1, inStock: false
remove Shipping s1 --> price: 1, inStock: false
remove Shipping s3 --> price: 1, inStock: trueEstaba pensando en el patrón de observador donde cada operación de agregar y quitar notifica a los observadores. Tenía algo como esto en mente, pero no obedece las reglas que planteé:
abstract class State implements Observer {
    public abstract void update();
}
class Car extends Observable {
    List<State> states = new ArrayList<>();
    int price = 100;
    boolean inStock = true;
    void addState(State state) {
        if (states.add(state)) {
            addObserver(state);
            setChanged();
            notifyObservers();
        }
    }
    void removeState(State state) {
        if (states.remove(state)) {
            deleteObserver(state);
            setChanged();
            notifyObservers();
        }
    }
}
class Upgrade extends State {
    @Override
    public void update(Observable o, Object arg) {
        Car c = (Car) o;
        int bonus = c.states.size() - c.states.indexOf(this) - 1;
        c.price += bonus;
        System.out.println(c.inStock + " " + c.price);
    }
}
class Shipping extends State {
    @Override
    public void update(Observable o, Object arg) {
        Car c = (Car) o;
        c.inStock = false;
        System.out.println(c.inStock + " " + c.price);
    }
}Obviamente, esto no funciona. Cuando Shippingse elimina a, algo tiene que verificar si hay otra configuración de estado inStocken falso, por lo que la eliminación de Shippingno puede simplemente inStock = true. Upgradeaumenta priceen cada llamada. Luego agregué constantes para los valores predeterminados e intenté un recálculo basado en esos.
De ninguna manera estoy tratando de imponer ningún patrón, solo estoy tratando de encontrar una solución para los requisitos anteriores. Tenga en cuenta que en la práctica Carcontiene muchas propiedades y hay muchos estados que se pueden aplicar de esta manera. Pensé en algunas maneras de hacer esto:
- Como cada observador recibe Car, puede observar a todos los otros observadores actualmente registrados y hacer un cambio basado en eso. No sé si es inteligente enredar a observadores como este.
- Cuando se agrega o elimina un observador Car, habrá un nuevo cálculo. Sin embargo, este recálculo deberá realizarse en todos los observadores, independientemente del que se acaba de agregar / eliminar.
- Tenga una clase de "administrador" externa que llamará a los métodos de agregar y quitar y hará el recálculo.
¿Cuál es un buen patrón de diseño para implementar el comportamiento descrito y cómo funcionaría?
fuente

Respuestas:
Los observadores funcionarían muy bien si factorizaras el sistema de manera diferente. En lugar de hacer que los estados sean observadores, puede hacer que 2 nuevas clases sean "observadores de cambio de estado": un observador actualizará "precio", otro actualizará "inStock". De esta manera, serían independientes si no tiene reglas de precio que dependan de inStock o viceversa, es decir, si todo pudiera calcularse simplemente mirando los cambios de estado. Esta técnica se denomina "abastecimiento de eventos" (por ejemplo, consulte - https://ookami86.github.io/event-sourcing-in-practice/ ). Es un patrón en la programación que tiene algunas aplicaciones notables.
Respondiendo a una pregunta más general, a veces realmente tienes dependencias entre los observadores. Por ejemplo, es posible que desee que un observador reaccione antes que otro. En tal caso, generalmente es posible hacer una implementación personalizada de la clase Observable para tratar con pedidos o dependencias.
fuente
Terminé con la opción 3: usar un administrador externo. El gerente es responsable de agregar y eliminar
States deCars y de notificar a los observadores cuando ocurren estos cambios.Así es como modifiqué el código. Eliminé el
Observable/Observerdel JDK porque estoy haciendo mi propia implementación.Cada uno
Statemantiene una referencia aCarsu aplicada.Carsolo mantiene su estado (para evitar confusiones: propiedades) y no maneja agregar y eliminarStates:Aquí está el gerente. Ha superado
Carel trabajo de s (el observable) de administrar susStates (observadores).Un par de cosas a tener en cuenta:
updatemétodo de los observadores .updatemétodo actual enupdateOnAddyupdateOnRemovesi están interesados solo en uno de estos cambios. Luego, los métodosaddStateyremoveStatese actualizarían en consecuencia. Junto con el punto anterior, este enfoque puede terminar como un mecanismo robusto, extensible y flexible.Statesy cuándo sucede eso, ya que no es importante para la pregunta. Sin embargo, en el caso de esta respuesta, hay que considerar el siguiente punto. ComoStateahora debe crearse con suCar(sin un constructor vacío expuesto) antes de llamar al método del administrador, los métodosaddStateyremoveStateno necesitan tomar unCary solo pueden leerlostate.car.fuente