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