【发布时间】:2019-05-04 08:52:54
【问题描述】:
作为一个新手,我正在开发一款游戏,但对创建复杂对象的更好方法感到困惑。此问题可能与 OOP、设计模式和 SOLID 原理有关。对于这些问题,编程语言限制很少。
情况很清楚:
- 一艘战舰由一个机身和几个炮塔组成。
- 一个炮塔由一个盾牌和几个枪管组成。
背景
我正在使用 Pixi.js 和 TypeScript 开发基于浏览器的 2D 游戏。以下类继承自 Pixi.js 的原生类 Sprite 或 Container,但为了清楚起见,我在下面的代码中省略了这些扩展子句。
代码
我可以简单地想出下面的 Barrel、Shield 和 Body 的代码:(在 TypeScript 中,但与 Java 和 C# 几乎没有区别,不是吗?)
class Barrel {
constructor(texture, x, y, rotation){
/*...*/
}
}
class Shield {
constructor(texture, x, y, rotation){
/*...*/
}
}
class Body {
constructor(texture, x, y, rotation){
/*...*/
}
}
问题来了,炮塔和战舰呢?
粗略地说,1 个炮塔 = 1 个盾牌 + N 个炮管,1 艘战舰 = 1 个车身 + N 个炮塔。
不用再细想,下面的代码就可以轻松搞定:
class Turret {
private shield: Shield
private barrels: Barrel[]
constructor(x, y, rotation, shieldCfg, barrelCfgList) {
/*...*/
this.shield = new Shield(shieldCfg.texture, shieldCfg.x, shieldCfg.y, shieldCfg.rotation)
for(let cfg of barrelCfgList){
const barrel = new Barrel(cfg.texture, cfg.x, cfg.y, cfg.rotation)
this.barrels.push(barrel)
}
}
}
class Warship {
private body: Body
private turrets: Turret[]
constructor(x, y, rotation, bodyCfg, turretCfgList) {
/*...*/
this.body = new Body(bodyCfg.texture, bodyCfg.x, bodyCfg.y, bodyCfg.rotation)
for(let cfg of turretCfgList){
const turret = new Turret(cfg.x, cfg.y, cfg.rotation, cfg.shieldCfg, cfg.barrelCfgList)
this.turrets.push(turret)
}
}
}
不难想象 turretCfgList 有多么复杂。
const turretCfgList = [
{
x: 1,
y: 2,
rotation: 3.14,
shieldCfg: {
texture: 'gun-shield'
x: 4,
y: 5,
rotation: 6.28
},
barrelCfgList: [
{
texture: 'gun-barrel'
x: 7,
y: 8,
rotation: 9.42
},
/*...*/
]
},
/*...*/
]
我的问题是:
- 如何解决上面嵌套对象的复杂参数?
- 上面的原始代码与工厂方法模式、构建器模式等更好的解决方案有哪些改进?
非常感谢。
我不太确定是否使用下面的代码。仅供参考。
- 传递一个复杂的配置对象而不是复杂的参数。
class Turret {
// constructor(texture, x, y, rotation, shieldCfg, barrelCfgList) {}
constructor(cfg) {
/*...*/
this.shield = new Shield(cfg.shieldCfg.texture, cfg.shieldCfg.x, shieldCfg.y, cfg.shieldCfg.rotation)
for(let barrelCfg of barrelCfgList){
const barrel = new Barrel(cfg.barrelCfg.texture, cfg.barrelCfg.x, cfg.barrelCfg.y, cfg.barrelCfg.rotation)
this.barrels.push(barrel)
}
}
}
- 在其他地方创建组件实例,并传递这些实例而不是参数
class Turret {
// constructor(texture, x, y, rotation, shieldCfg, barrelCfgList) {}
constructor(x, y, rotation, shield, barrels) {
/*...*/
this.shield = shield
this.barrels = barrels
}
}
- 工厂方法模式?
- 建造者模式?
-
??
- 更新1,添加一些关于背景的说明。
【问题讨论】:
-
如果我理解正确,您将使用 TypeScript。但是您将如何进一步使用您的对象?此代码将在浏览器或服务器上运行吗?如果您要使用代码呈现 UI 或开发后端?如果是后端,你将如何与前端通信?等等。所以请描述您的解决方案的架构。
-
@Fyodor 你是对的。我想使用 TypeScript。谢谢你的建议,我会完成你提到的问题的背景。
-
谢谢。问题变得更清楚了。您的游戏会是多人游戏并会与某些后端通信吗?
-
@Fyodor 目前我没有这样的计划(因为我可能无法处理)。所以这个游戏一开始只是一个单人游戏。实现这一点后,我将尝试实现您介绍的功能。
标签: java c# typescript oop