Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/iphone/42.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 子类中的强制单例模式_C#_Design Patterns - Fatal编程技术网

C# 子类中的强制单例模式

C# 子类中的强制单例模式,c#,design-patterns,C#,Design Patterns,我想强制子类实现singleton模式 我最初想在父类中有一个抽象静态属性,但后来发现这没有意义(抽象需要和实例) 接下来,我考虑使用一个具有静态属性的接口,但这也没有意义(接口也需要一个实例) 这是可能的,还是我应该放弃这一思路,实现一个抽象工厂?尝试使用IOC容器。大多数好的IOC容器都支持使用单例模式,而无需自己实现它(即:spring框架)——我喜欢这比强制使用静态GetInstance()方法要好 此外,java中不可能,它将在C++中使用模板。< p>我将定义一个密封类,它从传递给构

我想强制子类实现singleton模式

我最初想在父类中有一个抽象静态属性,但后来发现这没有意义(抽象需要和实例)

接下来,我考虑使用一个具有静态属性的接口,但这也没有意义(接口也需要一个实例)


这是可能的,还是我应该放弃这一思路,实现一个抽象工厂?

尝试使用IOC容器。大多数好的IOC容器都支持使用单例模式,而无需自己实现它(即:spring框架)——我喜欢这比强制使用静态GetInstance()方法要好

此外,java中不可能,它将在C++中使用模板。

< p>我将定义一个密封类,它从传递给构造函数的委托获得它的功能,类似于:

public sealed class Shape {
  private readonly Func<int> areaFunction;

  public Shape(Func<int> areaFunction) { this.areaFunction = areaFunction; }

  public int Area { get { return areaFunction(); } }
}
公共密封类形状{
专用只读功能区功能;
公共形状(Func areaFunction){this.areaFunction=areaFunction;}
公共int区域{get{return areaFunction();}}
}
这个例子没有多大意义,它只是说明了一种模式。 这种模式不能在任何地方使用,但有时会有所帮助

此外,它还可以扩展以暴露有限数量的静态场:

public sealed class Shape {
  private readonly Func<int> areaFunction;

  private Shape(Func<int> areaFunction) { this.areaFunction = areaFunction; }

  public int Area { get { return areaFunction(); } }

  public static readonly Shape Rectangle = new Shape(() => 2 * 3);
  public static readonly Shape Circle = new Shape(() => Math.Pi * 3 * 3);
}
公共密封类形状{
专用只读功能区功能;
私有形状(Func areaFunction){this.areaFunction=areaFunction;}
公共int区域{get{return areaFunction();}}
公共静态只读形状矩形=新形状(()=>2*3);
公共静态只读形状圆=新形状(()=>Math.Pi*3*3);
}

为什么?如果有人想使用您类的子类的多个实例,他们可能有充分的理由这样做


如果你想为你的类的子类做一些只应该做一次的事情(为什么,我不知道,但你可能有理由这么做),在基类中使用字典。

老实说,我认为你最好在这里使用工厂模式。或者使用Brian Dilley推荐的IoC工具。在c#world中有负载,这里是最流行的负载:Castle/windsor、StructureMap、Unity和Ninject

除此之外,我认为尝试实际解决你的问题会很有趣!看看这个:

//abstract, no one can create me
public abstract class Room
{
    protected static List<Room> createdRooms = new List<Room>();
    private static List<Type> createdTypes = new List<Type>();

    //bass class ctor will throw an exception if the type is already created
    protected Room(Type RoomCreated)
    {
        //confirm this type has not been created already
        if (createdTypes.Exists(x => x == RoomCreated))
            throw new Exception("Can't create another type of " + RoomCreated.Name);
        createdTypes.Add(RoomCreated);
    }

    //returns a room if a room of its type is already created
    protected static T GetAlreadyCreatedRoom<T>() where T : Room
    {
        return createdRooms.Find(x => x.GetType() == typeof (T)) as T;
    }
}

public class WickedRoom : Room
{
    //private ctor, no-one can create me, but me!
    private WickedRoom()
        : base(typeof(WickedRoom)) //forced to call down to the abstract ctor
    {

    }

