战略模式在F# [英] Strategy pattern in F#

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

问题描述

在C#中,我有以下代码:

public class SomeKindaWorker
{
public double Work(策略策略)
{
int i = 4;
//一些代码...
var s = strat.Step1(i);
//多一些代码...
var d = strat.Step2(s);
//更多代码...
return d;
}
}

这是一段可以做某种类型的代码通过使用提供的策略 object 来填充部分实现。注意:一般来说策略对象不包含状态;它们只是多态地提供了各个步骤的实现。



策略类看起来像这样:

  public abstract class Strategy 
{
public abstract string Step1(int i);
public abstract double Step2(string s);
}

public class StrategyA:策略
{
public override string Step1(int i){returnwhatever; }
public override double Step2(string s){return 0.0; }
}

public class StrategyB:Strategy
{
public override string Step1(int i){returnsomething else; }
public override double Step2(string s){return 4.5; }
}

观察:效果相同在C#中通过使用lambda表达式(并且完全摆脱了策略对象),但是这个实现的好处是扩展类将Step1和Step2实现在一起。



:在F#中这个想法的惯用实现是什么?



想法:



我可以在Work函数中注入单步函数,类似于观察中的想法。



我也可以创建一个类型来收集两个函数,并通过该类型的传递:

  type Strategy = {Step1:int  - >串;第二步:字符串 - > double} 
let strategyA = {Step1 =(fun i - >whatever); Step2 = fun s - > 0.0}
let strategyB = {Step1 =(fun i - >something else); Step2 = fun s - > 4.5}

这似乎与我想实现的最接近的匹配:它保持执行步骤靠近在一起,以便它们可以作为一堆进行检查。但是,这个想法(创建一个只包含函数值的类型)在功能范式中是惯用的吗?任何其他想法?

解决方案

以下是对问题的更多功能方法:

  type Strategy = 
| StrategyA
|策略B

让step1 i =函数
| StrategyA - > 无论
|策略B - > 别的东西

让step2 s =函数
| StrategyA - > 0.0
|策略B - > 4.5

让工作策略=
让i = 4
让s = step1我的策略
让d = step2的策略
d


In C# I have the following code:

public class SomeKindaWorker
{
    public double Work(Strategy strat)
    {
        int i = 4;
        // some code ...
        var s = strat.Step1(i);
        // some more code ...
        var d = strat.Step2(s);
        // yet more code ...
        return d;
    }
}

This is a piece of code that can do some kind of work by using a provided strategy object to fill in parts of the implementation. Note: in general the strategy objects do not contain state; they merely polymorphically provide implementations of individual steps.

The strategy class looks like this:

public abstract class Strategy
{
    public abstract string Step1(int i);
    public abstract double Step2(string s);
}

public class StrategyA : Strategy
{
    public override string Step1(int i) { return "whatever"; }
    public override double Step2(string s) { return 0.0; }
}

public class StrategyB : Strategy
{
    public override string Step1(int i) { return "something else"; }
    public override double Step2(string s) { return 4.5; }
}

Observation: The same effect can be achieved in C# through the use of lambdas (and getting rid of the strategy object altogether), but the nice thing about this implementation is that the extending classes have their Step1 and Step2 implementations together.

Question: What is an idiomatic implementation of this idea in F#?

Thoughts:

I could inject individual step functions into the Work function, similar to the idea in the observation.

I could also create a type that collects two functions, and pass a value of that type through:

type Strategy = { Step1: int -> string; Step2: string -> double }
let strategyA = { Step1 = (fun i -> "whatever"); Step2 = fun s -> 0.0 }
let strategyB = { Step1 = (fun i -> "something else"); Step2 = fun s -> 4.5 }

This seems like the closest match to what I'm trying to achieve: it keeps the implementing steps close together so that they may be examined as a bunch. But is this idea (creating a type to contain function values only) idiomatic in the functional paradigm? Any other thoughts?

解决方案

Here's a more functional approach to the question:

type Strategy =
    | StrategyA
    | StrategyB

let step1 i = function
    | StrategyA -> "whatever"
    | StrategyB -> "something else"

let step2 s = function
    | StrategyA -> 0.0
    | StrategyB -> 4.5

let work strategy = 
    let i = 4
    let s = step1 i strategy
    let d = step2 s strategy
    d

这篇关于战略模式在F#的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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