首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >继承/面向对象设计问题

继承/面向对象设计问题
EN

Software Engineering用户
提问于 2014-04-25 11:49:05
回答 6查看 463关注 0票数 4

这可能是个很简单的问题,但首先需要一些背景.我正在模拟各种硬件开关,这些开关可以打开或关闭。这些开关是可配置的,允许用户指定发送到硬件的数字值,以表示它应该打开或关闭。这是Switch类:-

代码语言:javascript
复制
public class Switch
{
    public Id { get; set; }
    public SwitchConfig Config { get; set; }

    public void TurnOn()
    {
        WriteToSerialPort(Id, Config.OnValue);
    } 

    public void TurnOff()
    {
        WriteToSerialPort(Id, Config.OffValue);
    } 
}

public class SwitchConfig
{
    public int OnValue { get; set; }
    public int OffValue { get; set; }
}

到目前一切尚好。

现在我需要建模一种新类型的开关,它不仅可以打开和关闭,而且还可以设置温度阈值,因此从Switch类继承似乎是明智的。该配置还需要扩展以包括最低/最高允许温度,例如:

代码语言:javascript
复制
public TemperatureSwitchConfig : SwitchConfig
{
    public int MinTemperature { get; set; }
    public int MaxTemperature { get; set; }
}

专业开关类如下所示:-

代码语言:javascript
复制
public TemperatureSwitch : Switch
{
    public void SetTemperature(int temperature)
    {
        var temperatureSwitchConfig = Config as TemperatureSwitchConfig;

        if (temperature < temperatureSwitchConfig.MinTemperature
            || temperature > temperatureSwitchConfig.MaxTemperature)
        {
             return;
        }

        WriteToSerialPort(Id, temperature);
    }
}

在我不得不抛出Config属性的地方,它感觉“不对”。我相信一定有一个更圆滑的OO解决方案,但我认为“分析瘫痪”已经开始,我看不到树木的木材!还是我什么都不担心--在这种情况下,铸造是一个可以接受的解决方案吗?

EN

回答 6

Software Engineering用户

回答已采纳

发布于 2014-04-25 13:52:17

我建议您从类中删除Config属性,并将它的所有属性放入类本身。然后,在每个开关的构造函数中或作为属性设置这些属性。

您说SwitchConfig来自于XML序列化。如果您想以某种方式将序列化参数化,这通常是使用模型类中的属性完成的(在您的例子中是SwitchConfig)。然后,SwitchConfing和传递的Switch就会依赖于模块来进行XML序列化。

如果您想要创建基于XML以外的其他东西的开关呢?然后,您需要不必要地创建Config类,而不是在构造函数或属性中设置参数。

最后想到的是:如何创建Switch类的具体类型?例如:如何决定创建SwitchTemperatureSwitch?可能是基于SwitchConfig的类型。如果你已经有了这样的代码,为什么不直接把它变成一个功能齐全的工厂,根据XML数据构建特定的开关呢?而且XML序列化可以在这个工厂内部封装。

如果您担心在配置更改时需要更改许多东西,那么您可以按照Karl的话,使用弱类型反序列化,而不是显式类模型。

票数 1
EN

Software Engineering用户

发布于 2014-04-25 12:54:16

您关于需要从xml生成Config的评论为问题添加了一个全新的维度。强类型在编译时最有用,在这里不适用。我倾向于创建一个Dictionary来保存解析的配置,并使用它如下:

代码语言:javascript
复制
public TemperatureSwitch : Switch
{
    public void SetTemperature(int temperature)
    {
        if (temperature < config["MinTemperature"]
         || temperature > config["MaxTemperature"])
        {
             return;
        }

        WriteToSerialPort(Id, temperature);
    }
}

您可以将验证放入解析器代码或setter代码中。或者,您可以完全放弃Config,让您的xml解析器代码直接创建Switch对象,并为配置项设置单独的字段。

票数 4
EN

Software Engineering用户

发布于 2014-04-25 12:50:17

您可以将配置设置为参数:

代码语言:javascript
复制
public abstract class Switch<TConfig> where TConfig : SwitchConfig
{
    public Id { get; set; }
    public TConfig { get; set; }

    public void TurnOn()
    {
        WriteToSerialPort(Id, Config.OnValue);
    } 

    public void TurnOff()
    {
        WriteToSerialPort(Id, Config.OffValue);
    } 
}

public class NormalSwitch : Switch<SwitchConfig>
{
}

public TemperatureSwitch : Switch<TemperatureSwitchConfig>
{
    public void SetTemperature(int temperature)
    {

        if (temperature < Config.MinTemperature
            || temperature > Config.MaxTemperature)
        {
             return;
        }

        WriteToSerialPort(Id, temperature);
    }
}
票数 1
EN
页面原文内容由Software Engineering提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://softwareengineering.stackexchange.com/questions/236988

复制
相关文章

相似问题

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