1. 设计模式概念
在一定的环境中总能用固定的套路解决实际问题,这种套路就叫做设计模式。这些套路将问题标准化:对各部分进行抽象、归纳和解耦合。注意,设计模式的实现基础是多态。
设计模式可分为3个类别:
(1)创建型模式:通常和对象的创建相关,涉及到对象实例化的方式(5种)
单例模式、工厂模式、抽象工厂模式、建造者模式、原型模式
(2)结构型模式:描述如何组合类和对象以获得更好的结构(7种)
代理模式、装配者模式、适配器模式、组合模式、桥接模式、外观模式、享元模式
(3)行为型模式::描述类(或者对象)之间如何交互和如何分配职责(11种)
模板模式、命令模式、责任链模式、策略模式、中介者模式、观察者模式、备忘录模式、访问者模式、状态模式、解释器模式、迭代器模式
2. 设计模式的基本原则
(1)开放封闭原则
对于类的改动不是修改源码,而是增加代码进行的。(开放增加代码的渠道,封闭修改源码的渠道)
(2)单一职责原则
类的职责单一,对外提供一种功能,引起类发生变化的原因也只能有一个。
未引入单一职责前的类的设计:
class bank_worker
{
public:
void savings() { cout << "savings..." << endl; }
void transfer() { cout << "transfer..." << endl; }
void draw() { cout << "draw..." << endl; }
void fund() { cout << "fund..." << endl; }
};
int main(void)
{
bank_worker *bw = new bank_worker;
bw->savings();
bw->draw();
delete bw;
return 0;
}
类bank_worker具有多种功能,显然不符合单一职责原则,修改成:
class ab_bank_worker
{
public:
virtual void dothing() = 0;
};
class save_worker : public ab_bank_worker
{
public:
void dothing() { cout << "savings..." << endl; }
};
class transfer_worker : public ab_bank_worker
{
public:
void dothing() { cout << "transfer..." << endl; }
};
class draw_worker : public ab_bank_worker
{
public:
void dothing() { cout << "draw..." << endl; }
};
class fund_worker : public ab_bank_worker
{
public:
void dothing() { cout << "fund..." << endl; }
};
int main(void)
{
ab_bank_worker* bw = new save_worker;
bw->dothing();
bw = new fund_worker;
bw->dothing();
delete bw;
return 0;
}
(3)依赖倒置原则
针对接口编程,即依赖于抽象(接口),不依赖于具体的实现(类)。
以组装电脑为例,如电脑的cpu可以是英特尔的也可以是其他厂家的,内存条也是如此,电脑要和具体的部件厂商解耦合,就需要用依赖倒置原则。
//computer.h
#ifndef __COMPUTER_H__
#define __COMPUTER_H__
#include <iostream>
using namespace std;
class hard_disk
{
public:
virtual void work() = 0;
};
class memory
{
public:
virtual void work() = 0;
};
class cpu
{
public:
virtual void work() = 0;
};
class computer
{
public:
computer(hard_disk* hd, memory* m, cpu* c) : m_hard_disk(hd), m_memory(m), m_cpu(c) {}
void work()
{
m_hard_disk->work();
m_memory->work();
m_cpu->work();
}
private:
hard_disk* m_hard_disk;
memory* m_memory;
cpu* m_cpu;
};
#endif /* __COMPUTER_H__ */
//hard_disk.h
#ifndef __HARD_DISK_H__
#define __HARD_DISK_H__
#include "computer.h"
using namespace std;
class Samsung_hard_disk : public hard_disk
{
public:
void work() { cout << "Samsung Hard disk" << endl; }
};
class Toshiba_hard_disk : public hard_disk
{
public:
void work() { cout << "Toshiba Hard disk" << endl; }
};
#endif /* __HARD_DISK_H__ */
//memory.h
#ifndef __MEMORY_H__
#define __MEMORY_H__
#include "computer.h"
using namespace std;
class kingston_memory : public memory
{
public:
void work() { cout << "Kingston Memory" << endl; }
};
class infineon_memory : public memory
{
public:
void work() { cout << "Infineon Memory" << endl; }
};
#endif /* __MEMORY_H__ */
//cpu.h
#ifndef __CPU_H__
#define __CPU_H__
#include "computer.h"
using namespace std;
class inter_cpu : public cpu
{
public:
void work() { cout << "Inter CPU" << endl; }
};
class amd_cpu : public cpu
{
public:
void work() { cout << "AMD CPU" << endl; }
};
#endif /* __CPU_H__ *
//computer.cpp
#include "computer.h"
#include "cpu.h"
#include "memory.h"
#include "hard_disk.h"
int main(void)
{
hard_disk* hd = new Samsung_hard_disk;
memory* mem = new infineon_memory;
cpu* c = new inter_cpu;
computer* cmp = new computer(hd, mem, c);
cmp->work();
delete cmp;
delete c;
delete mem;
delete hd;
return 0;
}
(4)接口隔离原则
一个接口对外只提供一种功能,不把所有的操作都封装到一个接口中。
(5)里式替换原则
任何抽象类出现的地方都可以用它的实现类进行替换,实际上也是赋值兼容原则: 指在需要基类的地方都可以使用派生类代替(反过来则不可以)
(6)迪米特法则
一个对象应该对其它对象尽可能少的了解,从而降低各个对象之间的耦合,提高软件系统的可维护性性。例如各个功能模块之间相互调用,通常要提供一个接口来实现。这样其它模块不需要了解另一个模块的内部实现细节,当模块的内部实现发生改变时不会影响其它模块的使用。
(7)类之间优先使用组合而非继承
使用继承会导致父类的任何改变都可能影响到子类的行为(如将成员属性从protected改为private),若使用对象组合则会降低依赖关系。