2016年2月

设计模式--单例设计模式

单例模式的动机

有的时候我们需要控制某个类型的实例数量,使其有且只有一个。比如后台服务进程统计数、比如windows任务管理器,这样当这个类型的实例创建成功后,其他所有的操作都是基于这个唯一实例。

单例模式的概述和实现

单例模式

确保某个类只有一个实例,而且自行实例化并向整个系统提供这个实例,这个类称为单例类,它提供全局访问的方法。单例模式是一种对象创建型模式

经典的实现方法

class TaskManager{
    private static TaskManager tm= null;
    private TaskManager(){...}                //构造函数私有
    public void displayProcesses(){...}       //普通方法
    public void displayServices(){...}        //普通方法:显示服务

    public static TaskManager getInstance(){
        if(tm == null){
            tm = new TaskManager();
        }
        return tm;
    }    
    ...
}

以上是经典的实现方法,通过将构造函数私有,提供一个静态的方法来提供这个静态实例变量,但以上的方法存在问题,在有多个进程访问到if(TaskManager == null),如果此时构造函数还没有完成创建这个类型,那么这个条件就会为true,多个进程就会进入执行构造这个实例。
解决方法通常有两个:饿汉式单利类懒汉式单例类

//饿汉式单例类
class TaskManager{
    private static TaskManager tm = new TaskManager();
    private TaskManager(){...}
    
    public static TaskManager getInstance(){
        return tm;
    }
}

以上可以看出饿汉式单例类在类加载时,静态变量tm就会被创建,此时类的私有构造函数被调用,单例模式的唯一实例被创建。保证了对象的唯一性。

//懒汉式单例类通过线程的锁定来保证
class TaskManager{
    private static TaskManager tm = null;
    private TaskManager(){...}

    public static TaskManager getInstance(){
        if(tm == null){
            lock(typeof(tm)){
                if(tm == null )
                    tm = new TaskManager();
            }
        }
    }
}

懒汉式单例在需要使用到的时候才进行创建,比较懒。
结合C#单例模式经常如下使用(内容来自模式工程化实现及扩展):

    sealed class TaskManager{
        TaskManager(){...}    //默认为private
        public static readonly TaskManager tm = new TaskManager();
    }

以上为在C#中如何使用单例模式,其中tm被定义为静态的只读属性
有两个常用的场景会破坏这种单例模式的稳定性

  • 不要实现ICloneable接口或者继承自相关的子类,否则客户程序可以跳过已经隐藏起来的类构造函数。

//C#会导致变质的场景
public class BaseEntity:system.ICloneable
{
    public object Clone(){
        return this.MemberwiseClone();    //采用这种方式可以克隆
    }
}

public class TaskManager : BaseEntity
{
    ...
}
  • 严防序列化。对于远程访问,往往需要把复杂的对象进行序列化后进行传递,但是序列化本身会导致单例模式特性的破坏,因为序列化实际上完成了但是对象的复制和重现,所以不要对期望具有单例模式特性的类型声明SerializableAttribute属性。

总结

单例模式作为一种目标明确、结构简单、容易理解的设计模式,在许多应用软件中都得以广泛应用。
优点

  • 提供了对唯一实例的受控访问

  • 由于只有一个对象,因此可以节约系统资源

  • 允许可变数目的实例。基于单例模式,开发人员可以进行扩展,使用与控制单例对象相似的方法来获得指定个数的实例对象,既节省了系统资源,又解决了由于单例模式共享过多有损失性能的问题。

缺点

  • 没有抽象层,扩展很困难

  • 单例类职责过重,一定程度违背了单一职责原则

  • 现在C#java语言的运行环境都提供了自动垃圾回收技术,因此实例化的共享对象不被利用,可能会被系统回收

总结起来,就是当系统只需要一个实力对象或者调用类的单个实例只允许使用一个公共访问点,此时可以考虑使用单例模式,宁缺毋滥。

《设计模式的艺术》读书笔记

废话

