设计模式笔记(一)
一、什么是设计模式?
特定环境下解决某类重复出现问题的一套成功或有效的解决方案。
二、设计模式的分类
GOF:23个。
创建型:如何创建对象;
结构型:如何实现类或对象的组合;
行为型:类或对象怎样交互以及怎样分配职责;
简单工厂模式:独立于23个设计模式之外的一种。
共24个。
三、设计模式的目标
(1)如何将代码分散在几个不同的类中?
(2)为什么要有接口?
(3)何谓针对抽象编程?
(4)何时不应该使用继承?
(5)如何不修改源代码添加新功能?
(6)更好的阅读和理解类库与其他系统中的源代码。
四、设计模式的基础
多态
五、面向对象设计的目的与原则
目的:高内聚,低耦合。
原则:
1)单一职责原则:类的职责单一,对外只提供一种功能,而引起类变化的原因都应该只有一个;
2) 开闭原则:对扩展开放,对修改关闭。类的改动是通过增加代码进行的,而不是修改源代码;
3) 里氏代换原则:任何抽象类出现的地方都可以用它的实现类进行替换,实际就是虚拟机制,语言级别实现面向对象功能;
4) 依赖倒转原则:依赖于抽象(接口),不要依赖具体的实现(类),也就是针对接口编程;
5) 接口隔离原则:不应该强迫用户程序依赖他们不需要的接口方法。一个接口应该只提供一种对外功能,不应该把所有操作都封装到一个接口中去;
6) 合成复用原则:如果使用继承,会导致父类的任何变换都可能影响到子类的行为。如果使用对象组合,就降低了这种依赖关系。对于继承和组合,优先使用组合;
7) 迪米特法则:一个对象应当对其他对象尽可能少的了解,从而降低各个对象之间的耦合,提高系统的可维护性。
六、部分代码示例
(1)开闭原则
/*
第一版小孩儿写作业:
此处每当我们想让小孩儿写别的科目的作业,我们需要定义新的作业类或者继承作业类后覆写do_homowork接口,并且Child类也必须作出修改。
*/
#include<iostream>
class Homework{
public:
Homework(){}
~Homework(){}
public:
void BeDoing()
{
std::cout << "I am Chinese homework, and I'am being done. " << std::endl;
}
};
class Mathwork : public Homework{
public:
Mathwork(){}
~Mathwork(){}
public:
void BeDoing()
{
std::cout << "I am Math homework, and I'am being done. " << std::endl;
}
};
class Child{
public:
Child(){}
~Child(){}
public:
void do_homework()
{
m_work.BeDoing();
}
private:
Homework m_work;
};
class Child2{
public:
Child2(){}
~Child2(){}
public:
void do_homework()
{
m_work.BeDoing();
}
private:
Mathwork m_work;
};
int main(int argc, char **argv)
{
Child child;
child.do_homework();
Child2 child2;
child2.do_homework();
return 0;
}
/*
第二版小孩儿写作业:
此时,我们再想让小孩儿写其他的作业,只需定义新的作业类,而无需修改已经定义好的小孩儿类。即:新功能的实现是通过添加代码,而不是修改已经写好的小孩类源码。
*/
#include<iostream>
class Homework{
public:
Homework(){}
virtual ~Homework()
{
std::cout << "Homework over. " << std::endl;
}
public:
virtual void BeDoing() = 0;
};
class Chinese_work : public Homework{
public:
Chinese_work(){}
virtual ~Chinese_work()
{
std::cout << "Chinese work over. " << std::endl;
}
public:
void BeDoing()
{
std::cout << "I'am Chinese homework, and I'am being done. " << std::endl;
}
};
class Math_work : public Homework{
public:
Math_work(){}
virtual ~Math_work()
{
std::cout << "Math work over. " << std::endl;
}
public:
void BeDoing()
{
std::cout << "I'am Math homework, and I'am being done. " << std::endl;
}
};
//...其他作业
class Child{
public:
Child(){}
~Child(){}
public:
void set_work(Homework *a_work)
{
m_work = a_work;
}
void do_homework()
{
if(!m_work)
{
return;
}
m_work->BeDoing();
delete m_work;
m_work = NULL;
}
private:
Homework* m_work;
};
int main(int argc, char **argv)
{
Child child;
child.set_work(new Chinese_work);
child.do_homework();
child.set_work(new Math_work);
child.do_homework();
return 0;
}
(2)合成复用原则
/*
作业批改:
当我们想让小孩儿写作业的时候,可以通过以下方式实现。但是当基类作出改变的时候(修改作业),会造成子类作出不必要的改变或无意义的改变。
如向上例中的组合使用(将作业类指针作为小孩儿类成员),则不会造成此问题。即:能组合,尽量使用组合。
*/
#include<iostream>
class Homework{
public:
Homework(){}
virtual ~Homework(){};
public:
virtual void BeDoing() = 0;
virtual void Deal() = 0;
};
class Child : public Homework{
public:
Child(){}
virtual ~Child(){}
public:
void BeDoing()
{
std::cout << "I'am homework, and I'am being done. " << std::endl;
}
void Deal()
{
std::cout << "I'am just a child and no one gives me the answer. F**k it. " << std::endl;
}
};
int main(int argc, char **argv)
{
Child child;
child.BeDoing();
return 0;
}