帐前卒专栏

code, software architect, articles and novels.
代码,软件架构,博客和小说

在ubuntu或者其他的linux下生成大文件,必须使用编译参数 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64.否
则生成的文件一定是2G左右的,原因是fseek,这个函数中的offset参数是一个long型的或者是size_t型的,在fseeko中是off_t,但是这个
off_t默认还是32位,只有加了 -D_FILE_OFFSET_BITS=64的宏定义才被作为64位对待.

写了下面一段代码来生成大文件,传说有一种方法:直接跳转nG位置之后,然后写入一个字符.这种方法可能更快,不过我为了保守的生成文件,还是使用下面的一个写法:

#include<stdio.h> #include<stdlib.h> #include<unistd.h> #include<string.h>
void gen_file(const char filename, int block_size, int count){ int is_exist =
0; FILE
file = fopen(filename,“w+b”); char * buf = NULL; int i=0; long long
size = block_size; if(file == NULL){ printf(“fatal error in gen_file:
fopen/n”); exit(1); } buf = (char )malloc(sizeof(char)block_size);
memset(buf,‘1’,sizeof(char)block_size); while(i++<count){ if(i % 10 == 0){
printf(“count is %d, size is %lld/n”,i,size); } fwrite(buf,block_size,1,file);
size += block_size; fseeko(file,size,SEEK_SET); } fclose(file); free(buf); /

long long size = 1024
1024
1024; size =10; fseeko(file,size,SEEK_SET);
fwrite(buf,block_size,1,file); fclose(file); free(buf); / } int main(){
printf(“size of char %d/n”,sizeof(char)); int block_size = 1024
1024
20; //
20M int count = 50; gen_file(“smallfile”,block_size,count*2);// gen 2G file
return 0; }

int block_size = 1024102420; // 20M

这个是每次写入的数据大小,gen_file(“smallfile”,block_size,count*2);第三个参数可以调节生成文件的大小.

下面写了一个测试大文件和小文件的随机读写和顺序读写.

#include<stdio.h> #include<time.h> #include<sys/stat.h> #include<sys/types.h>
#include<unistd.h> #include<stdlib.h> #include<sys/time.h> #include<string.h>
const int block_size = 8092; struct timeval start; struct timeval end; struct
timezone tz; void start_time(){ gettimeofday(&start,&tz); } void end_time(){
gettimeofday(&end,&tz); } void print_time(){ printf(“%lf sec/n”,(end.tv_sec-
start.tv_sec)+(double)(end.tv_usec-start.tv_usec)/1000000); } size_t
look_size(const char * filename){ struct stat st; stat(filename,&st); return
st.st_size; } void read_blocks(FILE* file, off_t offset,int block_size){ int
where = offsetblock_size; fseeko(file,where,0); } FILE fopen_safe(const char

  • filename){ FILE* file = fopen(filename,“r”); if(file == NULL){ printf(“fatal
    error in random_read, open file”); exit(1); } return file; } void
    random_read(const char * filename){ int random; size_t size; FILE* file =
    fopen_safe(filename); size = look_size(filename)/block_size; random =
    rand()%size; read_blocks(file,random,block_size); fclose(file); } void
    order_read(const char filename,int order){ size_t size; FILE file =
    fopen_safe(filename); size = look_size(filename)/block_size;
    read_blocks(file,order%size,block_size); fclose(file); } void
    random_test(const char * filename,int times){ int count = 0; start_time();
    while(count++<times){ // access Big File random_read(filename); } end_time();
    print_time(); } void order_test(const char * filename, int times){ int count =
    0; start_time(); while(count++<times){ order_read(filename,count); }
    end_time(); print_time(); } void random_test_diff(const char * basename,int
    num,int times){ int count = 0; char ** names = malloc(sizeof(char)*num); int
    len = strlen(basename); int i = 0; while( i < num){ names[i] =
    malloc(sizeof(char)*len+4); sprintf(names[i],“%s_%d”,basename,i); i++; }
    start_time(); while(count++<times){ if(count < 900){ random_read(names[0]); }
    else { if(count < 960){ random_read(names[count%num]);
    random_read(names[(count+1)%num]); } if(count < 1000){
    random_read(names[count%num]); random_read(names[(count+1)%num]);
    random_read(names[(count+2)%num]); } } } end_time(); print_time(); } int
    main(){ int i,count; int times = 1000; count = 0; // clock_t start,end;
    srand(time(NULL)); char * filename=“bigfile”; //printf(“time is %lf”,((double
    )(end-start))/CLOCKS_PER_SEC); random_test(filename,times);
    order_test(filename,times); times = times; filename = “smallfile”;
    random_test(filename,times); order_test(filename,times);
    random_test_diff(filename,3,times); return 0; }

