在类和其成员之间共享变量

5
如果您有一个包含状态变量的类,并且有两个成员类需要异步访问并操作该变量,那么最好的实现方式是什么?
一个例子:
 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
}

这些类是异步操作的。DeliveryMan和Supplier类都需要能够读写状态。DeliveryMan推送餐厅的状态,而Supplier监听其供应商的状态。

有没有更好的设计方式或者一种实现方法来最小化耦合,而不给DeliveryMan或Supplier一个对其所有者Restaurant的引用。


由于ResturantState被声明为私有,你如何期望其他类更新它? - user957902
谢谢,我已将访问修饰符更改为 internal。 - eddiehobbes
如果这些是您实际的状态,我建议将其制作为一个类,其中包含2个布尔值,就像我的(编辑后)答案中一样。 - Davy8
5个回答

2

我建议将状态作为构造函数参数传递给你的两个内部类,由于它是引用类型,因此可以进行修改。


你能详细说明一下你的答案吗?假设状态不断变化,配送员需要始终提供当前状态。 - eddiehobbes

1
如果RestaurantState是或可以成为一个持有状态而不是状态本身的对象,那么您可以像@Davide的答案一样将其传递给构造函数。
但是,如果它是像enum这样的值类型,那么我认为event是正确的方法。 DeliveryMan引发一个带有新状态的事件,Restaurant监听并更新其内部状态。
然后,Restaurant可以在状态更改时调用Supplier上的StateChanged方法或类似的内容。或者,Supplier可以引发一个带有特殊的RestaurantStateEventArgseventRestaurant可以监听并使用状态填充事件参数。
根据用例,仅仅拥有对Restaurant的引用可能并不可怕,尽管它会变得紧密耦合。

编辑:如果DeliveryManSupplier需要访问RestaurantState,那么它们已经与餐厅有些联系,因此,除非你拥有比RestaurantState更通用的“状态”类型,否则它们已经耦合了。

有时候退后一步来看:

a)解耦在特定场景下是否真的有帮助
b)你正在做的是否足够解耦以便有用。

在这种情况下,你仍然不能将DeliveryManSupplier重用于例如家具店等其他领域。

顺便说一句:

OPEN,
CLOSED,
LOW_ON_SUPPLIES

这些并不是枚举类型的最佳选择,因为它们并不完全互斥。如果将其定义为类可能会更好:

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

在这种情况下,@Davide的答案是将RestaurantState传递到DeliveryMan和Supplier的构造函数中,这个方法很有效。

谢谢,我会尝试改进这个例子。如果我将餐厅状态作为一个类,并通过构造函数传递它,那么读取butcherShop.parentState是否会反映出餐厅状态的任何和所有更改? - eddiehobbes
@eddiehobbes 如果你将RestaurantState作为一个持有实际状态信息的类,那么你就可以这么做:butcherShop.RestaurantState.RealState。如果只有一个属性,则有点笨重,但如果有多种类型的状态,例如“IsOpen”、“CurrentlyServing”(例如早餐、午餐、晚餐)等,它确实非常有效。 - Davy8
@eddiehobbes 我仍然会考虑在这种特定情况下解耦是否真的给你带来了任何好处。如果你不能将这些类与除了“餐厅”之外的任何东西一起使用,那么它们已经隐式地耦合在一起,不是通过代码,而是通过设计,例如RestaurantState对于除了餐厅之外的任何东西都没有意义。 - Davy8
在这种情况下,给每个对象一个对其父对象的引用是否有意义?或者使用事件/委托来获取访问权限的替代方案呢? - eddiehobbes
@eddiehobbes,我只会给出对父级的引用,除非有令人信服的理由不这样做。解耦的主要好处是您可以在其他场景中重用类,但是由于它们需要了解餐厅状态,因此您将无法获得该好处。因此,除非没有引用父级的另一个好处,或者如果传递对父级的引用变得麻烦(例如在更新引用时),否则我会选择最简单的解决方案,即引用父级。 - Davy8

1
也许你可以在 DeliveryManSupplier 类上创建事件,当状态需要更新时触发。餐厅可以订阅这些事件并在事件处理程序被调用时相应地更新自己的状态。

我考虑为成员类提供一个委托来获取/设置状态。感谢您的回答和思考。 - eddiehobbes

0
我会将餐厅类中的状态移除,并创建一个名为StateManager的类,作为其他类的单例或工厂。由于您的面向对象设计不够详细,很难给出更完整的答案。
var restaurant = new Restaurant();
var supplier = new Supplier();
StateManager.GetState(restaurant);
StateManager.GetState(supplier);

0
我会创建一个包含所需信息的Order类,并在另一个类中使用队列,您可以在计时器事件上检查它。当您出队一个订单时,请查看订单状态(例如)。将队列放在公共静态类中,具有Enqueue和Dequeue方法。
当DeliveryMan计时器事件触发时,出队订单。
您提到一切都是异步的,因此您可能需要查看ConcurrentQueue。由于供应商等待通知,因此您可以使用IObserver / IObservable向供应商发送流消息,其中包含序列化的Order对象...
这只是一些可能有所帮助的想法。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接