1.UML图
2. 常见设计模式
(1) 工厂模式
1)简单工厂:
简单工厂是工厂模式最简单的一种实现,对于不同产品的创建定义一个工厂类,将产品的类型作为参数传入到工厂的创建函数,根据类型分支选择不同的产品构造函数。
2) 工厂方法:
工厂方法模式在简单工厂模式的基础上增加对工厂的基类抽象,不同的产品创建采用不同的工厂创建(从工厂的抽象基类派生),这样创建不同的产品过程就由不同的工厂分工解决。(基类抽象,增加了开闭原则,便于产品扩展)
3)抽象工厂:
抽象工厂方法适用于产品种类结构多的场合,就是当具有多个抽象产品类型时,抽象工厂便可以派上用场。
抽象工厂模式更适合实际情况,受生产线所限,让低端工厂生产不同种类的低端产品,高端工厂生产不同种类的高端产品。
(2) 策略模式:
策略模式定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换。策略模式让算法独立于使用它的客户而独立变化。
(3) 单例模式:
保证一个类只有一个实例,并提供一个访问它的全局访问点,使得系统中只有唯一的一个对象实例。(简单,功能单一,适合管理资源,日志等)参考多线程的单例模式。
1)饿汉模式:
在类加载时就完成了初始化,但是加载比较慢,获取对象比较快,类一加载就实例化。
2)懒汉模式:
在类加载的时候不被初始化,第一次被引用时才实例化
(4) 装饰模式:
动态的给对象添加一些额外的职责
(5) 代理模式:
为其他对象提供一种代理,以控制对这个对象的访问(相当于媒人)
3. 设计模式常见五项原则
(1)单一职责原则
单一职责有2个含义,一个是避免相同的职责分散到不同的类中,另一个是避免一个类承担太多职责。减少类的耦合,提高类的复用性。
(2)接口隔离原则
表明客户端不应该被强迫实现一些他们不会使用的接口,应该把胖接口中额方法分组,然后用多个接口代替它,每个接口服务于一个子模块。简单说,就是使用多个专门的接口比使用单个接口好很多。
该原则观点如下:
1)一个类对另外一个类的依赖性应当是建立在最小的接口上
2)客户端程序不应该依赖它不需要的接口方法。
(3)开放-封闭原则
open模块的行为必须是开放的、支持扩展的,而不是僵化的。
closed在对模块的功能进行扩展时,不应该影响或大规模影响已有的程序模块。一句话概括:一个模块在扩展性方面应该是开放的而在更改性方面应该是封闭的。
核心思想就是对抽象编程,而不对具体编程。
(4)里氏替换原则
子类型必须能够替换掉他们的父类型、并出现在父类能够出现的任何地方。
主要针对继承的设计原则
1)父类的方法都要在子类中实现或者重写,并且派生类只实现其抽象类中生命的方法,而不应当给出多余的,方法定义或实现。
2)在客户端程序中只应该使用父类对象而不应当直接使用子类对象,这样可以实现运行期间绑定。
(5)迪米特法则
如果两个类不必彼此直接通信,那么两个就不应当发生直接的相互作用。如果其中一个类需要调用另一类的某一个方法的话,可以直接通过第三者转发这个调用。
(6)依赖倒置原则
上层模块不应该依赖于下层模块,他们共同依赖于一个抽象,即:父类不能依赖子类,他们都要依赖抽象类。抽象不能依赖于具体,具体应该要依赖于抽象。
生产消费模式
这里使用环形队列来实现生产者与消费者的写与读过程。首先我们知道队列的底层存储数据的方式其实就是一个数组,只要控制好对于队头和队尾的相关计算,我们就可以实现循环队列,而生产者依旧是在有空间的时候进行存放数据,没有空间时进入挂起等待状态,消费者则是在有数据时进行取数据,没有数据时进行挂起等待操作,这样我们便可以实现生产者和消费模型
1 #include <stdlib.h>
2 #include <pthread.h>
3 #include <stdio.h>
4 #include <semaphore.h>
5 #include <unistd.h>
6
7 #define NUM 4
8 int queue[NUM];//循环队列长度
9
10 sem_t blank_number, product_number;
11
12 void *producer(void *arg)
13 {
14 int p = 0;
15 while(1){
16 sem_wait(&blank_number);//等待信号量,信号量减1
17 queue[p] = rand() % 1000 + 1;//循环队列头
18 printf("produce %d\n", queue[p]);
19 p = (p + 1) % NUM;
20 sem_post(&product_number);//信号量增加1
21 sleep(1);
22
23 }
24 }
25
26 void *consumer(void *arg)
27 {
28 int c = 0, i;
29 while(1) {
30 sem_wait(&product_number);
31 for(i=0; i < NUM; i++) {
32 printf("%d ", queue[i]);
33 }
34 putchar('\n');
35
36 printf("consume %d\n", queue[c]);
37 queue[c] = 0;
38 sem_post(&blank_number);
39 c = (c+1)%NUM;
40 sleep(3);
4
42 }
43 }
44
45 int main()
46 {
47 pthread_t pid, cid;
48
49
50 sem_init(&blank_number, 0, NUM);
51 sem_init(&product_number, 0, 0);
52 pthread_create(&pid, NULL, producer, NULL);//创建线程
53 pthread_create(&cid, NULL, consumer, NULL);
54 pthread_join(pid, NULL);//等待线程结束
55 pthread_join(cid, NULL);
56 sem_destroy(&blank_number);//销毁信号量
57 sem_destroy(&product_number);
58 return 0;
59 }