当然你这里做测试的时候可以把gettimeofday替换为clock()或者time()函数,其中clock()是程序实际运行的时间,你感觉可能执行了七八秒
,其实程序只占用cpu执行了1秒.如果是time()函数或者gettimeofday()函数就是真正的运行时间也就是你感觉执行的时间.所以各有千秋,前者是为
了排除各种运行环境中的软件或者os的不同,单独检测程序的效率.后者是在系统环境中程序的执行时间.

下面是我得到的结论,创建1个10G文件,创建3个2G小文件.
大文件 随机访问7.199645 sec
大文件 顺序访问0.013617 sec
单个小文件 随机访问5.119245 sec
小文件 顺序访问0.014190 sec
多个小文件的随机访问测试:90%的几率访问同一个小文件,6%访问两个小文件,4%访问3个小文件 9.791248
sec.并且90%几率发生在前,所以如果随机发生多个文件的随机访问,那么可能速度会更慢.这里慢的原因,是因为fopen.

这也就是数据库为什么只有一个数据文件的原因.有时进行文件切分,反而不利于效率的提高.但是对于100G以上的大文件,是否这个结论又要改变了呢?我没有做过这个实
验.

这次大会的演讲嘉宾的内容参差不齐,有好有坏。

有时个人觉得听上面的人吹来吹去,不如听听各个展台的工程师是怎么做的。

个人感觉csdn实在是没有钱。既然没有钱就不要打肿脸充胖子乱搞活动。中午就发个三明治。还不如不发餐卷,或者写自带午餐或者请到外面的成都小吃自己买饭吃。我实在
不知道处于什么目的,发一个精美的袋子,里面就一点点吃的。本以为是午餐前的餐点,后来才真的相信这就是午餐。

传说第一届的午餐也是三明治,但是人家是不要钱的!另外第一、二天其实没有票也是可以去听的。当初实验室真不如把钱给我们算了。

去那里发现许多人和我有同样的问题,有一部分解答了,有一部分还在思考研究中:

1。服务器利用率的提高,是否是真正利用了?这部分利用率是用于虚拟化,还是用于真正的业务?VMware的工程师说,资源只用5%消耗在虚拟化上。这个5%并不随着
虚拟机的增多而线性增加。当然,我还是不信…

2。当两台虚拟机在同一个机器中运行,是有公平的弹性机制(你不用时我用,我不用时你用,你我都用时对半分),也就是balloom技术。至于这个技术是啥米,有待研
究,但是从xcp中看到了Memory Balloom,不知道是否是同样的东东。

3。当应用需消耗大量资源的程序,如果在一台物理服务器上跑得很吃力,那么就别寻求云计算。

4。程序必须有并发性。如果云计算平台能屏蔽分布式物理机带来的进程通信的影响,那么多进程的编程是必要的。如果云计算可以只把线程迁移到其他物理机器上,那就更好了
,不过我知道那是天方夜谭。

5。如果我的物理机器都只是两核的,那么我也就不会虚拟出四核的机器。

6。一台虚拟机器可以使用另外一台物理机器的存储资源(硬盘)?当时那个工程师说可以。那是因为那台物理机器开启了另外一个VM实例,还是没有开?

7。chinaCache说Xen比vmware好,因为xen是os层虚拟化,vmware说vmware最好,因为vmware稳定。其实vmware传说也有自
己的os虚拟化技术。

8。mysql在chinaCache中效率比EC2高3倍。因为它是一个机器中的本地存储,而EC2可以看作使用了存储网络,所以EC2会有线路传输带宽的消耗。我
个人认为chinaCache没有办法大量持续扩容的.否则性能会降低到EC2的水平。

9。如果因为一台物理机中太多虚拟机共同消耗资源,而导致某些井喷业务不能响应,那么会将这些业务迁移到其他机器中。但是它的监控器都无法响应了,它怎么知道哪个业务
是井喷业务呢?

