当前位置: 移动技术网 > IT编程>软件设计>设计模式 > C#面试分享:单例模式

C#面试分享:单例模式

2018年09月03日  | 移动技术网IT编程  | 我要评论

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

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网