带你搞懂设计模式

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 }
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页