博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

C#面向对象设计模式纵横谈:Singleton

Posted on 2008-02-16 18:04  夏虫  阅读(218)  评论(0编辑  收藏  举报
 

模式分类:

1. 目的分类

创建型(creatinal)

机构型(structural):类与对象间的组合,避免继承的耦合

行为型(behavioral):类与对象交互中的职责分配,组件间的交互,隔离变化

2. 范围分类

类模式处理类与子类的静态关系

对象模式处理对象间的动态关系

单件模式:

1.动机(tivation)

在软件系统中,经常有这样一些特殊的类,必须保证它们在系统中只存在一个实例,才能确保它们的逻辑正确性、以及良好的效率。

如何绕过常规的构造器,提供一种机制来保证一个类只有一个实例?

这应该是类设计者的责任,而不是使用者的责任

   2.意图(Intent)保证一个类仅有一个实例,并提供一个该实例的全局访问点

    ——《设计模式》GOF

3. 结构



4. 单线程Singleton模式的几个要点

Singleton模式中的实例构造器可以设置为protected以允许子类派生。

Singleton模式一般不要支持ICloneable接口,因为这可能会导致多个对象实例,与Singleton模式的初衷违背。

Singleton模式一般不要支持序列化,因为这也有可能导致多个对象实例,同样与Singleton模式的初衷违背。

Singletom模式只考虑到了对象创建的管理,没有考虑对象销毁的管理。就支持垃圾回收的平台和对象的开销来讲,我们一般没有必要对其销毁进行特殊的管理。

不能应对多线程环境:在多线程环境下,如直接使用传统Singleton模式仍然有可能得到Singleton类的多个实例对象
单线程Code:

class ServeChannel
    {
        private static ServeChannel FInstance;
        private ServeChannel() { }
        public static ServeChannel Instance//如果有参数时,则不能用属性而应改为函数
        {
            get {
                if (FInstance == null) {//此实现导致无法多线程
                    FInstance = new ServeChannel();
                }
                return FInstance;
            }
        }
    }
test{
  
ServeChannel t = ServeChannel.Instance;
}

多线程Code:1。传统实现,C#下实现

class ServeChannel
    {
        private static volatile ServeChannel FInstance; //不允许编译器对实现代码顺序微调
        private static object FLocker = new object();
        private ServeChannel() { }
        public static ServeChannel Instance
        {
            get {
                if (FInstance == null) {
                    lock (FLocker)
                    {

                        if (FInstance == null)
                            FInstance = new ServeChannel();
                    }
                }
                return FInstance;
            }
        }
    }
test{
  
ServeChannel t = ServeChannel.Instance;
}

这是比较传统的方案而下面的是C#中很经典的的实现,它利用静态构成函数的特点将代码简化,缺点是不支持构造时传参数,但一般的应用中是可以满足的,有人建议在构造后加一个初始化的函数,我认为不会,这方式不是通用的习惯,新手加入是很容易漏掉。

class ServeChannel
    {
        public static readonly ServeChannel Instance = new ServeChannel();
        private ServeChannel() { }
    }

此实现相当于:

class ServeChannel
    {
        public static readonly ServeChannel Instance;

        static ServeChannel()//保证了多线程安全

        {

           Instance = new ServeChannel();

        }       

        private ServeChannel() { }
    }