我有一个类别的“武器”,根据它的分类,它有不同的行为。可以在运行时更改行为,也可以将行为替换为其他行为。(对于那些知道的人来说,我描述的是一种蠕虫武器:世界末日)。
通常,我会创建实现特定行为的不同的“武器”子类,但是由于可以在运行时对其进行更改,所以不能使用这样的“静态类型化”。
我想到了像下面这样的类武器(C#)。
public class Weapon
{
public AirstrikeSettings _airstrikeSettings;
public MineSettings _mineSettings;
public LauncherSettings _launcherSettings,
}*Settings类包含定义确切行为的参数。
在运行时,必须检查3个设置实例中的哪个不为null,以确定这是什么武器分类。如果将分类更改,例如从“地雷”更改为“空袭”,则将MineSettings设置为null,并初始化AirstrikeSettings。
这是一个正确的设计方法,还是我有极端的设计问题?
PS:如果您感兴趣,这就是我想在我的课堂上反映的结构:区块
发布于 2014-03-09 13:22:34
正如您已经说过的,基于继承的基于Weapon级别的方法将不允许您在运行时更改行为。我建议你看看战略设计模式。它允许您在运行时更改类的行为,并且可以避免类本身中有大量if-语句。
因此,在您的示例中,Weapon类将是上下文和策略设置。对于每种类型的设置,您将只拥有一个成员,而不是每个类型的设置有三个单独的成员。如果确保始终设置此设置,则不需要检查null,并且如果要执行特定于设置的行为,则始终调用当前设置。为了使其工作,设置需要基于一个共同的结构。
为了能够从外部设置行为,您可以为当前设置创建一个属性,该属性可以从类的外部访问,从而允许调用方在运行时更改该设置。
所以你的样本看起来很像这样:
// base strategy, can also be an abstract class if you want to share
logic between the settings
public interface IWeaponSettings
{
// Definition of common structure for the behaviors
void BehaveInSpecialWay();
// ...
}
public class AirstrikeSettings: IWeaponSettings
{
// Implementation for Airstrike
public void BehaveInSpecialWay()
{
// Airstrike
}
}
public class MineSettings : IWeaponSettings
{
// Implementation for Mining
public void BehaveInSpecialWay()
{
// Mining
}
}
// ...
public class Weapon
{
// Constructor that takes the initial settings as an input
public Weapon(IWeaponSettings settings)
{
Settings = settings
}
// Public property that can be used to change behavior.
// You might want to check against null in the setter
public IWeaponSettings Settings { get; set; }
public void DoSomething()
{
Settings.BehaveInSpecialWay();
}
}请注意,如果某些设置不支持某些行为,则仍然需要实现它们,但只需不做任何操作或返回默认值。
发布于 2014-03-09 13:11:05
我建议您创建一个抽象的Weapon类,以及三个派生类:AirstrikeWeapon、MineWeapon和LauncherWeapon。每个子类都可以有自己的设置。然后,向基类中添加一个Attack方法,并使用每个派生类中所需的任何逻辑来实现它。然后,在运行时,每个蠕虫都有一个Weapon成员,可以将其设置为当前使用的武器的实例。
顺便说一下,这被称为多态。
发布于 2014-03-09 13:22:03
简单地说,如果我必须在运行时检查null是否知道类的类型,那么Inheritance究竟在做什么。
在您的示例中,您可以定义一个抽象类Settings,它将是这3个类的父类。那么类Weapon将只具有类Settings的引用。请参阅下列代码:
public abstract class Settings
{
}
public class AirstrikeSettings : Settings
{
}
public class MineSettings : Settings
{
}
public class LauncherSettings : Settings
{
}
public class Weapon
{
public Settings Settings { get; set; } // as this member is public, it can be declared as property
}https://stackoverflow.com/questions/22282431
复制相似问题