10。以后会议别请高层了,乱忽悠。另外我不太清楚服务器是什么概念?如果是高级稳定机器来说,我们实验室就两台服务器。如果随便的pc机就可以做服务器,那归我管的
服务器就有4~5台。我觉得业界还没有统一服务器的概念。

11。大云其实就是做了基于MapReduce的数据挖掘算法…

12.中移动说现在已经可以支持5000台服务器,那是Yahoo的hadoop.其实我不太相信他有这么多机器。(他的服务器是啥概念?)

First, compile the source code use ./configure --prefix=XXXX --enable-debug && CFLAGS=-O0

then make and make install.

IF you want to RESTART PG

Detected if there is an instance of Postgre server. If there is, kill it. use
1
2
3
ps -e | grep postgre
// find id of the process
kill -9 $processid

to detect the pocess of postgresql and kill it.

then use:

1
2
3
4
gdb postgresqlHomeDIR/bin/postgres -quiet
// enter gdb then use
set args -D DATADIR
run

here DATADIR and postgresqlDIR are your own directory.

IF you don't want to RESTART PG

1
2
3
4
5
6
7
// find postgres pid
pid = `ps auxww | \
grep postgres: | \
grep -v -e 'grep postgres:' -e 'postgres: stats' -e 'postgres: writer' -e 'postgres: archiver' -e 'postgres: logger' -e 'postgres: autovacuum' | \
tee /dev/tty | \
awk '{print $2}'`
gdb pid

then use

1
./psql test

to test. Here test is  your database name.

IF you want to debug contrib

make && make install in contrib/yourdir

then go to gdb to file your shard lib to load symbol. Here XXX.so is your contrib share lib.

1
(gdb) file XXX.so

if not, when you use break somefunction, it will report:

No symbol table is loaded.  Use the “file” command.
Make breakpoint pending on future shared library load? (y or [n])

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
// flyweight.cpp : Defines the entry point for the console application.
// author: chillyc
// email: chillycreator @t gmail.com

#include&lt;iostream&gt;
#include&lt;map&gt;
namespace pattern{

/// this is flyweight pattern
/// In text processing, there will be thousands of hundreds of characters.
/// If we construct too many this class instance, and
/// imaging this class will have many member variables, will the system be efficient?
/// So we just record the characters state, and not care about other part of character.
/// we shall save a lot of main memories, shall we?
/// If there are many characters, but they are only in differnt place, we can reuse characters.
/// So there are Fly_Manager to record the shared objects or states.
/// All objects should be derived from Metadata class.
/// Graphdata is no-shared metadata. And Character is shared metadata.
/// In main function, you will see the difference between two of them.

#ifndef STATE_H
#define STATE_H
class State{
private:
int font_num;
int style;

public:
void Set_Font_Num(int num){font_num = num;}
void Set_Style(int style){this-&gt;style = style;}
int Get_Font_Num(){return font_num;}
int Get_Style(){return style;}
State(){}
State(int num,int style){
font_num = num;
this-&gt;style = style;
}
State(const State&amp; state){
this-&gt;font_num = state.font_num;
this-&gt;style = state.style;
}
State* operator = (const State&amp; state){
this-&gt;font_num = state.font_num;
this-&gt;style = state.style;
return this;
}
};

#endif

#ifndef METADATA_H
#define METADATA_H
class Metadata{
public:
virtual void show()=0;
};
#endif

#ifndef character_H
#define character_H
// share the basic information
// here you should image character has a huge infomation,
// and state is only a small part of this class
class character: public Metadata{
private:
State state;
public:
// set state to default state
character():Metadata(),state(1,1){}
~character(){}
void Set_State(State&amp; state);
virtual void show();

};
void character::Set_State(pattern::State&amp; state){
this-&gt;state = state;
}

void character::show(){
std::cout &lt;&lt; "write a character font is "&lt;&lt; state.Get_Font_Num()&lt;&lt; " style is "
&lt;&lt; state.Get_Style()&lt;&lt;std::endl;
}
#endif

#ifndef GRAPHDATA_H
#define GRAPHDATA_H
// not share
class Graphdata: public Metadata{
private:
State state;
public:
Graphdata(State &amp; state):Metadata(),state(state){}
// font num is not used
Graphdata(int style):Metadata(),state(-1,style){}
~Graphdata(){};
virtual void show();
};

#endif
void Graphdata::show(){
// only use its own state
std::cout&lt;&lt; "print a graph! style is "&lt;&lt;state.Get_Style()&lt;&lt;std::endl;
}

#ifndef FLYMANAGER_H
#define FLYMANAGER_H
class Fly_Manager{
public:
// suggest you should make it as private or protected
std::map&lt;int,State&gt; characters;
Fly_Manager(){}
void Set_I(int i, State&amp; state);
State&amp; Get_I(int i);
~Fly_Manager(){}

};
#endif
void Fly_Manager::Set_I(int i, State&amp; state){
characters[i] = state;
}
State&amp; Fly_Manager::Get_I(int i){
return characters[i];
}

}
int main()
{
pattern::Fly_Manager fm;
pattern::character c;
pattern::State s1(1,2);
pattern::State s2(2,3);
pattern::State s3(3,4);
fm.Set_I(0,s1);
fm.Set_I(1,s2);
fm.Set_I(2,s3);
pattern::Graphdata gd1(2);
pattern::Graphdata gd2(9);
for(int i = 0; i &lt; 3; i++){
c.Set_State(fm.Get_I(i));
c.show();
}
gd1.show();
gd2.show();
return 0;
}

