经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » Java相关 » 设计模式 » 查看文章
C#面试分享:单例模式
来源:cnblogs  作者:ArthurRen  时间:2018/9/25 20:18:49  对本文有异议

C#面试分享:单例模式

提问1:请给出单例模式的实现:

答:

  1. public class Animal
  2. {
  3. private static Animal _instance = null;
  4. private static readonly object _lock = new object();
  5. public static Animal Instance
  6. {
  7. get
  8. {
  9. if (_instance == null)
  10. {
  11. lock (_lock)
  12. {
  13. if (_instance == null)
  14. {
  15. _instance = new Animal();
  16. }
  17. }
  18. }
  19. return _instance;
  20. }
  21. }
  22. public string Name { get; set; } = "Animal"
  23. private Animal() {}
  24. public void Print()
  25. {
  26. Console.WriteLine("i am " + Name);
  27. }
  28. }

提问2:继承会破坏单例模式吗?

分析:

说实话,当时这个问题把我给问懵了,没有想明白面试官想考察什么。

下面参考《Head First 设计模式》一书的相关问题,来做一些分析:

首先,就上文的代码而言,子类可以继承 Animal 吗?

答案显然是不能的,因为Animal的构造函数是私有(private)的。为了不破坏单例模式"唯一实例,全局访问点"这两个约束条件,我们把构造器改为 protected ,这样子类就能顺利继承Animal了。

第二点,我们假定所有的子类也是单例的,所以每个子类都应该实现 Instance 这么一个全局访问点,以下代码实现了继承自 Animal 的子类 Cat 单例模式:

  1. public class Cat : Animal
  2. {
  3. private static Cat _instance = null;
  4. private static readonly object _lock = new object();
  5. public new static Cat Instance
  6. {
  7. get
  8. {
  9. if (_instance == null)
  10. {
  11. lock (_lock)
  12. {
  13. if (_instance == null)
  14. {
  15. _instance = new Cat();
  16. }
  17. }
  18. }
  19. return _instance;
  20. }
  21. }
  22. protected Cat()
  23. {
  24. Name = "cat";
  25. }
  26. }

测试:

  1. Animal animal = Animal.Instance;
  2. Animal cat = Cat.Instance;
  3. animal.Print();
  4. cat.Print();

打印结果:

  1. i am animal
  2. i am animal

这种结果显然是有问题的,原因就在于子类 Cat 的 Instance 是用 new 修饰的,cat对象调用的Instance属性其实还是父类 Animal 的Instance属性。

解决方法就是在父类中实现“注册器”,提供父类及其所有子类的“全局访问点”,以下就是修改后的父类 Animal 代码:

  1. public class Animal
  2. {
  3. private static readonly IDictionary<Type, Animal> _dictionary = new ConcurrentDictionary<Type, Animal>();
  4. static Animal()
  5. {
  6. _dictionary.Add(typeof(Animal), new Animal());
  7. }
  8. public static T GetInstance<T>() where T : Animal
  9. {
  10. var type = typeof(T);
  11. if (!_dictionary.ContainsKey(type))
  12. {
  13. var constructors = type.GetConstructors(BindingFlags.Instance | BindingFlags.NonPublic);
  14. var constructor = constructors[0];
  15. var animal = constructor.Invoke(null) as Animal;
  16. _dictionary.Add(type, animal);
  17. return animal as T;
  18. }
  19. return _dictionary[type] as T;
  20. }
  21. public string Name { get; protected set; }
  22. protected Animal()
  23. {
  24. Name = "Animal";
  25. }
  26. public void Print()
  27. {
  28. Console.WriteLine("i am " + Name);
  29. }
  30. }

Cat代码

  1. public class Cat : Animal
  2. {
  3. protected Cat()
  4. {
  5. Name = "Cat";
  6. }
  7. }

测试:

  1. static void Main(string[] args)
  2. {
  3. Animal animal = Animal.GetInstance<Animal>();
  4. Animal cat = Animal.GetInstance<Cat>();
  5. animal.Print();
  6. cat.Print();
  7. Console.ReadLine();
  8. }

输出:

  1. i am Animal
  2. i am Cat
 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号