Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 这是什么设计模式?_C#_Design Patterns - Fatal编程技术网

C# 这是什么设计模式?

C# 这是什么设计模式?,c#,design-patterns,C#,Design Patterns,很久以前我做过一次,当时我遵循了一种设计模式。现在,我需要再做一次,我真的不记得我以前是怎么做的,我想不出是什么样的模式帮了我 我有一个包含大量变量/属性的类。有些是基于其他属性计算的,这些属性之间存在各种交叉计算 当我第一次实例化时,一切都很好——所有的值和计算都很好。我的问题是,当一个值更改时,我希望从中派生的所有计算值根据新值自动更新自己。如果不需要的话,我也不想手动编写每个recalc——每当这个类被更新或添加到其中,试图跟踪所有需要传播任何更改的地方,这都会增加很多开销 我想你跟着我

很久以前我做过一次,当时我遵循了一种设计模式。现在,我需要再做一次,我真的不记得我以前是怎么做的,我想不出是什么样的模式帮了我

我有一个包含大量变量/属性的类。有些是基于其他属性计算的,这些属性之间存在各种交叉计算

当我第一次实例化时,一切都很好——所有的值和计算都很好。我的问题是,当一个值更改时,我希望从中派生的所有计算值根据新值自动更新自己。如果不需要的话,我也不想手动编写每个recalc——每当这个类被更新或添加到其中,试图跟踪所有需要传播任何更改的地方,这都会增加很多开销

我想你跟着我

不管怎样,谁能想到是什么样的模式使这成为可能?我发誓我以前知道。我想是变老了

// Like this...
class foo
{
    decimal A = 1233;
    decimal B = 42;

    decimal C = A / B; // I want this to update whenever
                       // the value of either A or B changes.
    decimal D = 123;
    decimal E = 321;

    decimal F = D + E; // I don't want this one to change when
                       // A or B or even C for that matter changes,
                       // and I don't wan to have to cycle through
                       // all of the calculated values that don't
                       // need to change just for find the few that do.
}

观察员。您需要在模型上使用某种类型的
.Subscribe()
方法来注册回调—在您的特定情况下,这些函数只是接受新值并基于该值重新计算其他函数的函数。只要您的编程环境有实现,我强烈建议您坚持使用该实现。否则,您将因为多线程和内存泄漏而蒙受损失

我建议在这里避免过度设计。您作为示例展示的有6个成员,它们之间有简单的依赖关系,可以轻松地重新计算。我知道这只是一个简单的例子,所以让我们针对10-20个成员,以及不需要数据库查找或磁盘访问的依赖项(作为较重操作的示例)

您可以将所有依赖项放在一个方法中(我们称之为
Update
),如果任何成员被修改,您将调用该方法。为了避免忘记调用
Update()
,您将所有成员移动到一个单独的“state”类中:

你得到的是:

  • 事情马上就清楚了。给任何一个碰巧遇到你的人 修改此代码
  • 成员之间的所有依赖项都在一个方法中,易于阅读和修改。您的业务逻辑不会被这些细节所污染
  • 您不能忘记重新计算您的从属成员
  • 是的,您可以进行比严格要求更多的重新计算,因为即使修改了不相关的成员,您也可以重新计算所有从属成员。在我在真实文件中看到的大多数类似案例中,这都不是问题
  • 如果您有循环依赖关系(这是另一种情况),这种方法就不起作用
可以随意实现“观察者”模式并进行比较


我认为这种简单的方法没有名字。不要把它与“状态”模式混淆,这是一件有点不同的事情。

我想不出任何模式。但是INotifyPropertyChanged在类本身注册更改事件以进行重新计算的地方可以工作。最大的危险是你可能会在一个infinite更新循环中结束:a改变B,B改变a。特别是对于浮点inprecision,这种危险是非常真实的。谢谢Christopher,我来看看这个。这样的计算不是乱伦的,所以没有无限循环的危险,但感谢提醒。这不是一种设计模式,但这符合可观测的描述。事件驱动架构模式?(埃达)艾米——看着观察到的东西,我的记忆又回来了——就是这样!谢谢你让一个老黑客动脑筋!观察员…听起来很熟悉。谢谢我会查一查,看看它是否管用。@KevinPaulTracy,它会管用的:它是专门为此设计的。只是不要自己实现它,而是采用
rxjs
或您的环境中现有的类似机制。有些平台,比如.NET,提供了默认的实现,对于简单的情况来说已经足够了。不要认为RXJS可以工作-这不是一个UI,它是一个后端解决方案。但这种模式看起来可能是这样的。我来看看,谢谢。网络有反应式扩展。在我看来,这太过分了,但功能非常强大。@KevinPaulTracy,它可以与UI和后端一起工作。由于现代UI的事件驱动起源,它与UI的配合更加自然。请检查您是否支持.NET。它几乎不可测试、不线程安全、几乎不可扩展、非泛型,并且依赖于隐式状态而不是干净的纯函数-1和-10,如果我能做到的话。我明白你的意思,但是这个解决方案仍然比我想要的更需要维护。但是谢谢!
class FooState
{
    private int _a;

    public int A
    {
        get { return _a; }
        set
        {
            _a = value;
            Update();
        }
    }

    private int _b;

    public int B
    {
        get { return _b; }
        set
        {
            _b = value;
            Update();
        }
    }

    public double C { get; private set; }

    // other members

    private void Update()
    {
        C = A * B + 3;
        // other updates
    }
}

class Foo
{
    private FooState _state;

    public Foo()
    {
        _state.A = 1;
        _state.B = 2;
        Debug.Write($"C = {_state.C}");
    }
}