关于不可知的语言:OO设计,开放/封闭原则问题

关于不可知的语言:OO设计,开放/封闭原则问题

OO Design, open/closed principle question

我已经思考了这个面向对象的设计问题已有一段时间了,并且无法提出令人满意的解决方案,因此我想将其向此处的人群开放以征求一些意见。

我有一个Game类,它代表一个基于回合的棋盘游戏,对于这个问题,我们可以假定它类似于Monopoly。
在我的设计中,我有一个Player类,其中包含方法TakeTurn。

游戏遍历所有玩家,并调用TakeTurn方法执行所有必要的操作以完成转弯。
我希望能够有n个播放器,并能够将任意数量的播放器设置为计算机播放器。
因此,我的想法是要拥有一个HumanPlayer类和一个ComputerPlayer类,这两个类都从Player派生而来。

游戏仅知道Player类,并且仅依次依次对每个Player调用TakeTurn方法。
我的问题在于,ComputerPlayer对象可以完全自动化,即与Monopoly示例保持一致,可以使用某种逻辑来决定购买物业。
现在,使用HumanPlayer对象,它需要从实际用户那里获得输入,以便能够购买物业,这似乎暗示着一个不同的界面,并可能意味着他们不应衍生出

在没有让Game类明确知道各种Player类的实际实现的情况下,我无法提出一个很好的解决方案。
我总是可以在Game类中做出这样的假设:只会有人类和计算机玩家,并有效地将其关闭以进行扩展,但这似乎不是一个好的OO编程。

任何意见,将不胜感激。


我认为您不应该让Game类处理IO。
这样,(阻塞)TakeTurn方法将从游戏板上隐藏实现的手段。它可以使用其他对象与用户通信。

游戏类应该关心的只是棋盘的状态和转弯。所有玩家都应实现一个Player界面,并从游戏中隐藏所有实现。


我可能没有两个HumanPlayerComputerPlayer类,但是只有一个Player类,该类在创建时使用正确的输入策略进行了配置。

玩家获取信息以决定其在下一轮游戏中的动作的方式是唯一变化的(至少与原始问题描述不同),因此只需将其封装在单独的抽象中即可。

无论设置游戏的任何高级班级,都应该创建两组玩家(一个人,另一台计算机模拟的),并为每个玩家提供适当的输入策略,然后将这些玩家对象简单地赋予游戏对象。然后,对于每个新回合,Game类将仅在给定的玩家列表上调用TakeTurn方法。


如果游戏正在管理游戏状态并进行I / O,则游戏做得太多。

您希望Game严格专注于规则和转弯以及状态更改。
游戏不知道玩家是什么。它只知道它有玩家。

您希望玩家检查游戏状态并在回合期间执行法律诉讼。

人类玩家和整个游戏都共享一个通用的I / O程序包,该程序包可显示游戏状态并提示人类输入。

通过将I / O包作为游戏的Observer,可以充分利用Java Observable。这样,游戏状态更改会报告给I / O进行显示或记录,或同时显示和记录两者。


Player提供给Game的接口与派生的Player类的行为正交。

TakeTurn的实现根据Player对象的具体类型而变化的事实不应引起关注。


与其告诉游戏类只有一个人,为什么不让它在游戏的菜单/初始化过程中得到输入呢?如果还有更多玩家,可以在游戏类初始化之前通过某种形式的输入(在菜单中选择玩家)来


代替游戏类在所有玩家上调用TakeTurn,玩家应在游戏类上调用TakeTurn,并且游戏类应验证是否合适的玩家轮到他。

这应该有助于解决用户和计算机播放器问题。


我会说,Game类应该不在乎这是计算机玩家还是人类玩家。它应该始终在下一个玩家类上调用TakeTurn。如果这是人类玩家,则Player类的职责是与用户交流并询问用户该怎么做。这意味着它将一直阻塞直到用户下定决心。由于通常UI交互是在应用程序的主线程中发生的,因此仅重要的一点是,阻塞的TakeTurn不会阻塞整个应用程序,否则在Game等待TakeTurn时无法处理用户输入。


我不确定这是否是您想要的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
public abstract class Player
{
  int position;
  DecisionMaker decisionDependency;

  ...

  public void TakeTurn()
  {
    position += RollDice();
    GameOption option GetOptions(position);
    MakeDescion(option);
  }

  protected int RollDice()
  {
    //do something to get the movement
  }

  protected abstract void MakeDecision(GameOption option);

}

Public class ComputerPlayer : Player
{
  public ComputerPlayer()
  {
    decisionDependency = new AIDecisionMaker();
  }

  protected override void void MakeDecision(GameOption option)
  {
    decisionDependency.MakeDecision(option);
    //do stuff, probably delgate toan AI based dependency
  }
}

Public class HumanPlayer : Player
{
  public HumanPlayer()
  {
    decisionDependency = new UIDecisionMaker();
  }

  protected override void void MakeDecision(GameOption option)
  {
    decisionDependency.MakeDecision(option);
    //do stuff, probably interacting with the a UI or delgate to a dependency
  }
}

我认为Game类不应该关注Player类的任何实现,也应该忽略用户界面。

任何用户输入都需要由HumanPlayer类处理。


推荐阅读

    计算机蓝屏故障的计算机蓝屏解决方案

    计算机蓝屏故障的计算机蓝屏解决方案,,电脑蓝屏电脑故障经常使用电脑的朋友经常遇到,因为电脑蓝屏是一个非常普遍的现象,所以很难预测,什么时

    无法打开网络正常网页的解决方案

    无法打开网络正常网页的解决方案,,昨天我在一家电脑公司做了一个奇怪的现象,在网络的开始都是正常的,QQ是正常的,但不久之后,我发现无法打开网

    MacChrome打开HTTPS证书错误解决方案

    MacChrome打开HTTPS证书错误解决方案,,评论:在Chrome浏览器下,总是建议站点的安全证书不可信。有一个很好的解决方案,你可以试试看。 GoAge

    三常见BIOS故障排除解决方案

    三常见BIOS故障排除解决方案,,笔记本电脑如何长时间出现黑屏为什么为什么如何删除和修改旧IBM笔记本电脑BIOS设置中的密码我想你会与这些

    探探语言设置|探探怎么设置语言

    探探语言设置|探探怎么设置语言,,1. 探探怎么设置语言打开探探软件,然后就有消息提示的红点,点开就行了!其实这些软件都是挺简单的操作的,都是

    git设置编码|git语言设置

    git设置编码|git语言设置,,git设置编码点击cap4j搜索从git直接链接上拉代码。git语言设置Git是一个开源的分布式版本控制系统,可以有效、高

    对计算机无反应的解决方案

    对计算机无反应的解决方案,,(1)从计算机中取出计算机最常用的方法 电脑对开机没有反应。最常见的是:主计算机电源线没有连接,监视器开关未打