最近在看《Head First 设计模式》,感觉挺有意思的,本系列的多数内容也是引自于它。
不过会加入一些自己的理解,代码肯定也是敲自己的啦~
了解设计模式之前,首先我们得明确一点:贯穿在软件开发过程中不变的真理只有一条,那就是“改变”。很多设计模式的产生正是为了使我们的软件不至于在不断的迭代与改变中变成一堆垃圾。当我们写一些代码量比较少,无需后期反复迭代的测试性的程序时可能无法体会到设计模式给我们带来的好处,但是相信我,在平时写小程序时培养一些设计模式的习惯,对于将来做产品级代码会带来潜移默化的好处。
其实呢,我们在日常编程时或多或少都在使用着设计模式,只是我们没有意识它有那么一个“官方”的名称罢了,
比如下面的“策略模式”就是这样:
策略模式:定义算法族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化独立于使用算法的客户。
UML图:
太官方了哈,还是写个测试代码看看:
为了鲜明,我们只保留主要代码,大致意思出来就行~
假设现在有个Person抽象基类,其纯虚函数Language()需要子类重写,由于并不是每个不同人种的Language()都不同(比如英国人和美国人都speak English(不要太较真噢。。。)),所以对每个派生类重写这个方法可能不太合适,那么我们可以考虑将Language()移到一个接口类中来单独声明:
class ILanguage { public: virtual void speak() = 0; }
class Person{ public: ILanguage* iLanguage; void speak(){iLanguage->speak();} }
class LanguageEnglish : public ILanguage { public: void speak(){ std::out << "I Can Speak English"; } }
class American : public Person { public: American(){ iLanguage = new LanguageEnglish(); } }
Person *p = new American(); p->speak();
well,我们可以在设计Person类时为它加上一个setLanguage函数,变成下面这样:
class Person{ public: ILanguage* iLanguage; void speak(){iLanguage->speak();} void setLanguage(ILanguage* i){iLanguage = i;} }
class LanguageChinese : public ILanguage { public: void speak(){ std::out << "I Can Speak Chinese"; } }
Person *p = new American(); p->speak(); p->setLanguage(new LanguageChinese()); p->speak();
可以在这个设计模式看到三个设计原则:
1、封装变化
由于软件开发过程中迭代的反复性,我们应该将易变的部分独立开来。
2、多用组合,少用继承
使用组合建立系统往往比使用继承具有更大的弹性。
3、针对接口编程,不针对实现编程
接口编程:使用一个接口函数在运行时调用不同的实现;
实现编程:实现代码写在实体类中,弹性差,不灵活。
好,先到这里吧~