面向对象设计的几个基本原则和单例模式

本文是根据刘伟老师《设计模式的艺术》一书和网上资料整理而成,仅供学习交流之用。

一 设计原则
1 单一职责原则:一个类只负责一个功能领域中的相应职责,或者说一个类只有一个引起它变化的原因,简单来说就是一个类不能承担太多的职责。

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

3 里氏代换:所有引用基类的地方必须能透明的使用其子类的对象。在软件中将一个对象替换成它的之类对象不会产生异常,但是反过来不成立。例如:小明喜欢动物,那小明一定喜欢狗,但是小明喜欢狗却不一定喜欢所有动物。

4 依赖倒转:抽象不应依赖于细节,细节应当依赖于抽象。即:要针对接口编程,而不是针对实现编程。

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

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

7 迪米特法则:一个软件应该尽可能的减少与其他实体发生互相作用。

二 软件设计模式

1) 单例模式
确保一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。该类称为单例类,它提供全局的访问方法。比如操作系统只能启动一个任务管理器。

C++单例模式

class CSingleton
{
private:
    CSington(){} // 构造函数是私有的
    static CSingleton * m_pInstance;
public:
    static CSingleton * GetInstance(){
        if(m_pInstance == NULL) {
            m_pInstance = new CSingletion();
        }
        return m_pInstance;
    }
}

用户访问唯一实例的方法只有GetInstance()成员函数,因为构造函数是私有的。GetInstance()是懒惰实例化,即它的返回值是当这个函数首次被访问的时候被创建的。
上面的代码存在两个问题:
1 m_pInstance指向的空间什么时候释放呢?
2 更严重的问题是,该实例的析构函数什么时候执行?

有两种方法可以解决上述问题:
1 程序结束的时候调用GetInstance(),并对返回的指针调用delete操作,但是这样容易出错,难以保证delete后不再调用GetInstance()函数。
2 程序结束的时候,系统会自动析构所有的全局变量,也会析构所有的静态成员函数。所以在单例类中定义一个静态成员变量,它的唯一工作就是析构单例类的实例。代码如下:

class CSingleton()
{
private:
    CSingleton():{}
    static CSingleton * m_pInstance;

    class CGarbo{
    public:
        ~CGarbo(){  // 假如要在类的外部访问该内嵌类,需要外围类::内嵌类
            if(CSingleton::m_pInstance){  // 注意内嵌类的使用格式
                delete CSingleton::m_pInstance;
            }
        }

    }

public:
    static CSingleton * GetInstance(){
        if(CSingleton::m_pInstance == NULL) {
            m_pInstance = new CSingleton();
        }
        return m_instance;
    }
}

将CGarbo定义为私有的,就是防止在其他地方滥用。

你可能感兴趣的:(软件设计模式)