【问题标题】:Design pattern: singleton with setting capabilities设计模式:具有设置能力的单例
【发布时间】:2014-02-06 10:29:10
【问题描述】:

对不起标题,我会尽力更好地解释这个问题。 我为我的 log4net 实例创建了一个包装器,我使用以下构造函数实例化了这个记录器:

    public MyLogger(string _dbName)
    {
        dbName = _dbName;
        logger = LoggerConfigurator.AddNamedLogger(dbName);
    }

现在的问题是:这个构造函数在两个不同的类中实例化,所以一些消息日志被打印了两次。 仅当先前的实例不存在时,我才需要创建一个新实例,否则返回该实例。一种单例模式。问题是单例模式不接受参数,所以我没有办法传递_dbName。按照最佳做法,我该如何处理?

【问题讨论】:

  • 为什么不使用 Singleton x = Singleton.GetInstance(params object[] parameters);或创建使用参数集初始化单例的 Init 方法? x.Init(params object[] 参数);
  • 甚至更好 - 使用 IoC 容器!在那里你可以定义,只有一个类型 <T> 的实例应该用于所有依赖于它的类。看看:msdn.microsoft.com/en-us/library/ff648211.aspx

标签: c# design-patterns


【解决方案1】:

如果我理解正确,您正在寻找 Multiton (Multiton pattern on Wikipedia)。它基本上是每个键的单例(这是 Wikipedia 上的 C# 示例):

using System.Collections.Generic;
using System.Collections.Concurrent;

namespace MyApplication 
{
    class FooMultiton 
    {
        private static readonly ConcurrentDictionary<object, FooMultiton> _instances
        = new ConcurrentDictionary<object, FooMultiton>();

        private FooMultiton() {}

        public static FooMultiton GetInstance(object key) 
        {
            _instances.TryAdd(key, new FooMultiton()); // This would of course be new MyLogger(_dbName)
            return _instances[key];
        }
    }
}

【讨论】:

  • 我不这么认为,但很高兴知道。
  • 示例错误,每次调用 GetInstance 都会创建一个 FooMultiton 的实例!我使用 GetOrAdd 而不是 TryAdd 在 wikipedia 上修复了它。
  • @Guillaume 当然更多的是想法而不是实际实现,并且根据构造函数中发生的情况,它可以更改为 ConcurrentDictionary>
  • 拥有一个单例列表并不是那么有用(对我来说)。我每次只需要一个单例,其参数与 DB 上的给定操作相关
  • 我选择你的作为接受的答案,因为这样(即使我将所有记录器都存储在没有任何实际好处的情况下)在一行log = MyLogger.GetInstance(builder.InitialCatalog); 我可以得到我需要的东西。在其他解决方案中:我首先必须设置静态name 属性,在这一步之后我终于可以得到实例(我认为这个问题真的很容易出错并且样式不好。)所以......
【解决方案2】:

由于不建议给单例的“getHandle”方法一个参数,我想说你需要将dbName 作为单独的静态属性传递,例如

class MyLogger {

private String dbname = String.Empty;

public static String DbName {
    get { return dbname; }
    set { dbname = value; }
}

private static MyLogger mylogger = null;

public static MyLogger Handle {
    get {
        if (logger == null) mylogger = new MyLogger(dbName);
        return mylogger;
    }
}

private MyLogger(String db) {
    // your code
    logger = LoggerConfigurator.AddNamedLogger(db);
}

【讨论】:

    【解决方案3】:
    class MySingleton
    {
        private static MySingleton _instance;
    
        private MySingleton()
        {
        }
        private MySingleton(params object[] parameters)
        {
            // assign parameters
        }
        public static MySingleton Instance
        {
            get
            {
                if (_instance == null)
                {
                    throw new Exception("not created");
                }
                return _instance;
            }
        }
    
        public static void Create(params object[] parameters)
        {
            if (_instance != null)
            {
                return;
            }
    
            _instance = new MySingleton(parameters);
        }
    }
    

    多个线程需要一些同步。

    【讨论】:

      猜你喜欢
      • 2014-06-13
      • 2017-10-12
      • 2010-11-03
      • 2021-07-03
      • 1970-01-01
      相关资源
      最近更新 更多