策略模式 - 多种返回类型/值

发布于 2024-08-10 19:55:51 字数 1124 浏览 1 评论 0原文

我们正在使用 C# 和 EmguCV 开发一个图像处理项目。我们的团队由3人组成。为了取得更快的进展,我们三个人同时研究不同的子问题或尝试不同的算法。

目前,我们每个人都创建一个包含我们正在处理的主要代码的函数,并且我们所有人都对驱动程序进行更改以添加对新函数的调用。所有这些都发生在同一个文件上。我们正在使用源代码控制,所以我们还没有互相干涉。但我认为,随着我们取得更多进展,这种情况不会持续。另外,我觉得代码变得越来越混乱。

我认为对我们来说,实现策略模式并将我们的算法或子问题处理封装到它们自己的类中并从驱动程序中调用每个类的执行方法可能会更好。

然而我意识到这种方法可能存在一些问题:

  1. 不同的算法采用不同的输入(源图像、一些不同的参数集等)
  2. 不同的算法返回不同的输出(新图像、特征集、矩阵等)

我相信第一个问题可以通过做这样的事情来克服,

Class Strategy1 : IStrategy
{
    int _code;

    // Different *input* paramteres for the strategy may be passed in the 
    // constructor depending on the type of strategy
    public Strategy1(int c)
    {
        _code = c;
    }

    // This is the method defined in the IStrategy interface
    public void execute()
    {
        // Some code that uses _code and does some processing goes here
    }
}

我可以改变不同策略的构造函数,这样它们就可以接受不同类型的参数。

当我思考如何处理返回多个类型/值的问题时,我首先想到的就是将execute的返回类型从void更改为类似哈希表的东西,其中可以存储和返回不同的返回参数< strong>OR 具有该类的其他成员,例如“int _returnCode”,可以通过其他方法或通过该类的只读属性来检索。

我不确定这在设计原则方面有多好,并且很高兴听到您对此的意见。谢谢

We are working on an image processing project using C# and EmguCV. Our team is composed of 3 people. To make faster progress, the 3 of us work on different sub-problems or experiment with different algorithms at the same time.

Currently each of us creates a function that contains the major code we are working at and all of us make changes to the driver to add calls to our new functions. All this happens on the same file. We are using source control, so we have not stepped into each other toes yet. But I don't think this will be sustainable as we make more progress. Also, I feel the code is getting messier.

I was thinking it may be better for us to implement the Strategy pattern and encapsulate our algorithms or sub-problem processing into classes of their own and call the execute method on each from the driver.

However I realize there may be some problems with this approach:

  1. Different algorithms take different inputs (source image, some different set of parameters etc)
  2. Different algorithms return different outputs (new image, feature set, a matrix etc)

The first problem I believe I can overcome by doing something like this

Class Strategy1 : IStrategy
{
    int _code;

    // Different *input* paramteres for the strategy may be passed in the 
    // constructor depending on the type of strategy
    public Strategy1(int c)
    {
        _code = c;
    }

    // This is the method defined in the IStrategy interface
    public void execute()
    {
        // Some code that uses _code and does some processing goes here
    }
}

I can change the constructors for the different strategies so they can take in different types of arguments.

When I think about how to deal with the issue of returning multiple types/values, the first thing I can think of is to change execute's return type from void to something like a hash table, where the different return parameters can be stored and returned OR have other members of the class, like "int _returnCode" which can be retrieved by another method or through read-only properties of that class.

I am not sure how good a solution this would be in terms of design principles, and would be happy to hear your opinion on this. Thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

不寐倦长更 2024-08-17 19:55:51

如果算法唯一的共同点是它们执行,那么您应该考虑命令模式 而不是策略模式。 (至少,这最适合您所描述的解决方案。)

这很好!它不会为您带来策略模式的细粒度可持续性,但听起来您没有能力做到这一点。命令模式将允许您将特定于算法的代码与处理流控制(驱动程序,从它的声音来看)分开。

例如,它可以让您编写如下代码:

// ... logic to obtain an image and handle application flow ...

// I'm using 'image' here as a stand-in for a single object all your commands
// could derive their inputs from, or a container of all the inputs. If no such
// object exists, just do what you have to construct the commands.
ICommand[] commands = ImageCommandFactory.CreateCommands(image);

foreach(ICommand command in commands) {
    command.Execute();
}

// ... Handle commands ...

正如您所提到的,命令对象将使用公共成员来公开其执行结果 - 最简单的形式将使用类似 public object Results { get; 的属性。 }。 (当然,您越能将返回值缩小为标准的 ICommandResults 类型,效果就越好。)

如何处理结果取决于您。您可以(再次)使用工厂来创建适合您传递的命令的处理程序:

// Picks the correct type of processor, depending on the command
IResultHandler handler = ResultHandlerFactory.CreateHandler(command, form);

// renders the results to the form provided to the factory method
handler.RenderResults();

或者使用更适合您的设计的其他技术。

If the only thing the algorithms have in common is that they execute, you should be thinking about the command pattern rather than the strategy pattern. (At least, that best fits the solution you've described.)

This is fine! It doesn't buy you the fine-grained sustitutability of the strategy pattern, but it doesn't sound like you're in a position to do that. The command pattern will let you keep your algorithm-specific code separate from your processing flow control (the driver, from the sound of it).

For example, it would let you write code like this:

// ... logic to obtain an image and handle application flow ...

// I'm using 'image' here as a stand-in for a single object all your commands
// could derive their inputs from, or a container of all the inputs. If no such
// object exists, just do what you have to construct the commands.
ICommand[] commands = ImageCommandFactory.CreateCommands(image);

foreach(ICommand command in commands) {
    command.Execute();
}

// ... Handle commands ...

As you mentioned, command objects would use public members to expose the results of their execution - the simplest form would use a property like public object Results { get; }. (Of course, the more you can narrow that return value down to a standard ICommandResults type, the better off you'll be.)

How you handle results is up to you. You could use a factory (again) to create a handler suitable for the command you pass it:

// Picks the correct type of processor, depending on the command
IResultHandler handler = ResultHandlerFactory.CreateHandler(command, form);

// renders the results to the form provided to the factory method
handler.RenderResults();

Or use some other technique that fits your design better.

一向肩并 2024-08-17 19:55:51

如果您可以自由使用 C# 4,则可以依赖 协变 返回类型特征。
这样,您可以将执行接口定义为:,

public object execute()

然后在派生类中使用特定于该具体类的返回类型覆盖它。

If you have the freedom to use C# 4, you could rely on the covariant return type feature.
That way you can define the interface for execute as:

public object execute()

and then override it in derived classes with return types specific to that concrete class.

幻想少年梦 2024-08-17 19:55:51

这里有几件事:

  • 将所有内容都放在一个文件中是一种反模式“大泥球”
  • 您可以使用部分类将其拆分为多个文件,这解决了许多人处理同一个文件的问题,但只是稍微好一些。
  • 与其采用策略模式,为什么不直接创建帮助器类(帮助器模式),每个帮助器都可以进行测试。

There are several things here:

  • having everything in a single file is an anti-pattern "Big ball of mud"
  • You could split it into several files using partial classes, this solves your problem of many people working on the same file, but is only marginally better.
  • Instead of the strategy pattern, why not just create helper classes (helper pattern), each helper can be tested.
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文