【问题标题】:Too many subclasses while making equipment for character (Role Playing Game)为角色制作装备时子类过多(角色扮演游戏)
【发布时间】:2017-02-20 19:38:00
【问题描述】:

我正在构建一个小型 RPG。一个角色有多种属性,例如:力量、魔法、射箭和防御。玩家也可以穿戴装备,例如头盔、躯干、腿、靴子、手套和武器。每件装备都有自己的统计数据。例如,银色躯干有 10 点防御。

当角色拥有 15 点防御力并且他穿着银色躯干时,他的防御力现在将是 25 点。无论如何,为了穿戴装备,需要生产。目前我用抽象工厂模式设计了它(见图)。

该设计有很多类,其中大多数基本没用,例如青铜头盔、银色躯干等等,因为它们只有一个实例类统计。

因此,我的问题是:生产设备的最佳方式是什么,少的类更有用。由于它是针对学校项目的,因此我最好使用设计模式。

【问题讨论】:

  • 专业类代表特定类型的设备有什么意义?我希望 all 实例例如boots 由单个类 Boots 表示。
  • 你为什么要使用工厂?当我穿西装时,它只是一套西装。
  • 如果要使用特定的type 字符串调用工厂,为什么还要使用工厂?抽象工厂的整个想法是,您实际上并不知道您正在创建的内容的类型或实现。

标签: java oop design-patterns uml abstract-factory


【解决方案1】:

该设计有很多类,其中大部分基本没用,如青铜头盔、银色躯干等,因为它们只有一个 Stats 类的实例。

您似乎无缘无故地爆炸您的设计。整个层次结构可以只用一个名为Equipment 的类来替换。

public class Equipment {
    private Stats stats;
    private String equiptmentName;

    //constructors and getters and setters follow..
}

您的Player 类可以有Set 或Equipment,如下所示。每当安装或卸载设备时,您可以使用来自Equipment 的stats 更新Player 统计信息。

public class Player {
    private Set<Equipment> mountedEquipment;
    private Stats baseStats;

    public Player(Stats baseStats) {
       this.baseStats = baseStats;//set base stats for player
       mountedEquipment = new HashSet<Equipment>();
    }

    public void mountEquipment(Equipment equipment) { 
          baseStats.setMagic(baseStats.getMagic()+equipment.getStats().getMagic());

         //update base stats similarly for strength, hitpoints, etc
         mountedEquipment.add(equipment);

    }

    public void unmountEquipment(Equipment equipment) {

       baseStats.setMagic(baseStats.getMagic()-equipment.getStats().getMagic());
       //update base stats in a similar fashion for strength, hitpoints, etc
       mountedEquipment.remove(equipment);
    }

    public Set<Equipment> getMountedEquiptment() {
        return Collections.unmodifiableSet(mountedEquiptment);
    }

}

您实际上并不需要您在问题中显示的任何 Factory 类,因为您可以在引入新的Equipment 类型。

【讨论】:

    【解决方案2】:

    在商业视频游戏中,许多具有不同属性和可能特殊效果的项目通常通过脚本系统实现。很难让它更具体,因为诸如脚本绑定和基于组件的架构之类的东西没有严格定义,并且因游戏而异。

    您可以通过查看用于 RPG 的(项目更改)模组的工作原理,对这些系统的内部运作有一个很好的了解。例如,看看 Skyrim 的“Papyrus”绑定,或者更简单的例子看看 The Binding of Isaac: Rebirth 的 lua 绑定。

    【讨论】:

      【解决方案3】:

      我会这样处理:

      拥有一个所有头盔、躯干等都继承自的抽象类 Armor。然后你可以有一个单一的 Silver 和 Bronze 类,可能也统一在一个 ArmorType 类下。我会根据它是哪种设备来进行某种修饰符,即 Bronze::modifier = 1.25;、Silver::modifier = 1.5; 等。这样,对于您拥有的每个新 ArmorType 或 Armor,您不需要不必添加大量新课程。随着游戏的扩展,这种情况只会变得更糟。

      当在 Armor 子类中完成实际统计计算时,它会这样:

      //这是你的盔甲类。

          class Torso extends Armor {
      
              public Torso(ArmorType armorType) {
                  this.armorType = armorType;
                  this.baseStat = 10;
              }
      
              public double calculateStats() {
                   return this.getBaseStat() * armorType.getModifier();
              }
          }
      

      现在举个例子。如果躯干的基础属性是 10 护甲,白银有 1.5 的修正值,那么这件护甲的最终防御就是 15。当然,您可以根据自己的喜好调整这些数字或在计算中添加更多方面。这只是您可以做的事情的一个简单示例。

      如果您想保留原始设计中的 Stats 部分,我会将 Stats 对象放在 Armor 类中。因此,您正在有效地使用装饰器模式来使用 ArmorTypes 来装饰您的 Armor 类。您也只是在 Stats 类和 Armor 子类之间添加了一层。

      让我知道你的想法。

      【讨论】:

        猜你喜欢
        • 2021-05-17
        • 2011-01-08
        • 2020-01-25
        • 1970-01-01
        • 1970-01-01
        • 2017-06-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多