答:
public class Animal{ private static Animal _instance = null; private static readonly object _lock = new object(); public static Animal Instance { get { if (_instance == null) { lock (_lock) { if (_instance == null) { _instance = new Animal(); } } } return _instance; } } public string Name { get; set; } = "Animal" private Animal() {} public void Print() { Console.WriteLine("i am " + Name); }}
public class Animal
{
private static Animal _instance = null;
private static readonly object _lock = new object();
public static Animal Instance
get
if (_instance == null)
lock (_lock)
_instance = new Animal();
}
return _instance;
public string Name { get; set; } = "Animal"
private Animal() {}
public void Print()
Console.WriteLine("i am " + Name);
分析:
说实话,当时这个问题把我给问懵了,没有想明白面试官想考察什么。
下面参考《Head First 设计模式》一书的相关问题,来做一些分析:
首先,就上文的代码而言,子类可以继承 Animal 吗?
答案显然是不能的,因为Animal的构造函数是私有(private)的。为了不破坏单例模式"唯一实例,全局访问点"这两个约束条件,我们把构造器改为 protected ,这样子类就能顺利继承Animal了。
第二点,我们假定所有的子类也是单例的,所以每个子类都应该实现 Instance 这么一个全局访问点,以下代码实现了继承自 Animal 的子类 Cat 单例模式:
public class Cat : Animal{ private static Cat _instance = null; private static readonly object _lock = new object(); public new static Cat Instance { get { if (_instance == null) { lock (_lock) { if (_instance == null) { _instance = new Cat(); } } } return _instance; } } protected Cat() { Name = "cat"; }}
public class Cat : Animal
private static Cat _instance = null;
public new static Cat Instance
_instance = new Cat();
protected Cat()
Name = "cat";
测试:
Animal animal = Animal.Instance;Animal cat = Cat.Instance;animal.Print();cat.Print();
Animal animal = Animal.Instance;
Animal cat = Cat.Instance;
animal.Print();
cat.Print();
打印结果:
i am animali am animal
i am animal
这种结果显然是有问题的,原因就在于子类 Cat 的 Instance 是用 new 修饰的,cat对象调用的Instance属性其实还是父类 Animal 的Instance属性。
解决方法就是在父类中实现“注册器”,提供父类及其所有子类的“全局访问点”,以下就是修改后的父类 Animal 代码:
public class Animal{ private static readonly IDictionary<Type, Animal> _dictionary = new ConcurrentDictionary<Type, Animal>(); static Animal() { _dictionary.Add(typeof(Animal), new Animal()); } public static T GetInstance<T>() where T : Animal { var type = typeof(T); if (!_dictionary.ContainsKey(type)) { var constructors = type.GetConstructors(BindingFlags.Instance | BindingFlags.NonPublic); var constructor = constructors[0]; var animal = constructor.Invoke(null) as Animal; _dictionary.Add(type, animal); return animal as T; } return _dictionary[type] as T; } public string Name { get; protected set; } protected Animal() { Name = "Animal"; } public void Print() { Console.WriteLine("i am " + Name); }}
private static readonly IDictionary<Type, Animal> _dictionary = new ConcurrentDictionary<Type, Animal>();
static Animal()
_dictionary.Add(typeof(Animal), new Animal());
public static T GetInstance<T>() where T : Animal
var type = typeof(T);
if (!_dictionary.ContainsKey(type))
var constructors = type.GetConstructors(BindingFlags.Instance | BindingFlags.NonPublic);
var constructor = constructors[0];
var animal = constructor.Invoke(null) as Animal;
_dictionary.Add(type, animal);
return animal as T;
return _dictionary[type] as T;
public string Name { get; protected set; }
protected Animal()
Name = "Animal";
Cat代码
public class Cat : Animal{ protected Cat() { Name = "Cat"; }}
Name = "Cat";
static void Main(string[] args){ Animal animal = Animal.GetInstance<Animal>(); Animal cat = Animal.GetInstance<Cat>(); animal.Print(); cat.Print(); Console.ReadLine();}
static void Main(string[] args)
Animal animal = Animal.GetInstance<Animal>();
Animal cat = Animal.GetInstance<Cat>();
Console.ReadLine();
输出:
i am Animali am Cat
i am Animal
i am Cat
本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728