C#面试分享:单例模式
程序员文章站
2022-05-04 14:01:59
C 面试分享:单例模式 提问1:请给出单例模式的实现: 答: 提问2:继承会破坏单例模式吗? 分析: 说实话,当时这个问题把我给问懵了,没有想明白面试官想考察什么。 下面参考《Head First 设计模式》一书的相关问题,来做一些分析: 首先,就上文的代码而言,子类可以继承 Animal 吗? 答 ......
c#面试分享:单例模式
提问1:请给出单例模式的实现:
答:
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); } }
提问2:继承会破坏单例模式吗?
分析:
说实话,当时这个问题把我给问懵了,没有想明白面试官想考察什么。
下面参考《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"; } }
测试:
animal animal = animal.instance; animal cat = cat.instance; animal.print(); cat.print();
打印结果:
i 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); } }
cat代码
public class cat : animal { protected cat() { name = "cat"; } }
测试:
static void main(string[] args) { animal animal = animal.getinstance<animal>(); animal cat = animal.getinstance<cat>(); animal.print(); cat.print(); console.readline(); }
输出:
i am animal i am cat