昨天机器终于蓝屏了。产生了一个unmountable_boot_volume错误,大概是我管电源时突然断电所致。这个错误会停在0x000000ED位置。据微
软官方称是因为硬盘驱动器IDE写缓存时导致的内容不一致。最初断电后重启,画面一只能够停在windows图标上,并且硬盘没有动静。后来F8进入选择最近配置,结
果就报出了这个0x000000ED蓝屏,然后再try了下安全模式,发现依旧是蓝屏。

微软提供的解决方案是把windows安装盘放进去,然后再进入recover console.进入后使用chkdsk
/r即可恢复。结果我放入windows安装盘,进入recover console, 提示曰:安装程序没有找到安装在此计算机上的硬盘驱动器。我后来想重装,结果
是一样的提示。(连windows都不能重装)。后来进入BIOS,使用硬盘检测,fail掉了。以为是硬件坏了…幸好安装了ubuntu,可以顺利进入ubu
ntu,这说明硬件是没有问题的。继续搜索发现windows xp的OEM版本在同样的问题下也不能进入recover
console.我发现自己每次都是走的最长路径。微软说OEM不能进入recover console,然后就没有任何解决方案了…唉~.

无奈之下找了张番茄家园,可以进入DOS NTFS,然后选择DOS+NTFS的选项,进入后使用NTFSCHK,它说正在运行所以不能运行…无语,然后去win
dows/system32下找到chkdsk.exe 然后执行chkdsk /r,结果它说不能在DOS下运行…更加无语。无奈之后退出。

然后在番茄中选择xp引导修复,反正也是碰碰运气,再选择正常启动,结果终于看到了蓝色的自检画面。

之后检查了半个小时,终于进入了windows.

对于OEM的用户,修复过程可能如下:

使用番茄进入xp引导修复,选择正常启动或者前一次配置,然后done.

非OEM的用户:

使用windows安装盘,进入recover console,然后执行chkdsk c: /r /f 如果不行再使用fixboot

要是没有ubuntu,真的以为硬盘坏掉了。windows系统实在是太霸道了,害我差点想把整个硬盘重新格式化。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
// Adapter.cpp : Defines the entry point for the console application.
// author: chillyc
// email: chillycreator @t gmail.com

#include&lt;iostream&gt;
#include&lt;string&gt;
using namespace std;

/// adapter pattern is used for combining two or more classes,
/// which have the same behaviors but different interfaces.
/// some classes is common used in future, and the other which are special will never used.
/// common used classes should be public, and the other is private.
/// some classes which inherit adapter class will never use the special ones.
/// adapter pattern is divided into two patterns.
/// one is belong to class structure, and the other is belong to object structure.

#ifndef INTERFACEA_H
#define INTERFACEA_H
/// Interface A is a common interface!
class Interface_A{
public :
virtual void connect_com();
};
#endif
void Interface_A::connect_com(){
cout&lt;&lt;"connect a"&lt;&lt;endl;
}

#ifndef INTERFACEB_H
#define INTERFACEB_H
/// Interface B is not a common interface,
/// it will be used in some special area!
class Interface_B{
public :
virtual void connect_B();
};
#endif
void Interface_B::connect_B(){
cout&lt;&lt; "connect b"&lt;&lt;endl;
}