俗话说的好:万事开头难,一直懒得动笔去记录东西,这一个周来主要看了MVVM light Toolkit方面的相关,将Laurent Bugnion的博客和视频都看了几遍,不得不说,真爽,以前许多不理解的概念和方法现在都相当的清楚,在这两天看看这本书读烦了可以换着写写那个。
最近一共有了三本有关设计模式的书,最先看的是《设计模式的艺术--软件开发人员内功修炼之道》,还有另外两本是《Head First 设计模式》和《模式--工程化实现及扩展》,我觉得《设计模式的艺术》还是写的很通俗易懂,按照问题提出、解决、改进、总结的方式来介绍每个设计模式。所以我的记录也就大体按照这个方式来记录,同时如果其他两本书有比较的话也拿到这里来,所以,这一个系列不能是一次性完成的,需要多次改进吧。废话了不少,正式开始。

设计模式概述

从什么时候忘了,听到设计模式就是一种高大上的感觉,如果你不用设计模式来设计你的软件,好像你的软件就是不能用一样。其实哪是这样,设计模式不过是使你的软件有弹性,更能应对需求的变化,使代码重用性更强。
设计模式始于建筑行业,GOF四个人整理收集23种设计模式,出版《设计模式:可复用面向对象软件的基础》一书,标志着设计模式正式成为面向对象软件工程的一个重要研究分支。
设计模式是什么?

设计模式是一套被反复使用的、多数人直销的、经过分类编目的、代码设计经验的总结,使用设计模式是为了可重用代码、让代码更容易被他人理解并且保证代码可靠性。

设计模式一般包含模式名称、问题、目的、解决方案、效果等组成要素。根据它们的用途,设计模式可分为创建型、结构性和行为型,其中创建型描述如何创建对象,结构性主要描述如何实现类或对象的耦合,行为型主要用于描述类或对象怎样交互及怎样分配职责。
反正设计模式很有用,你跟着学就对了。
《设计模式沉思录》中一句话:模式从不保证任何东西,它不保证你一定能够做出可复用的软件,提高你的生产率,更不能保证世界和平。模式并不能替代人来完成软件系统的构造,它们只不过会给那些缺乏经验但具备才能和创造力的人带来希望。

面向对象设计原则概述

  1. 单一职责原则

一个类只负责一个功能领域中的相应职责,或者可以定义为:就一个类而言,应该只有一个引起它变化的原因。

  1. 开闭原则

一个软件实体应当对扩展开放,对修改关闭。即软件实体应尽量在不修改原有代码的情况下进行扩展。

可以为系统定义一个稳定的抽象层,而将不同的实现行为移至具体的实现层中实现。即通过抽象类、接口等机制定义抽象层,然后通过具体类进行扩展,现在我终于理解了抽象类和接口的作用,在设计模式中是最有用的

  1. 里氏替换原则

所有引用基类(父类)的地方必须能透明的使用其子类的对象。

里氏替换原则是实现开闭原则的重要方式之一,由于使用基类对象的地方都可以使用其子类对象,因此在程序中尽量使用基类类型来进行定义,而在运行时再确定其子类类型,用子类类型来替换父类对象。

  1. 依赖倒置原则

抽象不应该依赖于细节,细节应该依赖于抽象。换言之,要针对接口编程,而不应该针对实现编程。

依赖倒置原则要求在程序代码中传递参数或者在关联关系时,尽量引用层次高的抽象层类,即使用接口和抽象类进行变量类型声明、参数类型声明、方法返回值类型声明,以及数据类型的转换等,而不要使用具体类来做这些事应。

  1. 接口隔离原则

使用多个专门的接口,而不使用单一的总接口,即客户端不应该依赖那些它不需要的接口。

根据接口隔离原则,当一个接口太大时,需要将它分割成一些更细小的接口,使用该接口的客户端仅需要知道与之相连的方法即可。每一个接口承担相对独立的角色。

  1. 合成复用原则

尽量使用对象组合,而不是继承来达到复用的目的。

这里那个讲的很棒,有个小例子

  1. 迪米特法则

一个软件实体应当尽可能少的与其他实体发生相互作用,即不要和陌生人说话

其朋友包括:

  • 当前对象本身

  • 以参数形式传入当前方法中的对象

  • 当前对象的成员对象

  • 如果当前对象的成员对象是一个集合,那么集合中的元素都是朋友

  • 当前对象所创建的对象


总结

以前都是了解一点点,这次努力做成一个系列,方便以后查阅。下次文章关于单例模式。