避免用耦合策略模式 [英] Avoiding coupling with Strategy pattern

查看:189
本文介绍了避免用耦合策略模式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图策略模式适用于特定的情况,但我有与如何避免每个具体的战略耦合为它提供数据上下文对象的问题。以下是发生几种不同的方式的图案的简化情况下,但应该以类似的方式来处理。

I am attempting to apply the Strategy pattern to a particular situation, but am having an issue with how to avoid coupling each concrete strategy to the context object providing data for it. The following is a simplified case of a pattern that occurs a few different ways, but should be handled in a similar way.

我们有一个对象收购,提供相关的特定时间帧数据 - 基本上是一堆用不同的硬件采集外部数据。它已经过大,因为数据包含的金额,所以我不想给它任何进一步的责任。现在,我们需要采取一些这方面的数据,并根据一些配置发送相应的电压一块硬件。

We have an object Acquisition that provides data relevant to a specific frame of time - basically a bunch of external data collected using different pieces of hardware. It's already too large because of the amount of data it contains, so I don't want to give it any further responsibility. We now need to take some of this data, and based on some configuration send a corresponding voltage to a piece of hardware.

所以,想象下面的(很简单)班

So, imagine the following (much simplified) classes:

class Acquisition
{
    public Int32 IntegrationTime { get; set; }
    public Double Battery { get; set; }
    public Double Signal { get; set; }
}

interface IAnalogOutputter
{
    double getVoltage(Acquisition acq);
}

class BatteryAnalogOutputter : IAnalogOutputter
{
    double getVoltage(Acquisition acq)
    {
        return acq.Battery;
    }
}

现在,每一个具体的策略类有要被连接到我的采集类,这也是最可能的类之一,因为它的核心,以我们的应用进行修改。这仍然是在旧设计的改进,这是一个巨大的switch语句的的的收购类。每种类型的数据可能有不同的转换方法(而电池是一个简单的直通,其他人根本不是这么简单),所以我觉得策略模式或相似的应该是要走的路。

Now, every concrete strategy class has to be coupled to my Acquisition class, which is also one of the most likely classes to be modified since it's core to our application. This is still an improvement over the old design, which was a giant switch statement inside the Acquisition class. Each type of data may have a different conversion method (while Battery is a simple pass-through, others are not at all that simple), so I feel Strategy pattern or similar should be the way to go.

我也注意到,在最终实施, IAnalogOutputter 将是一个抽象类,而不是一个接口。这些类将在是由用户配置的,序列化到一个XML文件的列表。该列表必须在运行时可编辑的记忆,所以序列化必须是我们最终的解决方案的一部分。如果它的确与众不同。

I will also note that in the final implementation, IAnalogOutputter would be an abstract class instead of an interface. These classes will be in a list that is configurable by the user and serialized to an XML file. The list must be editable at runtime and remembered, so Serializable must be part of our final solution. In case it makes a difference.

我如何才能确保每一个实现类得到它需要工作的数据,而将其直接连接到我的最重要的一个类?还是我接近这种问题的完全错误的方式?

How can I ensure each implementation class gets the data it needs to work, without tying it to one of my most important classes? Or am I approaching this sort of problem in the completely wrong manner?

推荐答案

好吧,我不想给不给别人的功劳在这里,但我发现,工作得非常好,我的目的一个混合解决方案。它系列化完美,大大简化了增加新的输出类型。关键是一个单一的界面, IOutputValueProvider 。还应注意这个模式是如何轻松处理不同的存储数据(如字典,而不是一个参数)的方式检索。

Ok, I hate to not give someone else the credit here, but I found a hybrid solution that works very well for my purposes. It serializes perfectly, and greatly simplifies the addition of new output types. The key was a single interface, IOutputValueProvider. Also note how easily this pattern handles the retrieval of varying ways of storing the data (such as a Dictionary instead of a parameter).

interface IOutputValueProvider
{
    Double GetBattery();
    Double GetSignal();
    Int32 GetIntegrationTime();
    Double GetDictionaryValue(String key);
}

interface IAnalogOutputter
{
    double getVoltage(IOutputValueProvider provider);
}

class BatteryAnalogOutputter : IAnalogOutputter
{
    double getVoltage(IOutputValueProvider provider)
    {
        return provider.GetBattery();
    }
}

class DictionaryValueOutputter : IAnalogOutputter
{
    public String DictionaryKey { get; set; }
    public double getVoltage(IOutputValueProvider provider)
    {
        return provider.GetDictionaryValue(DictionaryKey);
    }
}



那么,我只需要确保收购实现的接口:

class Acquisition : IOutputValueProvider
{
    public Int32 IntegrationTime { get; set; }
    public Double Battery { get; set; }
    public Double Signal { get; set; }
    public Dictionary<String, Double> DictionaryValues;

    public double GetBattery() { return Battery;}
    public double GetSignal() { return Signal; }
    public int GetIntegrationTime() { return IntegrationTime; }
    public double GetDictionaryValue(String key) 
    {
        Double d = 0.0;
        return DictionaryValues.TryGetValue(key, out d) ? d : 0.0;
    }
}

这是不完美的,因为现在有一个巨大的接口必须保持并在一些重复的代码收购,但有东西风险少了很多赫克被改变,影响了我的应用程序的其他部分。这也让我开始子类化收购,而无需改变一些这些外部件。我希望这将有助于其他一些类似的情况。

This isn't perfect, since now there's a gigantic interface that must be maintained and some duplicate code in Acquisition, but there's a heck of a lot less risk of something being changed affecting the other parts of my application. It also allows me to start subclassing Acquisition without having to change some of these external pieces. I hope this will help some others in similar situations.

这篇关于避免用耦合策略模式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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