#ifndef ADAPTERCLASS_H
#define ADAPTERCLASS_H
/// this class uses private inheritance to construct adapter.
/// and it is a kind of class structure.
class Adapter_Class: public Interface_A, private Interface_B{
public:
Adapter_Class();
~Adapter_Class();
virtual void connect();
};

/// this class uses private member variable to construct adapter.
/// and it uses object relationship.
class Adapter_Object: public Interface_A{
private:
Interface_B * b;
public:
Adapter_Object();
~Adapter_Object();

virtual void connect();
};
#endif

Adapter_Class::Adapter_Class(){
cout&lt;&lt; "Adapter_Class construct"&lt;&lt;endl;

}
Adapter_Class::~Adapter_Class(){}
void Adapter_Class::connect(){
Interface_A::connect_com();
Interface_B::connect_B();
}

Adapter_Object::Adapter_Object(){
cout&lt;&lt;"Adapter_Object construct"&lt;&lt;endl;
b = new Interface_B();

}
Adapter_Object::~Adapter_Object(){
delete b;
}
void Adapter_Object::connect(){
Interface_A::connect_com();
b-&gt;connect_B();
}

int main()
{
Adapter_Class ac;
ac.connect();
Adapter_Object ao;
ao.connect();
return 0;
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
// composite.cpp : Defines the entry point for the console application.
//

#include&lt;iostream&gt;
#include&lt;string&gt;
#include&lt;vector&gt;

namespace pattern{
/// this pattern is composite pattern.
/// in this pattern, it like a tree to call the leaves function.
/// so there is an entry of high level (Graph), and each class has a function called "Draw"
/// the composite class is "Picture".
/// and the leaves are "Line" and "Point".
/// This pattern is combine many objects together which have same functions
/// and have level structures .
/// And the composite class is like a manager.
/// It has the same function also.
/// Benefits of this pattern is : outer class will never know the composite relationship;
/// outer class will deal the composite class only, not all of innerclass. and composite class
/// and inner class have same functions or level structures.
/// Do you think the composite class like a facade in facade pattern?
#ifndef GRAPH_H
#define GRAPH_H

class Graph{
protected:
std::string name;

public:
Graph(std::string name):name(name){std::cout&lt;&lt;"graph "&lt;&lt;name&lt;&lt;" construct"&lt;&lt;std::endl;}

virtual void Draw()=0;
virtual ~Graph(){std::cout&lt;&lt; "graph "&lt;&lt;name&lt;&lt; " destroy"&lt;&lt;std::endl;};
};
#endif

#ifndef PICTURE_H
#define PICTURE_H
class Picture:public Graph{
private:
std::vector&lt;Graph*&gt; list;
public:
Picture(std::string name):Graph(name){std::cout&lt;&lt;"Picture "&lt;&lt;name&lt;&lt;" construct!"&lt;&lt;std::endl;}
virtual void Add(Graph*);
virtual void Remove(Graph*);
virtual void Draw();
~Picture();
};

#endif
Picture::~Picture(){
list.clear();
std::cout&lt;&lt;"Picture destroy!"&lt;&lt;std::endl;
}
void Picture::Add(pattern::Graph * g){
list.push_back(g);
}
void Picture::Remove(pattern::Graph *g){
std::vector&lt;Graph*&gt;::iterator i=list.begin();
while(i!=list.end()){
if(g==*i){
list.erase(i);
break;
}
i++;
}
}
void Picture::Draw(){
std::vector&lt;Graph*&gt;::iterator i=list.begin();
while(i != list.end()){
(*i)-&gt;Draw();
i++;
}
}

#ifndef SHAPE_H
#define SHAPE_H
/// Shape class is parent class of "Line" and "Point"
class Shape:public Graph{
public:
virtual void Draw()=0;
Shape(std::string name):Graph(name){std::cout&lt;&lt;"Shape construct!"&lt;&lt;std::endl;}
virtual ~Shape(){std::cout&lt;&lt;"Shape destroy!"&lt;&lt;std::endl;}

};

#endif

#ifndef POINT_H
#define POINT_H
class Point:public Shape{
public:
Point(std::string name):Shape(name){std::cout&lt;&lt;"Point construct!"&lt;&lt;std::endl;}
~Point(){std::cout&lt;&lt;"Point destroy!"&lt;&lt;std::endl;}
virtual void Draw();

};
#endif
void Point::Draw(){
std::cout&lt;&lt;"Draw a point!"&lt;&lt;std::endl;
}

#ifndef LINE_H
#define LINE_H
class Line: public Shape{
public:
Line(std::string name):Shape(name){std::cout&lt;&lt;"Line construct!"&lt;&lt;std::endl;}
~Line(){std::cout&lt;&lt;"Line destroy!"&lt;&lt;std::endl;}
virtual void Draw();
};

#endif
void Line::Draw(){
std::cout&lt;&lt;"Draw a line!"&lt;&lt;std::endl;
}
}

int main()
{
pattern::Line l ("line");
pattern::Point p1 ("point 1");
pattern::Point p2("point 2");
pattern::Picture pic("Picture");
pic.Add(&amp;l);
pic.Add(&amp;p1);
pic.Add(&amp;p2);

pic.Draw();
// if you want destroy some shape, remove them first.
pic.Remove(&amp;p1);
p1.~Point();
pic.Draw();
return 0;
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
// Facade.cpp : Defines the entry point for the console application.
// author: chillyc
// email: chillycreator @t gmail.com

#include&lt;iostream&gt;

namespace pattern{
/// this pattern is facade pattern
/// facade pattern is for hiding relationship and behavior of inner classes .
/// client or outer class should only connect with facade class.
/// But it will not forbid accessing inner classes.
#ifndef INNERA_H
#define INNERA_H
class Inner_A{
public:
void Do(){std::cout&lt;&lt;"A"&lt;&lt;std::endl;}
};
#endif
#ifndef INNERB_H
#define INNERB_H
class Inner_B{
public:
void Do(){std::cout&lt;&lt;"B"&lt;&lt;std::endl;}
};
#endif

#ifndef FACADE_H
#define FACADE_H
class Facade{
private:
Inner_A* a;
Inner_B* b;
public:
Facade(){
a = new Inner_A();
b = new Inner_B();

}
void Do(){
a-&gt;Do();
b-&gt;Do();
}
~Facade(){
delete a;
delete b;
}
};
#endif
}

int main()
{
pattern::Facade f;
f.Do();
return 0;
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
// bridge.cpp : Defines the entry point for the console application.
//
/// author : chillyc
/// email : chillycreator @t gmail.com
/// uml:
/// _
/// / \
/// /_ _\

#include&lt;iostream&gt;

namespace pattern{

/// why use bridge pattern?
/// If the original parent class is not suitable for being inherited by subclass,
/// it will be refactor. And If there are some concepts are common,
/// it will be abstracted as implement interface or abstract class.
/// for example: in KFC, there will be some softdrink to be sold,
/// like coca cola, coff, and so on. And if you wish, you will add some additions like sugar,
/// or ice into softdrinks. If we design the classes as sugar-cocacola, sugar-coff, ice-cocacola,
/// and ice-coff. There will be four subclasses here. And in the future, is there add another
/// additions? If yes, the system will add another two classes! But if use bridge pattern,
/// it will add only one class called "another additions" inherited from addition class.
/// This is benefits of this pattern.

#ifndef ADDITION_H
#define ADDITION_H
/// this is the implement class in Bridge pattern.
/// if you want add another additions,
/// inherit this class and the point of your class into Softdrink class.
/// Do you have better implements for just adding class here and not modifying Softdrink class?
class Addition{
public:
virtual void Add()=0;
virtual ~Addition(){};
};
#endif

#ifndef SUGAR_H
#define SUGAR_H
class Sugar:public Addition{
public:
virtual void Add();
};
#endif
void Sugar::Add(){
std::cout&lt;&lt;"add sugar"&lt;&lt;std::endl;
}

#ifndef ICE_H
#define ICE_H
class Ice:public Addition{
public:
virtual void Add();
};
#endif
void Ice::Add(){
std::cout&lt;&lt;"add ice"&lt;&lt;std::endl;
}

#ifndef SOFTDRINK_H
#define SOFTDRINK_H
/// this class is the abstract class in Bridge pattern.
/// I consider there will be some other implement methods.
/// I use Addition objects as member variables,
/// and construct and destroy them in Softdrink.
/// But if there is no member variables of Addition, It will be ok.
/// for example: you can send Addition instances as parameters into Softdrink subclass.
/// But in Bridge pattern, the uml is aggregation between implement class and abstract class.
class Softdrink{
public:
Softdrink();
virtual void drink()=0;
virtual ~Softdrink()=0;
protected:
Addition *sugar;
Addition *ice;
/// another additions add here!
};
Softdrink::~Softdrink(){
if(NULL != sugar){
delete sugar;
}
if(NULL != ice){
delete ice;
}
}
Softdrink::Softdrink(){
sugar = new Sugar();
ice = new Ice();
}
#endif

#ifndef COFF_H
#define COFF_H

class Coff: public Softdrink{
public:

virtual void drink();

};
#endif
void Coff::drink(){
std::cout&lt;&lt;"I am drinking coff!"&lt;&lt;std::endl;
sugar-&gt;Add();
}

#ifndef COCA_H
#define COCA_H
class Coca: public Softdrink{
public:
virtual void drink();
};
#endif
void Coca::drink(){
std::cout&lt;&lt;"I am drinking coca cola!"&lt;&lt;std::endl;
ice-&gt;Add();
}

}

int main()
{

pattern::Coca coca;
coca.drink();
pattern::Coff coff;
coff.drink();
return 0;
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
// decorator.cpp : Defines the entry point for the console application.
// author: chillyc
// email: chillycreator @t gmail.com

#include&lt;iostream&gt;
namespace pattern{
/// this pattern is decorator pattern.
/// In this pattern the super class should have default process functions.
/// for example: "Read" has default read word function, and it is useful in the future.
/// Read_Char, Read_Chinese, Decorator inherit Read class.
/// But those three subclass is not powerful to deal with sentences.
/// Then the subclass of Decorator will deal with sentences, but it dose not know every word.
/// So Sentence(Encode) pattern has become.
/// But decorator pattern is not only dealing with this situation but also enhance some classes
/// capacity without adding new classes.
/// is it something like Bridge?
#ifndef READ_H
#define READ_H
class Read{
public:
Read(){}
virtual ~Read(){}

/// this is default process function.
/// and decorator class will use this function to read
virtual void ReadWord(){std::cout&lt;&lt;"default read!"&lt;&lt;std::endl;}
/// if the function is a pure virtual function,
/// decorator class need not inherit this class and
/// it just has an instance of Read as a member varible.
// virtual void ReadWord()=0;

};
#endif

#ifndef READCHAR_H
#define READCHAR_H
class Read_Char:public Read{
public:
Read_Char():Read(){}
~Read_Char(){}
virtual void ReadWord();
};
#endif
void Read_Char::ReadWord(){
std::cout&lt;&lt; "read a char"&lt;&lt;std::endl;

}

#ifndef READCHINESE_H
#define READCHINESE_H
class Read_Chinese:public Read{
public:
Read_Chinese():Read(){}
~Read_Chinese(){}
virtual void ReadWord();
};
#endif
void Read_Chinese::ReadWord(){
std::cout&lt;&lt;"read a chinese word"&lt;&lt;std::endl;
}

#ifndef DECORATOR_H
#define DECORATOR_H
class Decorator:public Read{
protected:
Read* r;
public:
Decorator():Read(){r = NULL;}
Decorator(Read* r):Read(),r(r){}
virtual ~Decorator(){if(r!=NULL) delete r;}
virtual void ReadWord();
};
#endif
void Decorator::ReadWord(){
if(NULL == r)
Read::ReadWord();
else
r-&gt;ReadWord();
}

#ifndef READSENTENCE_H
#define READSENTENCE_H
// this class is real work decorator class
class Read_Sentence:public Decorator{

public:
Read_Sentence():Decorator(){}
Read_Sentence(Read* r):Decorator(r){}
~Read_Sentence(){}
virtual void ReadWord();
};
#endif
void Read_Sentence::ReadWord(){
/// parent class method is called first!
Decorator::ReadWord();
/// then your method be called
std::cout&lt;&lt;"read a sentence"&lt;&lt;std::endl;
}
}

int main()
{
pattern::Read_Sentence rs1(new pattern::Read_Char());// read char
pattern::Read_Sentence rs2(new pattern::Read_Chinese());// read chinese
pattern::Read_Sentence rs3; // default read
rs1.ReadWord();
rs2.ReadWord();
rs3.ReadWord();
return 0;
}
0%