设计模式(一)——设计原则
在一定环境下,用固定模式解决问题。
设计模式目前种类:GoF的23种 + “简单工厂模式” = 24种
包括:
创建型(Creational)模式:如何创建对象,6种
结构性(Structual)模式:如何实现类或对象的组合,7种
行为型(Behavioral)模式:类或对象怎样交互以及怎样分配职责,11种
学习设计模式有利于更深理解面向对象思想,让你知道:
1.如何将代码分散在几个不同的类中?
2.为什么要有“接口”
3.何胃针对抽象编程
4.何时不应该使用继承?
5.如果不修改源代码增加新功能?
6.更好低阅读和理解现有类库与其他系统中的源代码?
设计模式的基础:多态(继承,虚函数重写,父类指针或引用指向子类对象)
原则:
对于面向对象软件系统的设计而言,在支持可维护性的同时,提高系统的
可复用性是一个至关重要的问题,如何同时提高一个软件系统的可维护性和可
复用性是面向对象设计需要解决的核心问题之一。 在面向对象设计中,可维护
性的复用是以设计原则为基础的。每一个原则都蕴含一些面向对象设计的思想,
可以从不同的角度提升一个软件结构的设计水平。
面向对象设计原则为支持可维护性复用而诞生,这些原则蕴含在很多设计
模式中,它们是从许多设计方案中总结出的指导性原则。 面向对象设计原则也
是我们用于评价一个设计模式的使用效果的重要指标之一。
目标:高内聚,低耦合
单一职责原则:类的职责单一,对外只提供一种功能
将每个类的方法分离出来,就能保证每个类的指针单一
提高安全性
提高了维护性
提高了可读性
#include <iostream> using namespace std; class Clothes { public: void shopping() { cout << "休闲的衣服" << endl; } void working() { cout << "工作的衣服" << endl; } }; class ClothesShoping { public: void style() { cout << "休闲的衣服" << endl; } }; class ClothesWorking { public: void style() { cout << "工作的衣服" << endl; } }; int main() { ClothesShoping cs; cs.style(); ClothesWorking cw; cw.style(); system("pause"); return 0; }
开闭原则:类的改动是通过增加代码进行的,而不是修改源代码
提高了可读性
提高了安全性
提高了维护性
提高了可复用性
#include <iostream> using namespace std; // 银行业务员: class Banker { public: void save() { cout << "存款" << endl; } void pay() { cout << "支付" << endl; } void tansfer() { cout << "转账" << endl; } // 添加一个办理基金业务 若添加的业务多,则代码会越来越庞大 void fund() { cout << "办理基金" << endl; } }; ///////////////////////////////// ////////////////////////////////// // 抽象的银行业务员 //------------------------------- //- worker() = 0 - //- - //------------------------------- ///////////////////////////////// ////////////////////////////////// // 存款业务员 //------------------------------- //- - //- 存款 - //------------------------------- ///////////////////////////////// ////////////////////////////////// // 支付业务员 //------------------------------- //- 支付 - //- - //------------------------------- ///////////////////////////////// ////////////////////////////////// // 转账业务员 //------------------------------- //- 转账 - //- - //------------------------------- ///////////////////////////////// // 抽象类 // 添加新的业务不需要修改原来代码,只需要添加新代码 class AbstractBanker { public: virtual void worker() = 0;// 抽象接口 }; class SaveBanker:public AbstractBanker { public: virtual void worker() { cout << "存款" << endl; } }; class PayBanker :public AbstractBanker { public: virtual void worker() { cout << "支付" << endl; } }; class TransferBanker :public AbstractBanker { public: virtual void worker() { cout << "转账" << endl; } }; // 添加一个办理基金业务 若添加的业务多,则代码会越来越庞大 class FundBanker :public AbstractBanker { public: virtual void worker() { cout << "基金业务" << endl; } }; int main() { #if 0 // 此方法不好 Banker b; b.save(); #endif AbstractBanker* ab = new SaveBanker(); ab->worker(); ab = new PayBanker(); ab->worker(); ab = new TransferBanker(); ab->worker(); delete ab; system("pause"); return 0; }
依赖倒转原则:依赖于抽象(借口),不要依赖于具体实现(类),也就是针对接口编程
将业务层和实现层通过抽象层隔离——解耦合
#include <iostream> using namespace std; class Benz { public: void run() { cout << "奔驰启动了" << endl; } }; class Baoma { public: void run() { cout << "宝马启动了" << endl; } }; class Zhangsan { public: void driveBenz(Benz* b) { b->run(); } void driveBMW(Baoma* b) { b->run(); } }; /////////////////////////////////////// // 高层业务逻辑层 // /////////////////////////////////////// /////////////////////////////////////// // 抽象层 // Driver Car /////////////////////////////////////// /////////////////////////////////////// // 实现层 底层向上依赖 // zhangsan lisi baoma benz /////////////////////////////////////// // 抽象层 class Car { public: virtual void run() = 0; }; class Driver { public: virtual void driver(Car* car) = 0; }; class Jeep:public Car { public: virtual void run() { cout << "吉普启动了" << endl; } }; class Lisi :public Driver { public: virtual void driver(Car* car) { cout << "李四开车了" << endl; car->run(); } }; // 业务 int main() { #if 0 // 让zhangsan 去开benz Benz* benz = new Benz; Zhangsan* zhangsan = new Zhangsan; zhangsan->driveBenz(benz); // 让zhangsan 去开benz Baoma* BMW = new Baoma; zhangsan->driveBMW(BMW); // 去开大众,jeep...越写越复杂混乱 delete benz; delete BMW; delete zhangsan; #endif // 只使用两个类 Car* car = new Jeep; Driver* lisi = new Lisi; lisi->driver(car); delete car; delete lisi; system("pause"); return 0; }
合成复用原则:如果使用继承,会导致父类的任何变换都影响到子类的行为。如果使用对 象组合,就降低了这种依赖关系。对于继承和组合,优先使用组合。
如果使用继承方式,那么新的子类将会和所有的父类高耦合
#include <iostream> using namespace std; class Cat // 还可以继承动物... { public: void sleep() { cout << "小猫睡觉" << endl; } }; // 继承方式 class AdCat :public Cat { public: void eat_and_sleep() { cout << "吃东西" << endl; sleep(); } }; // 使用组合的方式来添加小猫吃东西的方法 // 降低了AdCat2和Cat的耦合度,跟Cat的父类没有任何关系 // 只跟Cat的sleep方法有关系 class AdCat2 { public: AdCat2(Cat* cat) { this->cat = cat; } void eat_and_sleep()// 若将cat以参数传入,则是依赖关系 { cout << "吃东西" << endl; cat->sleep(); } private: Cat* cat;// 这种关系是关联 }; int main() { Cat cat; AdCat2 adcat(&cat); adcat.eat_and_sleep(); system("pause"); return 0; }