    public static WickedRoom GetWickedRoom()
    {
        WickedRoom result = GetAlreadyCreatedRoom<WickedRoom>();

        if (result == null)
        {
            //create a room, and store
            result = new WickedRoom();
            createdRooms.Add(result);
        }

        return result;
    }
}

public class NaughtyRoom :Room
{
    //allows direct creation but forced to call down anyway
    public NaughtyRoom() : base(typeof(NaughtyRoom))
    {

    }
}

internal class Program
{
    private static void Main(string[] args)
    {
        //Can't do this as wont compile
        //WickedRoom room = new WickedRoom();

        //have to use the factory method:
        WickedRoom room1 = WickedRoom.GetWickedRoom();
        WickedRoom room2 = WickedRoom.GetWickedRoom();

        //actually the same room
        Debug.Assert(room1 == room2);

        NaughtyRoom room3 = new NaughtyRoom(); //Allowed, just this once!
        NaughtyRoom room4 = new NaughtyRoom(); //exception, can't create another
    }
}
//抽象,没有人能创造我
公共抽象教室
{
受保护的静态列表createdRooms=新列表();
私有静态列表createdTypes=new List();
//如果类型已创建,bass类ctor将引发异常
受保护的房间(类型RoomCreated)
{
//确认尚未创建此类型
如果(createdTypes.Exists(x=>x==RoomCreated))
抛出新异常(“无法创建其他类型的”+RoomCreated.Name);
createdTypes.Add(RoomCreated);
}
//如果已创建其类型的文件室,则返回文件室
受保护的静态T GetAlreadyCreatedRoom(),其中T:Room
{
返回createdRooms.Find(x=>x.GetType()==typeof(T))作为T;
}
}
公共教室:房间
{
//二等兵,除了我,没有人能创造我!
私人WickedRoom()
:base(typeof(WickedRoom))//强制调用抽象构造函数
{
}
公共静态WickedRoom GetWickedRoom()
{
WickedRoom结果=GetAlreadyCreatedRoom();
如果(结果==null)
{
//创建一个房间,并存储
结果=新WickedRoom();
createdRooms.Add(结果);
}
返回结果;
}
}
公共教室:房间
{
//允许直接创建,但无论如何都必须取消
public noutyroom():基(typeof(noutyroom))
{
}
}
内部课程计划
{
私有静态void Main(字符串[]args)
{
//无法执行此操作,因为无法编译
//WickedRoom房间=新WickedRoom();
//必须使用工厂方法:
WickedRoom room1=WickedRoom.GetWickedRoom();
WickedRoom room2=WickedRoom.GetWickedRoom();
//实际上是同一个房间
Assert(room1==room2);
NoutyRoom room3=新的NoutyRoom();//允许,仅此一次!
NouttyRoom room4=新的NouttyRoom();//异常,无法创建另一个
}
}

WickedRoom是一个正确实现系统的类。任何客户端代码都将获得singleton WickedRoom类。NouttyRoom不能正确实现系统,但即使是这个类也不能实例化两次。第二次实例化会导致异常。

请重新考虑。您不想在这里使用单例。您正在为从您的类派生的用户提供一些功能。那很好。但你也在口述一种特定的方式,它必须始终被使用,而且绝对没有理由。那不好

大多数时候只实例化这个类的一个对象可能是有意义的,但在这种情况下,只需实例化一次对象即可。你不太可能在没有注意到的情况下意外地实例化一打对象。 此外,您如何判断拥有两个实例永远不会有用?即使现在,我也能想到几个案例

单元测试:您可能希望每个测试都实例化这个对象,然后再将其拆下。由于大多数人都有不止一个单元测试,所以您需要多次实例化它

或者您可能在某个时候决定在游戏中使用多个相同/相似的关卡,这意味着创建多个实例

单身汉给你两样东西:

  • 保证不会实例化超过一个对象实例,以及
  • 对该实例的全局访问
如果你不需要这两样东西,有更好的选择。 你当然不需要一个全球性的
public abstract class SuperClass {
private static SuperClass superClassInst = null;

public SuperClass () {
    if(superClassInst == null) {
        superClassInst = this;
    }
    else {
        throw new Error("You can only create one instance of this SuperClass or its sub-classes");
    }
}

public final static SuperClass getInstance() {
    return superClassInst;
}

public abstract int Method1();
public abstract void Method2();
}