通过使用助手功能保留的Demeter的完整性(删除了两个点)? [英] Integrity of Law of Demeter preserved by using helper function (removed two dots)?

查看:149
本文介绍了通过使用助手功能保留的Demeter的完整性(删除了两个点)?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

public House
{
    WeatherStation station;

    public float getTemp() {
        //Law of Demeter has been violated here
        return station.getThermometer().getTemperature();
    }
}

public House
{
    WeatherStation station;

    public float getTemp() {
        //Law of Demeter has been preserved?
        Thermometer thermometer = station.getThermometer();
        return getTempHelper(thermometer);
    }

    public float getTempHelper(Thermometer thermometer)
    {
        return thermometer.getTemperature();
    }
}

在上面的代码中,您可以看到两个不同的House类定义。这两个都有getTemp()函数,其中第一个违反了Demeter法,但第二个保护它(根据Head First Design Patterns书)。

In the code above you can see two different House class definitions. Both have getTemp() function, first of which violates Law of Demeter, but second one preservs it (according to Head First Design Patterns book).

麻烦是我不太明白为什么第二类保护法Demeter,getTemp()函数仍然有station.getThermometer()调用,哪个(应该?)违反了Demeter法则。
只使用一个点 - 我发现这在维基百科上可以适用,但我仍然需要更详细的解释 - 特别是,一个对象应该避免调用另一个方法返回的成员对象的方法(维基)。

The trouble is I don't quite get why second class preservs Law of Demeter, getTemp() function still has station.getThermometer() call, which (should?) violates Law of Demeter. "use only one dot" - I found this on wikipedia, which could be applicable, but I still need more detailed explanation - "In particular, an object should avoid invoking methods of a member object returned by another method" (wiki).

所以有人可以解释为什么第二个代码示例不违法?

So could anyone explain why the second code example does not violates the law? What truly distinguishes second method from first one?

推荐答案

我想,有很多关于这个问题的讨论,但是正如我所解释的那样,德米特法则的目的是...

I imagine there's a lot of discussion that can be had on the subject, but as I interpret it the purpose of the Law Of Demeter would be...

你不想从车站获取温度计,你想得到温度来自车站。

"You don't want to get the Thermometer from the Station. You want to get the Temperature from the Station."

从现实生活中考虑。你呼叫气象台,你不要问他们,建筑外面的温度计怎么说?你问他们:目前的温度是多少?事实上,他们有一个温度计附在他们的建筑物的外面是不关心的。也许他们用指向窗口的红外激光替代温度计。对你来说没关系他们的信息不是你的关心,你只是想要的信息。

Think of it from a real-life situation. You call up the weather station, you don't ask them, "What does the thermometer on the outside of your building say?" You ask them, "What is the current temperature?" The fact that they have a thermometer attached to the outside of their building isn't your concern. Maybe they replace the thermometer with an infrared laser pointed at a window. It doesn't matter to you. How they come by their information isn't your concern, you just want the information.

所以,为此,你会得到这样的结果: / p>

So, to that end, you'd end up with something like this:

public House
{
    private WeatherStation _station;

    public House(WeatherStation station)
    {
        _station = station;
    }

    public float GetTemperature()
    {
        return _station.GetTemperature();
    }
}

public WeatherStation
{
    private Thermometer _thermometer;

    public WeatherStation(Thermometer thermometer)
    {
        _thermometer = thermometer;
    }

    public float GetTemperature()
    {
        return _thermometer.GetTemperature();
        // This can be replaced with another implementation, or any other
        // device which implements IThermometer, or a hard-coded test value, etc.
    }
}

这导致了几个级别的嵌套,这似乎有点令人厌恶。但请记住,每个级别,虽然目前被称为完全相同的东西,意味着稍微不同的东西。如果重复的代码具有不同的含义,这不是真正的代码重复。你可以稍后用这样的方式打破链条:

This leads to a few levels of nesting, which does appear to be a little distasteful. But keep in mind that each level, while currently called the exact same thing, means something slightly different. It's not really code duplication if the duplicated code has a different meaning. You could later break the chain with something like this:

public House
{
    private WeatherStation _station;

    public House(WeatherStation station)
    {
        _station = station;
    }

    public WeatherInfoDTO GetCurrentWeather()
    {
        var info = new WeatherInfoDTO();
        info.Temperature = _station.GetTemperature();
        //...
        return info;
    }
}

public WeatherInfoDTO
{
    //...
}

public WeatherStation
{
    private Thermometer _thermometer;

    public WeatherStation(Thermometer thermometer)
    {
        _thermometer = thermometer;
    }

    public float GetTemperature()
    {
        return _thermometer.GetTemperature();
        // This can be replaced with another implementation, or any other
        // device which implements IThermometer, or a hard-coded test value, etc.
    }

    //...
}

通过不将顶层硬编码执行温度计,您可以轻松重构以支持此类。

By not hard-coding the top-level to the implementation of a Thermometer you allow for easy refactoring to support something like this.

这篇关于通过使用助手功能保留的Demeter的完整性(删除了两个点)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