C# 在抽象工厂方法中调用单例类

C# 在抽象工厂方法中调用单例类,c#,.net,design-patterns,c#-4.0,C#,.net,Design Patterns,C# 4.0,我有一个抽象工厂方法的类,如下所示: public abstract class OpClass { public abstract IHou OperationInvoke(string opClass); } public class FactoryClass : OpClass { public override IHou OperationInvoke(string opClass) {

我有一个抽象工厂方法的类,如下所示:

 public abstract class OpClass
    {
        public abstract IHou OperationInvoke(string opClass);
    }

    public class FactoryClass : OpClass
    {
        public override IHou OperationInvoke(string opClass)
        {
            if(opClass == "T")
            {
                //new Treasure();
            }

        }
    }
具体的“宝藏”类是这样的:

 public interface IHou
    {
        void Operation(Player p, List<Player> lstPlayers);
    }

public sealed class Treasure : IHou
    {
        private static Treasure instance = null;
        private static readonly object padlock = new object();

        Treasure()
        {

        }

        public static Treasure Instance
        {
            get
            {
                lock (padlock)
                {
                    if (instance == null)
                    {
                        instance = new Treasure();
                    }
                    return instance;
                }
            }
        }

        public void Operation(Player p, List<Player> lstPlayers)
        {
            p.Points = p.Points + 200;

        }
    }
公共接口IHou
{
作废操作(玩家p,玩家列表);
}
公开密封类珍品:IHou
{
私有静态宝藏实例=null;
私有静态只读对象挂锁=新对象();
宝藏
{
}
公共静态宝藏实例
{
得到
{
锁(挂锁)
{
if(实例==null)
{
实例=新宝藏();
}
返回实例;
}
}
}
公开作废操作(玩家p,玩家列表)
{
p、 点数=p.点数+200;
}
}
在我的主要方法中,我尝试将其称为:

Main()
{
    Player p = //Populate from db;
    List<Player> players = //populate from db 
    OpClass c = new FactoryClass();
    IHou output = c.OperationInvoke("T");
    output.Operation(p, players);
}
Main()
{
Player p=//从数据库填充;
列表播放器=//从数据库填充
OpClass c=新的FactoryClass();
i输出=c.操作声音(“T”);
输出。操作(p,玩家);
}
但是我需要一个“珍宝”类的实例,所以我想把普通的“珍宝”类改成一个单例类

所以,在这个场景中,我如何创建Treasure类的单个实例并同时保留facory模式?如果无法实现,那么如果增加了一些具体的类,比如宝藏、房子、积木等,那么最好的解决方案是什么


编辑:在这里使用工厂模式不合适吗?我的理解是,如果我们有许多类似于此宝藏的具有常见行为的类,并且说再添加一个类“房子”,以不同的方式计算点数,我将允许工厂决定调用哪个实例。

您可以使用Flyweight模式进行实例化,在该模式中,您将实例存储在缓存或字典中,并从工厂返回

借助下面基于泛型的工厂实现,您不需要添加更多的案例,它将基于模板类型T创建类。您可以访问下面的文章链接,以获得相同的实现

public class FlyWeidhtFactory
{
    Dictionary<string,IHou> dic = new Dictionary<string,IHou>();

    public IHou OperationInvoke<T>(string opClass)  where T: IHou 
    {
        Type type = typeof(T);
        string fullname = type.FullName;
        if(!dic.Contains(fullname)
        {
           Object obj = Activator.CreateInstance(type);
           dic[fullname] = (T)obj;  
           //no need of more cases 
        }
        return dic[opClass]; 
    }
}
公共类FlyWeidhtFactory
{
Dictionary dic=新字典();
公共IHou操作VOKE(字符串opClass),其中T:IHou
{
类型=类型(T);
字符串fullname=type.fullname;
如果(!dic.Contains)(全名)
{
Object obj=Activator.CreateInstance(类型);
dic[全名]=(T)obj;
//不需要更多的案例
}
返回dic[opClass];
}
}
模式确保您将要创建许多对象,并且通过上述实现,您可以确保只创建一个类的实例。无需使用单例模式

使您的混凝土类
内部密封
,以便它在程序集外部不可见

以上只是根据您的问题提出的建议

适用于工厂和flyweight的物品:


只需返回工厂中的singleton实例即可

你的工厂有责任知道如何“制造”。在宝藏的情况下,只有一个实例,所以工厂只返回该实例

基于键返回共享或非共享实例的事实使您的代码类似于flyweight。如果没有其他代码需要在工厂外创建宝藏,则您不需要单例。您可以通过工厂强制实例化类,使它们成为工厂的嵌套类


因此,请使用私有构造函数将其设为工厂的嵌套类。或者将其设为私有嵌套类,并使用工厂方法返回抽象基。

注意,如果
实例
为null,则还应检查锁外,否则每次都必须锁定,即使有实例,这意味着线程将具有为了争夺一个锁。一个外部检查,一个内部检查。你能使用DI容器吗?像这样的事情通常是DI容器的责任。任何DI容器都可以开箱即用地管理它。你不需要工厂模式。当初始化一个实例所需的参数数量很大并且初始化不容易时,使用工厂模式rd或在初始化和使用实例之间需要一些额外的逻辑时。您的
宝藏
甚至不接受单个参数。。。