首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何设计具有不同子结构的类

如何设计具有不同子结构的类
EN

Stack Overflow用户
提问于 2014-03-09 12:56:10
回答 3查看 150关注 0票数 1

我有一个类别的“武器”,根据它的分类,它有不同的行为。可以在运行时更改行为,也可以将行为替换为其他行为。(对于那些知道的人来说,我描述的是一种蠕虫武器:世界末日)。

通常,我会创建实现特定行为的不同的“武器”子类,但是由于可以在运行时对其进行更改,所以不能使用这样的“静态类型化”。

我想到了像下面这样的类武器(C#)。

代码语言:javascript
复制
public class Weapon
{
    public AirstrikeSettings _airstrikeSettings;
    public MineSettings _mineSettings;
    public LauncherSettings _launcherSettings,
}

*Settings类包含定义确切行为的参数。

在运行时,必须检查3个设置实例中的哪个不为null,以确定这是什么武器分类。如果将分类更改,例如从“地雷”更改为“空袭”,则将MineSettings设置为null,并初始化AirstrikeSettings。

这是一个正确的设计方法,还是我有极端的设计问题?

PS:如果您感兴趣,这就是我想在我的课堂上反映的结构:区块

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2014-03-09 13:22:34

正如您已经说过的,基于继承的基于Weapon级别的方法将不允许您在运行时更改行为。我建议你看看战略设计模式。它允许您在运行时更改类的行为,并且可以避免类本身中有大量if-语句。

因此,在您的示例中,Weapon类将是上下文和策略设置。对于每种类型的设置,您将只拥有一个成员,而不是每个类型的设置有三个单独的成员。如果确保始终设置此设置,则不需要检查null,并且如果要执行特定于设置的行为,则始终调用当前设置。为了使其工作,设置需要基于一个共同的结构。

为了能够从外部设置行为,您可以为当前设置创建一个属性,该属性可以从类的外部访问,从而允许调用方在运行时更改该设置。

所以你的样本看起来很像这样:

代码语言:javascript
复制
// 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();
    }
}

请注意,如果某些设置不支持某些行为,则仍然需要实现它们,但只需不做任何操作或返回默认值。

票数 1
EN

Stack Overflow用户

发布于 2014-03-09 13:11:05

我建议您创建一个抽象的Weapon类,以及三个派生类:AirstrikeWeaponMineWeaponLauncherWeapon。每个子类都可以有自己的设置。然后,向基类中添加一个Attack方法,并使用每个派生类中所需的任何逻辑来实现它。然后,在运行时,每个蠕虫都有一个Weapon成员,可以将其设置为当前使用的武器的实例。

顺便说一下,这被称为多态。

票数 0
EN

Stack Overflow用户

发布于 2014-03-09 13:22:03

简单地说,如果我必须在运行时检查null是否知道类的类型,那么Inheritance究竟在做什么。

在您的示例中,您可以定义一个抽象类Settings,它将是这3个类的父类。那么类Weapon将只具有类Settings的引用。请参阅下列代码:

代码语言:javascript
复制
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
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/22282431

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档