C# 模式:本地单例与全局单例?

C# 模式:本地单例与全局单例?,c#,design-patterns,naming-conventions,naming,C#,Design Patterns,Naming Conventions,Naming,有一种模式我经常使用,但我不太确定它叫什么。我希望SO社区能帮助我 该模式非常简单,由两部分组成: 基于传入的参数创建对象的工厂方法 由工厂创建的对象 到目前为止,这只是一个标准的“工厂”模式 然而,我要问的问题是,在本例中,父对象维护一组对它曾经创建的每个子对象的引用,保存在字典中。这些引用有时是强引用,有时是弱引用,但它始终可以引用它曾经创建的任何对象 当收到对“新”对象的请求时,父对象首先搜索字典,查看是否已经存在具有所需参数的对象。如果是,则返回该对象;如果不是,则返回一个新对象,并在字

有一种模式我经常使用,但我不太确定它叫什么。我希望SO社区能帮助我

该模式非常简单,由两部分组成:

  • 基于传入的参数创建对象的工厂方法

  • 由工厂创建的对象

  • 到目前为止,这只是一个标准的“工厂”模式

    然而,我要问的问题是,在本例中,父对象维护一组对它曾经创建的每个子对象的引用,保存在字典中。这些引用有时是强引用,有时是弱引用,但它始终可以引用它曾经创建的任何对象

    当收到对“新”对象的请求时,父对象首先搜索字典,查看是否已经存在具有所需参数的对象。如果是,则返回该对象;如果不是,则返回一个新对象,并在字典中存储对新对象的引用

    此模式可防止具有表示相同基础“事物”的重复对象。这在创建的对象相对昂贵的情况下非常有用。当这些对象执行事件处理或消息传递时,它也很有用-表示每个项目一个对象可以防止单个基础源的多个消息/事件

    使用此模式可能还有其他原因,但这正是我发现此模式有用的地方

    我的问题是:这叫什么

    从某种意义上说,每个对象都是一个单独的对象,至少就其包含的数据而言。每一个都是独一无二的。但是,这个类有多个实例,所以它根本不是真正的单例

    用我个人的术语来说,我倾向于将父类称为“全局单例”。然后,我将创建的对象称为“本地单例”。我有时也会说,创建的对象具有“引用相等”,这意味着如果两个变量引用相同的数据(相同的基础项),那么它们各自持有的引用必须是同一个确切的对象,因此是“引用相等”

    但这些是我自己发明的术语,我不确定它们是否好

    这个概念有没有标准术语?如果没有,能否提出一些命名建议

    先谢谢你

    更新#1:

    在Mark Seemans的回复中,他给出了这样的观点:“你所描述的结构本质上是一个DI容器,用作静态服务定位器(我认为它是反模式)。”

    虽然我同意有一些相似之处,而且非常优秀,但我认为这个依赖注入容器/静态服务定位器模式实际上是我所描述的一般模式的一个更狭隘的实现

    在本文描述的模式中,服务(“定位器”类)是静态的,因此需要注入以使其功能具有可变性。在我描述的模式中,服务类根本不需要是静态的。如果需要,可以提供一个静态包装器,但根本不需要成为一个静态类,没有静态类,就不需要依赖注入(在我的例子中,也不使用依赖注入)

    在我的例子中,“服务”要么是一个接口,要么是一个抽象类,但我认为我所描述的模式甚至不需要定义“服务”和“客户端”类。这样做很方便,但如果所有代码都是内部的,那么服务器类可以只是一个“父”类,通过工厂方法控制所有子类的创建,并保持对其所有子类的弱(或可能强)引用。没有注入,没有静态,甚至不需要定义接口或抽象类

    因此,我的模式实际上不是“静态服务定位器”,也不是“依赖注入容器”

    我认为我所描述的模式比这要广泛得多。因此问题依然存在:有人能确定这种方法的名称吗?如果没有,那么任何关于这个的想法都是欢迎的

    更新#2:

    好的,看起来是GoF“Flyweight”设计图案。以下是一些关于它的文章:

    使用接口或抽象类的“flyweight工厂”(服务器)和“flyweight对象”(客户端)方法在an中得到了很好的解释,这正是我在这里试图解释的

    中给出的Java示例是我在内部实现此方法时采用的方法

    Flyweight模式似乎也非常类似于和的概念

    稍微远一点的是一个,它的不同之处在于它倾向于预创建和/或保留创建的对象,甚至超出其使用范围,以避免创建和设置时间

    非常感谢大家,特别感谢加布里埃尔

    然而,如果有人对如何称呼这些子对象有任何想法,我愿意接受建议。“内部映射的子对象”?“可回收物品”?欢迎所有建议

    更新#3:

    这是对特鲁威尔的回复,他写道:


    这是一个反模式的原因是您没有使用DI。任何使用单例工厂(也称为服务定位器)的类都与工厂的实现紧密耦合。与new关键字一样,consumer类对工厂提供的服务的依赖关系不明确(不能从公共接口确定)。当您试图孤立地对使用者类进行单元测试,并且需要模拟/伪造/存根服务实现时,就会遇到麻烦。另一个难点是,如果您需要多个缓存(例如,每个会话或线程一个缓存)

    下面的Mark说我在使用DI/IoC。马克称之为反模式

    TrueWill同意Mark的评估,即我正在使用DI