OOP - 使用类属性或 lambda 包装静态方法(同名)的设计模式是否有名称?

OOP - Is there a name for the design pattern of using class properties or lambdas to wrap static methods (of the same name)?

提问人:Austin C 提问时间:10/6/2023 最后编辑:Mark SeemannAustin C 更新时间:10/6/2023 访问量:63

问:

我目前正在使用一个 C# 类,该类公开了一些 lambda [instance] 方法,这些方法用作同名静态方法的包装器。

下面是一个示例代码段:

public class UserUI : DataUI
{
  // FYI: the `Context` object here is inherited from the `DataUI` base class
  public string GetUserId() => GetUserId(Context);

  public static string GetUserId(IDataUIContext context)
  {
    // ... logic here for pulling id from `context` ...
    return userId;
  }
}

我想知道:这样的设计模式有名字吗?


此外,是否可以在此处使用类属性而不是实例方法/ lambda来实现相同的功能?

这样:

public class UserUI : DataUI
{
  public string GetUserId => GetUserId(Context);

  public static string GetUserId(IDataUIContext context)
  {
    // ... logic here for pulling id from `context` ...
    return userId;
  }
}

如果是这样,使用属性/getter 之间有什么明显的区别吗?(显然,除了必须调用方法,而不是像字段一样访问方法)

C# OOP 设计模式 静态方法 类属性

评论

0赞 knittl 10/6/2023
我不明白你通过拥有该方法的静态版本获得了什么?您可以实现,但不需要第二种方法public string GetUserId() { ... }
0赞 lidqy 10/6/2023
(get-set)属性只是一对方法的特殊语法,这些方法从/写入同一字段/存储,并且(似乎)具有相同的名称。因此,如果您使用其中一个,则没有太大区别。但是,喜欢属性且无法处理方法(JSON/WPFdatabinding 仅举几例)的 API 并不少。如果您不必遵守这些规定,那就要看品味了。通常,属性应该像字段访问一样快速运行。除了获取和返回值之外,不要执行许多子步骤。至于图案的名称:相反的是:YAGNI ;)
0赞 knittl 10/6/2023
请注意,表达式体成员只不过是句法糖public string GetUserId() => GetUserId(Context);public string GetUserId() { return GetUserId(Context); }
0赞 lidqy 10/6/2023
@knittl,我从您想要从其他几个变量中创建一个键的情况下知道这种“模式”,并且在该类中,您还有一个 Key 属性(使用静态 Builder 方法一次)。静态方法对于客户端 API 也很有用,因为客户端 API 本身需要构建这样的键,并将它们与拥有类的 Key 属性进行比较。

答:

1赞 Mark Seemann 10/6/2023 #1

这是一种设计模式吗?这不是一个经典的GoF,但总的来说,这只是部分应用程序,这是许多函数式编程语言的一个众所周知的特性。

在 genreal 中,您可以将任何具有 type 类型的过程视为(如果删除关键字)具有此方法的单方法接口的实现public static string GetUserId(IDataUIContext context)static

public interface IMyInteface
{
    string GetUserId(IDataUIContext context)
}

对应于 .如果您随后定义了一个关闭输入 () 的 lambda 表达式,那么您本质上就拥有了一个值。简而言之,这是部分应用。Func<IDataUIContext, string>IDataUIContextstring

对象只是闭包,因此可以有效地将该方法视为函数或对象。GetUserId

1赞 T.S. 10/6/2023 #2

现在,我只能想到一种类似于您拥有的代理设计模式。

如果您需要将对象呈现为接口,但您的功能实现只有静态访问权限,则可以创建一个代理,例如

public static class Functionality  // may be in the different assembly
{
    public static string MethodA(IDataUIContext context)
    {
        // do something
    }
}

public interface IProxy
{
    string MethodA(IDataUIContext context);
}

public class Proxy : IProxy
{
    public string MethodA(IDataUIContext context) => Functionality.MethodA(context);
}

这不是经典 Go4 代理模式的表示,而是一种变体

这种情况的延续可能是

public class Proxy2 : IProxy
{
    public string MethodA(IDataUIContext context) => AnotheFunctionality.ADifferentMethod(context);
}