gpt4 book ai didi

c# - 在使用对象时从一种实现类型转换为另一种实现类型是否合适?

转载 作者:行者123 更新时间:2023-12-04 15:28:03 25 4
gpt4 key购买 nike

我有一个简单的代码库,其中包含几个“武器”具体类,这些具体类实现了不同的契约以供其客户使用。

我的契约(Contract):

public interface IWeaponPrimaryAttack
{
void DoAttack();
}
public interface IWeaponSecondaryAttack
{
void DoSecondaryAttack();
}
public interface IReloadable
{
void Reload();
}

具体实现或实际武器:

public class Katana : IWeaponPrimaryAttack, IWeaponSecondaryAttack
{
public void DoAttack(){Console.WriteLine ("Swing");}
public void DoSecondaryAttack() {Console.WriteLine ("Stab");}
}
public class ShotGun : IWeaponPrimaryAttack, IReloadable
{
public void DoAttack(){Console.WriteLine ("Swing");}
public void Reload() {//reload it}
}

使用这些具体类的客户端:

public class PrimaryAttack
{
private IWeaponPrimaryAttack _attack;
public PrimaryAttack(IWeaponPrimaryAttack attack)
{
_attack = attack;
}
public void DoAttack()
{
_attack.DoAttack();
}
}
public class SecondaryAttack
{
private IWeaponSecondaryAttack _attack;
public SecondaryAttack(IWeaponSecondaryAttack attack)
{
_attack = attack;
}
public void DoSecondaryAttack()
{
_attack.DoSecondaryAttack();
}
}
public class WeaponReload
{
private IReloadable _reloader;
public WeaponReload(IReloadable reloader)
{
_reloader = reloader;
}
public void Reload()
{
_reloader.Reload();
}
}

当然,新的具体类的实例只有在用户选择多种武器中的一种(ShotGun、Katana 等中的一种)时才知道。

假设用户选择了 ShotGun 作为武器,根据选择它可能是这样的:

IWeaponPrimaryAttack weapon = new ShotGun(); // get it from a factory
PrimaryAttack primaryAttack = new PrimaryAttack(weapon);
primaryAttack.DoAttack();

现在对于 WeaponReload 必须在这里进行类型转换才能使用它。

WeaponReload reloader = new WeaponReload ((IReloadable)weapon);
reloader.Reload();

我对此有疑问,

  • 我真的应该最终结束类型转换吗?
  • 或者有更好的方法来处理这个对象创建部分。
  • 或者我可以想出一个更好的设计不一定会在选角中结束。
  • 或者像这样类型转换它完全没问题。

最佳答案

不太确定为什么需要所有这些额外的委托(delegate)包装器?无论如何,这里有一些事情在起作用。

最大化组合

您在这里为每种武器类型使用了一个具体类型,但您也可以更加强调组合并拥有一个包罗万象的 Weapon 类,将其所有内部工作委托(delegate)给 strategies .

例如

您可以使用 Weapon shotgun = Weapons.shotgun() 而不是 Weapon shotgun = new Shotgun();,其中工厂方法可能如下所示:

return new Weapon.Builder()
.withPrimaryAttack(...)
.withoutSecondaryAttack()
.withSlowReload().build();

最大化组合使设计变得非常灵活,并且可以让您在需要时动态地引入新的武器类型,甚至可以在运行时更改武器的某些方面(例如,霰弹枪现在可以在拾取能量的情况下发射刀 b/c)。

ISP之后

在上述基于组合的方法中,您可能会注意到 Weapon 的界面会变得臃肿,因为武器可以执行各种操作。依赖于 Weapon 类的客户端将间接依赖于它们可能永远不会调用的所有各种隐式接口(interface)方法。

为了减少客户端耦合,您可以很好地确保将 Weapon 功能隔离到许多接口(interface)中,例如 IReloadable 等。Weapon 类将全部实现它们,但是只对武器功能的一个子集感兴趣的客户端代码仍然可以依赖于这些接口(interface)而不是 Weapon

例如

reload(weapon);

void reload(IReloadable reloadable) {
if (stamina < ...) throw ...;

reloadable.reload();
}

ISP 和特征检测

考虑到您的原始设计,我认为使用 instanceof 作为特征检测机制没有任何根本性的错误。

使用instanceof 来匹配具体类型肯定是错误的,但是匹配接口(interface)很可能没问题。

weapon instanceof Shotgun //bad
weapon instanceof IReloadable //ok

请注意,在转换之前,您应该始终检查 instanceof。另请注意,您需要想出一种方法让武器实现者了解他们可以实现的一组潜在武器功能接口(interface)。

关于c# - 在使用对象时从一种实现类型转换为另一种实现类型是否合适?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61856870/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com