我正在处理一个设计问题,我不希望因为糟糕的解决方案而使我的代码变得混乱。与其给出一个差劲的类比,我宁愿解释我的确切情况。
我正在尝试编写Wii Play Tanks的克隆版,并且我在设计Tank类时遇到了麻烦。 Tank本身是唯一的这样一个类,它使用依赖注入来管理其部分。目前有两个部分:TankAI和TankWeapon。 AI负责决策运动和开火,武器描述武器行为-它发射什么弹药以及多久发射一次等。 我有一个工厂类,可以构建不同组合的坦克。
我的弹丸类设置在抽象Projectile类下。每个子类都描述了弹丸的模型,反弹次数,速度等。
我的问题是,每个TankWeapon子类都在构造新弹丸的区域周围重复了很多代码,因为它们各自构造了不同的类。我想将此代码移动到基类中,但我必须以某种方式注入武器需要构造的弹丸类本身。我知道我可以在构造时直接传递类,但那似乎不是正确的方法。
另外,我还有另一个设计问题:如何使我的AI类也了解弹丸类?他们的决策将取决于正在发射的弹药的属性,例如它们可以在墙上反弹多少次。 AI和Weapon类都在注入时给予对父级Tank的引用。
我正在尝试编写Wii Play Tanks的克隆版,并且我在设计Tank类时遇到了麻烦。 Tank本身是唯一的这样一个类,它使用依赖注入来管理其部分。目前有两个部分:TankAI和TankWeapon。 AI负责决策运动和开火,武器描述武器行为-它发射什么弹药以及多久发射一次等。 我有一个工厂类,可以构建不同组合的坦克。
我的弹丸类设置在抽象Projectile类下。每个子类都描述了弹丸的模型,反弹次数,速度等。
我的问题是,每个TankWeapon子类都在构造新弹丸的区域周围重复了很多代码,因为它们各自构造了不同的类。我想将此代码移动到基类中,但我必须以某种方式注入武器需要构造的弹丸类本身。我知道我可以在构造时直接传递类,但那似乎不是正确的方法。
另外,我还有另一个设计问题:如何使我的AI类也了解弹丸类?他们的决策将取决于正在发射的弹药的属性,例如它们可以在墙上反弹多少次。 AI和Weapon类都在注入时给予对父级Tank的引用。
public class Tank : ISolidObject
{
public TankAI AISystem { get; private set; }
public TankWeapon Weapon { get; private set; }
public Tank(TankAI aiSystem, TankWeapon weapon)
{
this.AISystem = aiSystem;
this.AISystem.Tank = this;
this.Weapon = weapon;
this.Weapon.Tank = this;
}
}
public abstract class TankAI
{
public Tank Tank { get; set; }
public abstract void Think();
}
// TankAI implementations aren't important here
public abstract class TankWeapon
{
protected int maxShotsOnScreen, shotsOnScreen;
public Tank Tank { get; set; }
public virtual void Shoot()
{
shotsOnScreen++;
// I really want to put the projectile construction code in here
}
}
public class BulletWeapon : TankWeapon
{
public BulletWeapon()
{
this.maxShotsOnScreen = 5;
this.turnSpeed = 1;
}
public override void Shoot()
{
// here's my problem. Every weapon class duplicates this, because I can't put the projectile construction in the base weapon class.
if (shotsOnScreen >= maxShotsOnScreen) return;
base.Shoot();
// just create it, it will take care of the rest
double bx = Tank.X - Math.Sin(Tank.AngleTurret * Math.PI / 180.0);
double by = Tank.Y + Math.Cos(Tank.AngleTurret * Math.PI / 180.0);
// note that projectiles subscribe themselves to the game entity handler, so don't have to store it myself.
// this weapon creates bullets. A different weapon might create rockets. How would the base class know which? Is there any way I can prevent this code from being duplicated?
new Bullet(bx, by, Tank.AngleTurret).Death += ShotDeath;
}
private void ShotDeath(Projectile p)
{
p.Death -= ShotDeath;
shotsOnScreen--;
}
}
Tank.Weapon.Shoot()
。如果你有更好的想法,我很乐意听取建议。我知道我的解决方案并不完美。 - Tesserex