目录
1.C 语言设计模式(开篇)..........................................................................................2
2.C 语言和设计模式(继承、封装、多态)..............................................................3
2.1 继承性...............................................................................................................3
2.2 封装性...............................................................................................................4
2.3 多态...................................................................................................................4
3.单件模式.....................................................................................................................4
4.工厂模式.....................................................................................................................5
5.抽象工厂模式.............................................................................................................6
6.访问者模式.................................................................................................................1
7.状态模式.....................................................................................................................1
8.命令模式.....................................................................................................................1
9.解释器模式.................................................................................................................1
10.备忘录模式...............................................................................................................1
11.观察者模式...............................................................................................................1
12.桥接模式...................................................................................................................1
13.建造者模式...............................................................................................................1
14.中介者模式...............................................................................................................1
15.策略模式...................................................................................................................1
16.适配器模式...............................................................................................................1
17.装饰模式...................................................................................................................1
18.亨元模式...................................................................................................................1
19.代理模式...................................................................................................................1
20.外观模式...................................................................................................................1
21.迭代器模式...............................................................................................................1
22.责任链模式...............................................................................................................1
23.模版模式................................................................................................................1
24.组合模式...................................................................................................................1
25.原型模式...................................................................................................................1
1.C 语言设计模式(开篇)
关于软件设计方面的书很多,比如《重构》,比如《设计模式》。至于软件开发
方式,那就更多了,什么极限编程、精益方法、敏捷方法。随着时间的推移,很多的方
法又会被重新提出来。
其实,就我个人看来,不管什么方法都离不开人。一个人写不出二叉树,你怎
么让他写?敏捷吗?你写一行,我写一行。还是迭代?写三行,删掉两行,再写三行。
项目的成功是偶然的,但是项目的失败却有很多原因,管理混乱、需求混乱、设计低劣、
代码质量差、测试不到位等等。就软件企业而言,没有比优秀的文化和出色的企业人才
更重要的了。
从软件设计层面来说,一般来说主要包括三个方面:
(1)软件的设计受众,是小孩子、老人、女性,还是专业人士等等;
(2)软件的基本设计原则,以人为本、模块分离、层次清晰、简约至上、适
用为先、抽象基本业务等等;
(3)软件编写模式,比如装饰模式、责任链、单件模式等等。
从某种意义上说,设计思想构成了软件的主题。软件原则是我们在开发中的必
须遵循的准绳。软件编写模式是开发过程中的重要经验总结。灵活运用设计模式,一方
面利于我们编写高质量的代码,另一方面也方便我们对代码进行维护。毕竟对于广大的
软件开发者来说,软件的维护时间要比软件编写的时间要多得多。编写过程中,难免要
有新的需求,要和别的模块打交道,要对已有的代码进行复用,那么这时候设计模式就
派上了用场。我们讨论的主题其实就是设计模式。
讲到设计模式,人们首先想到的语言就是 c#或者是 java,最不济也是 c++,一
般来说没有人会考虑到 c 语言。其实,我认为设计模式就是一种基本思想,过度美化或
者神化其实没有必要。其实阅读过 linux kernel 的朋友都知道,linux 虽然自身支持很多
的文件系统,但是 linux 自身很好地把这些系统的基本操作都抽象出来了,成为了基本
的虚拟文件系统。
举个例子来说,现在让你写一个音乐播放器,但是要支持的文件格式很多,什么 ogg,
wav,mp3 啊,统统要支持。这时候,你会怎么编写呢?如果用 C++语言,你可能会这
么写。
class music_file
{
HANDLE hFile;
public:
void music_file() {}
virtual ~music_file() {}
virtual void read_file() {}
virtual void play() {}
virtual void stop() {}
virtual void back() {}
virtual void front() {}
virtual void up() {}
virtual void down() {}
};
其实,你想想看,如果用 C 语言能够完成相同的抽象操作,那不是效果一样的吗?
typedef struct _music_file
{
HANDLE hFile;
void (*read_file)(struct _music_file* pMusicFile);
void (*play)(struct _music_file* pMusicFile);
void (*stop)(struct _music_file* pMusicFile);
void (*back)(struct _music_file* pMusicFile);
void (*front)(struct _music_file* pMusicFile);
void (*down)(struct _music_file* pMusicFile);
void (*up)(struct _music_file* pMusicFile);
}music_file;
当然,上面的例子比较简单,但是也能说明一些问题。写这篇文章的目的一是希望和朋
友们共同学习模式的相关内容,另一方面也希望朋友们能够活学活用,既不要迷信权威,也
不要妄自菲薄。只要付出努力,付出汗水,肯定会有收获的。有些大环境你改变不了,那就
从改变自己开始。万丈高楼平地起,一步一个脚印才能真真实实学到东西。如果盲目崇拜,
言必 google、微软、apple,那么除了带来几个唾沫星,还能有什么受用呢?无非白费了口
舌而已。
希望和大家共勉。
2.C 语言和设计模式(继承、封装、多态)
记得还在我们大学 C++第一门课的时候,老师就告诉我们说,C++是一门面向对象的
语言。C++有三个最重要的特点,即继承、封装、多态。等到后来随着编码的增多和工
作经验的积累,我也慢慢明白了面向对象的含义。可是,等我工作以后,使用的编程语
言更多的是 C 语言,这时候我又想能不能把 C 语言变成面向对象的语言呢?等到后来通
过思考和实践,我发现其实 C 语言也是可以面向对象的,也是可以应用设计模式的,关
键就在于如何实现面向对象语言的三个重要属性。
2.1 继承性
typedef struct _parent
{
int data_parent;
}Parent;
typedef struct _Child
{
struct _parent parent;
int data_child;
}Child;
在设计 C 语言继承性的时候,我们需要做的就是把基础数据放在继承的结构的首位
置即可。这样,不管是数据的访问、数据的强转、数据的访问都不会有什么问题。
2.2 封装性
struct _Data;
typedef
void (*process)(struct _Data* pData);
typedef struct _Data
{
int value;
process pProcess;
}Data;
封装性的意义在于,函数和数据是绑在一起的,数据和数据是绑在一起的。这样,
我们就可以通过简单的一个结构指针访问到所有的数据,遍历所有的函数。封装性,这
是类拥有的属性,当然也是数据结构体拥有的属性。
2.3 多态
3.单件模式
有过面试经验的朋友,或者对设计模式有点熟悉的朋友,都会对单件模式不陌生。
对很多面试官而言,单件模式更是他们面试的保留项目。其实,我倒认为,单件模式算
不上什么设计模式。最多也就是个技巧。
单件模式要是用 C++写,一般这么写。
#include
#include
class object
{
public:
static class object* pObject;
static object* create_new_object()
{
if(NULL != pObject)
return pObject;
pObject = new object();
assert(NULL != pObject);
return pObject;
}
private:
object() {}
~object() {}
};
class object* object::pObject = NULL;
单件模式的技巧就在于类的构造函数是一个私有的函数。但是类的构造函数又是必
须创建的?怎么办呢?那就只有动用 static 函数了。我们看到 static 里面调用了构造函数,
就是这么简单。
int main(int argc, char* argv[])
{
object* pGlobal = object::create_new_object();
return 1;
}
4.工厂模式
工厂模式是比较简单,也是比较好用的一种方式。根本上说,工厂模式的目的就根据不
同的要求输出不同的产品。比如说吧,有一个生产鞋子的工厂,它能生产皮鞋,也能生产胶
鞋。如果用代码设计,应该怎么做呢?
typedef struct _Shoe
{
int type;
void (*print_shoe)(struct _Shoe*);
}Shoe;
就像上面说的,现在有胶鞋,那也有皮鞋,我们该怎么做呢?
void print_leather_shoe(struct _Shoe* pShoe)
{
assert(NULL != pShoe);
printf("This is a leather show!\n");
}
void print_rubber_shoe(struct _Shoe* pShoe)
{
assert(NULL != pShoe);
printf("This is a rubber shoe!\n");
}
所以,对于一个工厂来说,创建什么样的鞋子,就看我们输入的参数是什么?至于结果,
那都是一样的。
#define LEATHER_TYPE 0x01
#define RUBBER_TYPE
0x02
Shoe* manufacture_new_shoe(int type)
{
assert(LEATHER_TYPE == type || RUBBER_TYPE == type);
Shoe* pShoe = (Shoe*)malloc(sizeof(Shoe));
assert(NULL != pShoe);
memset(pShoe, 0, sizeof(Shoe));
if(LEATHER_TYPE == type)
{
pShoe->type == LEATHER_TYPE;
pShoe->print_shoe = print_leather_shoe;
}
else
{
}
pShoe->type == RUBBER_TYPE;
pShoe->print_shoe = print_rubber_shoe;
return pShoe;
}
5.抽象工厂模式
前面我们写过的工厂模式实际上是对产品的抽象。对于不同的用户需求,我们可以给予
不同的产品,而且这些产品的接口都是一致的。而抽象工厂呢?顾名思义,就是说我们的工
厂是不一定的。怎么理解呢,举个例子。
假设有两个水果店都在卖水果,都卖苹果和葡萄。其中一个水果店买白苹果和白葡
萄,另外一个水果店卖红苹果和红葡萄。所以说,对于水果店而言,尽管都在卖水果,但是
两个店卖的品种不一样。
既然水果不一样,那我们先定义水果。
typedef struct _Apple
{
void (*print_apple)();
}Apple;
typedef struct _Grape
{
void (*print_grape)();
}Grape;
上面分别对苹果和葡萄进行了抽象,当然它们的具体函数也是不一样的。
void print_white_apple()
{
printf("white apple!\n");
}
void print_red_apple()
{
printf("red apple!\n");
}
void print_white_grape()
{
printf("white grape!\n");
}
void print_red_grape()
{
printf("red grape!\n");
}
完成了水果函数的定义。下面就该定义工厂了,和水果一样,我们也需要对工厂进行抽
象处理。
typedef struct _FruitShop
{
Apple* (*sell_apple)();
Grape * (*sell_grape)();
}FruitShop;
所以,对于卖白苹果、白葡萄的水果店就该这样设计了,红苹果、红葡萄的水果店
亦是如此。
Apple* sell_white_apple()
{
Apple* pApple = (Apple*) malloc(sizeof(Apple));
assert(NULL != pApple);
pApple->print_apple = print_white_apple;
return pApple;
}
Grape* sell_white_grape()
{
Grape* pGrape = (Grape*) malloc(sizeof(Grape));
assert(NULL != pGrape);
pGrape->print_grape = print_white_grape;
return pGrape;
}
这样,基本的框架就算搭建完成的,以后创建工厂的时候,
FruitShop* create_fruit_shop(int color)
{
FruitShop* pFruitShop = (FruitShop*) malloc(sizeof(FruitShop));
assert(NULL != pFruitShop);
if(WHITE == color)
{
pFruitShop->sell_apple = sell_white_apple;
pFruitShop->sell_grape = sell_white_grape;
}
else
{
}
pFruitShop->sell_apple = sell_red_apple;
pFruitShop->sell_grape = sell_red_grape;
return pFruitShop;
}
6.访问者模式
不知不觉当中,我们就到了最后一种设计模式,即访问者模式。访问者模式,听上去复
杂一些。但是,这种模式用简单的一句话说,就是不同的人对不同的事物有不同的感觉。比
如说吧,豆腐可以做成麻辣豆腐,也可以做成臭豆腐。可是,不同的地方的人未必都喜欢这
两种豆腐。四川的朋友可能更喜欢辣豆腐,江浙的人就可能对臭豆腐更喜欢一些。那么,这
种情况应该怎么用设计模式表达呢?
typedef struct _Tofu
{
int type;
void (*eat)
}Tofu;
(struct _Visitor* pVisitor, struct _Tofu* pTofu);
typedef struct _Visitor
{
int region;
void (*process)(struct _Tofu* pTofu, struct _Visitor* pVisitor);
}Visitor;