2011-10-10 9 views
5

Si tiene una clase que contiene una variable de estado y dos clases miembro que necesitan acceso y funcionan de forma asíncrona. ¿Cuál es la mejor manera de implementar esto?Compartir una variable entre una clase y su miembro

Un ejemplo

public enum RestaurantState 
{ 
    BREAKFAST, 
    LUNCH, 
    DINNER 
} 

public class Restaurant 
{ 
    //Below need access to state 
    private DeliveryMan pizzaDriver ; 
    private Supplier butcherShop ; 

    internal RestaurantState state ; 
} 

public DeliveryMan 
{ 
    //Uses a System.Timers.Timer 
    //Wakes up and does work every a minute 
    //Needs to inform state of restaurant 
} 

public Supplier 
{ 
    //Waits and listens for requests to accept deliveries 
    //If suppliers run out we need to change the restaurant state based on our own current state 
} 

Estas clases operan de forma asíncrona. Ambas clases, DeliveryMan y Supplier, necesitan poder leer/escribir el estado. DeliveryMan resalta el estado del restaurante y el Proveedor escucha el estado de su proveedor.

Existe una mejor manera de diseñar esto o una forma de implementarlo con un acoplamiento mínimo sin dar a DeliveryMan o Proveedor una referencia a su propietario Restaurant.

+0

ya que ResturantState se declara como privado ¿cómo espera que otras clases lo actualicen? – user957902

+0

Gracias, he cambiado el modificador de acceso a – eddiehobbes

+0

interno. Si esos son sus estados reales, recomendaría hacer una clase con 2 bools como en mi respuesta (editada). – Davy8

Respuesta

1

Quizás pueda crear eventos en las clases DeliveryMan y Supplier que se activan cuando el estado necesita actualizarse. El Restaurante puede suscribirse a estos eventos y actualizar su propio estado en consecuencia cuando se invocan los controladores de eventos.

+0

Pensé en dar a las clases miembro un delegado para obtener/establecer el estado. Aprecio tu respuesta y pienso en ello. – eddiehobbes

2

Bueno, pasaría el estado como parámetro constructor a sus dos clases internas y, dado que es un tipo de referencia, también se puede modificar.

+0

¿Podría explicar su respuesta? Digamos que el estado cambia continuamente y deliveryMan necesita dar siempre el estado actual – eddiehobbes

0

Quitaría el estado de la clase de restaurante y haría una clase StateManager que fuera un singleton o una fábrica para el resto de las otras clases. Es difícil dar una respuesta más completa ya que su diseño OO no da mucho para seguir.

var restaurant = new Restaurant(); 
var supplier = new Supplier(); 
StateManager.GetState(restaurant); 
StateManager.GetState(supplier); 
0

me gustaría crear una clase Order que contiene la información que necesita en otra clase. También use una Cola que verifique en un evento Timer. Cuando dequeue un pedido, mire Order.State (por ejemplo). Ponga la cola en una clase pública estática con los métodos Enqueue y Dequeue.

Cuando se dispara el evento del temporizador DeliveryMan, dequeue el pedido.

Menciona que todo es asíncrono, por lo que puede consultar ConcurrentQueue. Dado que el Proveedor espera la notificación, puede usar IObserver/IObservable para enviar un mensaje continuo al Proveedor con un objeto de pedido serializado ...

Solo algunas ideas que pueden ayudar.

1

Si RestaurantState es o puede convertirse en un objeto que contiene el estado en lugar del estado en sí, entonces puede hacer como respuesta de @Davide y pasarlo al constructor.

Sin embargo, si se trata de un tipo de valor como enum entonces creo que event s son el camino a seguir.

DeliveryMan provoca un evento con el nuevo estado, que Restaurant escucha y actualiza su estado interno.

Restaurant puede llamar a un método StateChanged o algo similar en Supplier cuando el estado cambia. O Supplier puede generar un event con un RestaurantStateEventArgs especial o algo que el Restaurant puede escuchar y rellenar los argumentos del evento con el estado.

Dependiendo del caso de uso, no es terrible tener una referencia a Restaurant a pesar de que se acopla fuertemente.

Editar: En realidad, si DeliveryMan y Supplier necesitan tener acceso a RestaurantState entonces son ya algo atados a restaurantes, por lo menos que tenga un tipo más genérico de "estado" que RestaurantState que ya están acoplados.

A veces es bueno dar un paso atrás y ver si

a) desacoplamiento es realmente útil en un escenario particular y
b) si lo que está haciendo en realidad es desacoplado suficiente como para ser útil.

En este escenario, todavía no podría volver a usar DeliveryMan y Supplier para decir una tienda de muebles.

Como comentario:

OPEN, 
CLOSED, 
LOW_ON_SUPPLIES 

Estos no son realmente las mejores opciones para una enumeración, ya que no todos son mutuamente excluyentes. puede ser mejor si se tratara de una clase para:

public class RestaurantState 
{ 
    public bool IsOpen { get; set; } 
    public bool IsLowOnSupplies { get; set; } 
} 

En ese caso, la respuesta de @ Davide para pasar RestaurantState en el constructor de DeliveryMan y Supplier funciona bien.

+0

Gracias, intentaré mejorar el ejemplo. Si hago de Restaurant State una clase y la paso por el constructor, ¿leerá butcherShop.parentState reflejando todos y cada uno de los cambios en restaurant.state? – eddiehobbes

+0

@eddiehobbes si haces de RestaurantState una clase que contiene la información de estado real, entonces puedes, pero tendrás que hacer algo como 'butcherShop.RestaurantState.RealState'. Es un poco torpe si hay una sola propiedad, pero funciona bien si tiene múltiples tipos de estado, como 'IsOpen'' CurrentlyServing' (por ejemplo, Breakfast, Lunch, Dinner), etc. – Davy8

+0

@eddiehobbes Todavía consideraría si el desacoplamiento en este escenario particular en realidad le da algún beneficio. Si no puede usar las clases con otra cosa que no sea 'Restaurante ', entonces ya están implícitamente acopladas, no a través del código, sino solo por diseño, p. RestaurantState no tiene sentido para otra cosa que no sea Restaurantes. – Davy8

Cuestiones relacionadas