想象一下,我有一个很好的 Deck 类,以最好的 OO 方式。它有卡片,有花色和等级,有洗牌方法,等等。现在,我将有很多并发的 Deck 实例(假设这是一个赌场)。问题是:所有牌组中的每张牌都应该有不同的实例吗?
4 回答
卡片对象可能最好实现为不可变对象。为了创建一张卡片,你必须传入一个花色和一个等级,这个花色和等级以后永远不会改变。
从这个角度来看,由于这些对象不会改变,并且因为有一个设定的数字开始,所以实现一个包含所有 52 个可能的 Card 对象的单个静态集合并从其他类访问这些卡片是有意义的(使Card private 上的构造函数,因此不可能在 Card 类之外创建卡片)。
这里真正的区别是 Card 本身不执行任何操作,其他操作将作用于卡片,因此制作单个卡片实例应该没问题。
它被正式称为享元模式,最早出现在 GOF 的“设计模式”中。在您的情况下应该非常有用。由于卡片永远不会改变,您甚至可以考虑将它们实现为枚举。
这取决于您将如何使用这些卡。不过,可能来自额外 Card 实例的任何额外内存使用都是微不足道的——毕竟,每张卡只存储两个字节的数据。
你问:“所有牌组中的每张牌都应该有不同的实例吗?” 答案是否定的:您可以使用每张卡片的单个实例并在所有卡片组中共享它,即使它们在不同的线程上运行。原因是卡片是不可变的,所以即使两个线程在同一张卡片上调用 card.getSuit(),它们的计算也不会干扰。
当然,这只有在您将卡片类编写为真正不可变的情况下才是正确的。一旦您写入卡的某些局部变量,您就会将自己暴露在数据竞争中。但我想不出这样做的理由,所以你应该是安全的。