diff --git a/C++/标准库/12 动态内存.md b/C++/标准库/12 动态内存.md index 497143b0..19745cca 100644 --- a/C++/标准库/12 动态内存.md +++ b/C++/标准库/12 动态内存.md @@ -1,5 +1,16 @@ # 动态内存 +> 存在的问题:栈空间和堆空间的分配也是运行时内存分配,即动态内存分配。文字常量区、全局变量和静态变量区是在编译时内存分配,即静态内存分配。 +> +> 栈空间的动态内存分配由操作系统管理。堆空间的动态内存分配由用户自身管理。二者可以交叉使用。 +> +> 例如:使用栈空间无法返回局部对象,只能返回局部对象的复制(重写复制构造函数),比较麻烦,可以返回堆空间申请一个对象,并返回指向该对象的指针。 +> +> 例如:使用堆空间,对象的释放需要自己管理,可以在栈空间创建一个局部对象,在其内部封装申请和释放堆空间的方法。当栈空间的局部对象被销毁时,调用析构函数,清除堆空间的对象。这也是allocator和智能指针的实现方案。(allocator一般使用栈对象的析构函数,销毁堆对象的空间。智能指针一般通过引用计数的方法销毁堆对象。) +> +> 关于汇编语言程序有两种方法进行动态分配: +> 方法一:通过系统调用从操作系统获得内存块。(linux/windows操作系统提供了alloc方法和heap方法。在当前的进程中,后者用来申请新的私有堆,前者用来在已有的堆空间上申请内存。) +> 方法二:实现自己的堆管理器来服务更小的对象提出的请求。 ## 0 C++直接管理内存 @@ -38,6 +49,16 @@ const int * pci = new const int(1024); > 所有可变长度的容器,都有自己的allcator实现动态内存管理,不需要自己手动申请和释放内存。 + +### new和delete的工作机理 +* 当我们使用new表达式分配内存时,实际上执行了三个步骤。 + 1. 是调用名为operator new(或者 operator new[])的标准库函数。该函数分配一块原始的足够大的未构造内存 + 2. 编译器运行构造函数构造对象 + 3. 返回一个指向该对象的指针 +* 同样的,delete则执行两个步骤: + 1. 倒序执行对象的析构函数 + 2. 调用 operator delete或(operator delete[])标准库函数释放内存空间 + ## 1 动态内存与智能指针 > 所以智能指针使用过来做动态内存管理的。普通的局部变量及其指针,不需要智能指针。智能指针是辅助new delete来管理动态内存的。智能指针就是为了解决一下问题。 @@ -163,7 +184,7 @@ if(shared_ptrnp = wp.lock()){ > * weak_ptr能将shared_ptr和weak_ptr赋值给weak_ptr;不能将新的动态内存对象赋值给智能指针。reset会将指针置为空。 -## 4 动态数组 +## 5 动态数组 ### 初始化动态内存数组 ``` @@ -210,3 +231,82 @@ alloc.deallocate(p,n) * 标准库为allocator定义了两个伴随算法。 ![](image/2021-03-06-22-42-35.png) + +### allocator的简单实现 + +```C++ +#ifndef __JJALLOC__ +#define __JJALLOC__ +#include // for placement new +#include //for cerr +#include //for ptrdiff_t +#include // for exit() +#include // for UINT_MAX +namespace JJ{ + template + inline T* _allocate(ptrdiff_t size, T*){ + //set_new_handler(0); + T* tmp = (T*)(::operator new)((size_t)(size * sizeof(T))); + if (tmp == 0){ + std::cerr << "out of memory" << std::endl; + } + return tmp; + } + template + inline void _destory(T* ptr){ + ptr->~T(); + } + + + template + inline void _deallocate(T* buffer){ + ::operator delete(buffer); + } + + template + inline void _construct(T1 *p, const T2 &value){ + new(p)T1(value); + } + template + class allocate{ + public: + typedef T value_type; + typedef T* pointer; + typedef const T* const_pointer; + typedef T& reference; + typedef const T& const_reference; + typedef size_t size_type; + typedef ptrdiff_t diference_type; + + template + struct rebind{ + typedef allocator other; + }; + + pointer allocate(size_type n, const void * hint = 0){ + return _allocate((difference_type)n, (pointer)0); + } + void deallocate(pointer p, size_type n){ + _deallocate(p); + } + + void construct(pointer p, const_reference value){ + return _construct(p, value); + } + + void destroy(pointer p){ + _destroy(p); + } + pointer address(reference x){ + return (pointer)&x; + } + pointer const_address(const_reference x){ + return (const_pointer)&x; + } + + size_type max_size()const{ + return (size_type)(UINT_MAX / sizeof(T)); + } + }; +} +``` diff --git a/C++/面试/1.C++编译过程详解.md b/C++/面试/1.C++编译过程详解.md index e79e7e9d..734a4d2b 100644 --- a/C++/面试/1.C++编译过程详解.md +++ b/C++/面试/1.C++编译过程详解.md @@ -57,7 +57,7 @@ * 目标代码生成与优化:代码生成器将中间代码转成机器代码,这个过程是依赖于目标机器的,因为不同的机器有着不同的字长、寄存器、数据类型等。最后目标代码优化器对目标代码进行优化,比如选择合适的寻址方式、使用唯一来代替乘除法、删除出多余的指令等。 -三、汇编 +## 3 汇编 汇编过程调用汇编器as来完成,是用于将汇编代码转换成机器可以执行的指令,每一个汇编语句几乎都对应一条机器指令。 diff --git a/C++/面试/5.C++内存分配.md b/C++/面试/5.C++内存分配.md index 83899801..682574e5 100644 --- a/C++/面试/5.C++内存分配.md +++ b/C++/面试/5.C++内存分配.md @@ -42,4 +42,50 @@ int main() { strcpy(p1, "123456"); // 123456\0放在常量区,编译器可能将它与p3所指向的"123456"优化成一个地方 return 0; } -``` \ No newline at end of file +``` + + +## 2 关于栈和堆的内存分配与编译执行过程的再说明 + +### 说明 +1. **“编译器申请和释放栈内存空间”** 并不是说,在编译阶段就完成了内存空间的申请和释放,而是在编译阶段生成了**内存申请和释放的命令**。通过这些内存申请释放的机器指令,在执行阶段具体地完成内存的申请和释放。编译器负责生成这些命令,所以是编译器负责栈空间的管理。 +2. “栈”是一种数据结构,通过机器指令实现,而不是一种内存空间结构。通过生成的指令,操作具体的地址,移动地址的指针,实现栈的计算。 +3. 所以在编译阶段到底做了什么呢?当然是 + 1. **编译器自动生成了栈空间的申请和释放的机器指令,将指令的对象翻译为相对地址,实现栈的逻辑结构** 。 + 2. **用户实现了堆空间申请和释放的代码,编译器负责翻译为机器指令。但是没有相对地址,只有相对地址的指针** 。 +4. 在实行阶段,将程序装入内存,对相对地址进行重定位。执行过程中,完成栈和堆的空间分配操作。 + +### 关于一个典型问题的说明 + +``` +#include +using namespace std; + +int main(){ + int n=1; + cin>>n; + + int a=0; + //编译器提示数组的长度必须是常量(即编译器能够推断出数组的地址) + // 但是,编译器好像并没有报错而是采用了动态重定位的方式解决了运行时才能确定的数组的长度。 + // 反正用vector就不会出现这些问题了,因为他们的空间都是在堆上分配的。 + int b[n]; + int c=0; + cout<<&a<<" "<<&b<<" "<<&c<>c; + return 0; +} +``` +* 问题描述:如果在编译时进行内存分配,那么n、a、c的相对地址应该都是确定的,但是a的长度只能在运行时确定,那么a和c在编译的时候相对地址到底是多少呢? +* 解决方案:在《操作系统》中介绍,重定位主要有两种方式,静态重定位(装入的时候进行重定位)。动态重定位(执行过程中进行重定位)。使用动态重定位,在执行到int a[n]的时候,对c进行动态重定位,那么就可以解决问题了。这么说现在主流的操作系统、编译器都是动态重定位吗?大概是吧。 +* intelligence提示不能使用变量初始化数组的长度,因为编译器无法确定相对地址。但是实际编译过程中并不会报错,貌似是编译器采用了动态重定位技术,或者其他的方法。对于这种问题一般有两种解决方法: + * 让编译器自己解决(虽然提示不可以,但是编译器动态重定位的话应该行) + * 使用动态内存分配。malloc、new在堆上分配空间,就不会出问题。 + * 使用vector,本身就是在堆上分配空间。 + +### 相关章节 + +* 编译原理 +* 操作系统---内存管理---程序的装入与链接---重定位 +* C++---标准库---动态内存管理---new、delete +* C++---面试---C++编译过程详解、C++内存分配 \ No newline at end of file diff --git a/C++/面试/5.cpp b/C++/面试/5.cpp new file mode 100644 index 00000000..ce030b2f --- /dev/null +++ b/C++/面试/5.cpp @@ -0,0 +1,17 @@ +#include +using namespace std; + +int main(){ + int n=1; + cin>>n; + + int a=0; + //编译器提示数组的长度必须是常量(即编译器能够推断出数组的地址) + // 但是,编译器好像并没有报错而是采用了动态重定位的方式解决了运行时才能确定的数组的长度。 + // 反正用vector就不会出现这些问题了,因为他们的空间都是在堆上分配的。 + int b[n]; + int c=0; + cout<<&a<<" "<<&b<<" "<<&c<>c; + return 0; +} \ No newline at end of file diff --git a/工作日志/2021年4月10日-今日计划.md b/工作日志/2021年4月10日-今日计划.md index 92575733..31f87bce 100644 --- a/工作日志/2021年4月10日-今日计划.md +++ b/工作日志/2021年4月10日-今日计划.md @@ -1,6 +1,6 @@ ## 计划 -- [ ] 设计模式复习 +- [x] 设计模式复习 - [ ] vscode C++集成开发环境 - [ ] cmake/vs 项目重构 - [ ] 制定四月份论文阅读计划 diff --git a/工作日志/2021年4月8日-简历投递记录.md b/工作日志/2021年4月8日-简历投递记录.md index 1eedbffc..18a3bc88 100644 --- a/工作日志/2021年4月8日-简历投递记录.md +++ b/工作日志/2021年4月8日-简历投递记录.md @@ -70,7 +70,7 @@ * 投递 - [x] 简历投递 - [x] 素质测评 - - [ ] 2021年04月09日 19:00 - 2021年04月09日 20:00 + - [x] 2021年04月09日 19:00 - 2021年04月09日 20:00 > 二期简历 diff --git a/设计模式/0 设计模式概述.md b/设计模式/0 设计模式概述.md index 34376226..b088d0b5 100644 --- a/设计模式/0 设计模式概述.md +++ b/设计模式/0 设计模式概述.md @@ -359,7 +359,8 @@ secondName 这样做能把客户类和具体子类的实现解耦,客户类不再需要知道有哪些子类以及应当实例化哪个子类。客户类往往有多个,如果不使用简单工厂,那么所有的客户类都要知道所有子类的细节。而且一旦子类发生改变,例如增加子类,那么所有的客户类都要进行修改。 -

+![](image/2021-04-10-15-34-10.png) + ### Implementation @@ -442,7 +443,7 @@ public class Client { 下图中,Factory 有一个 doSomething() 方法,这个方法需要用到一个产品对象,这个产品对象由 factoryMethod() 方法创建。该方法是抽象的,需要由子类去实现。 -

+![](image/2021-04-10-15-32-27.png) ### Implementation @@ -506,7 +507,8 @@ public class ConcreteFactory2 extends Factory { 从高层次来看,抽象工厂使用了组合,即 Cilent 组合了 AbstractFactory,而工厂方法模式使用了继承。 -

+ +![](image/2021-04-10-15-26-15.png) ### Implementation @@ -596,7 +598,8 @@ public class Client { ### Class Diagram -

+ +![](image/2021-04-10-15-39-40.png) ### Implementation @@ -686,7 +689,7 @@ abcdefghijklmnopqrstuvwxyz ### Class Diagram -

+![](image/2021-04-10-15-44-20.png) ### Implementation @@ -747,7 +750,7 @@ abc - Handler:定义处理请求的接口,并且实现后继链(successor) -

+![](image/2021-04-10-15-45-13.png) ### Implementation @@ -885,13 +888,13 @@ request2 is handle by ConcreteHandler2 - Invoker:通过它来调用命令 - Client:可以设置命令与命令的接收者 -

+![](image/2021-04-10-15-36-32.png) ### Implementation 设计一个遥控器,可以控制电灯开关。 -

+![](image/2021-04-11-10-24-34.png) ```java public interface Command { @@ -1006,7 +1009,8 @@ public class Client { - TerminalExpression:终结符表达式,每个终结符都需要一个 TerminalExpression。 - Context:上下文,包含解释器之外的一些全局信息。 -

+ +![](image/2021-04-10-15-34-41.png) ### Implementation @@ -1131,7 +1135,9 @@ false - Iterator 主要定义了 hasNext() 和 next() 方法。 - Client 组合了 Aggregate,为了迭代遍历 Aggregate,也需要组合 Iterator。 -

+ +![](image/2021-04-10-15-29-46.png) + ### Implementation @@ -1220,17 +1226,17 @@ public class Client { - Mediator:中介者,定义一个接口用于与各同事(Colleague)对象通信。 - Colleague:同事,相关对象 -

+![](image/2021-04-10-15-46-30.png) + ### Implementation Alarm(闹钟)、CoffeePot(咖啡壶)、Calendar(日历)、Sprinkler(喷头)是一组相关的对象,在某个对象的事件产生时需要去操作其它对象,形成了下面这种依赖结构: -

- +![](image/2021-04-10-15-45-52.png) 使用中介者模式可以将复杂的依赖结构变成星形结构: -

+![](image/2021-04-10-15-45-58.png) ```java public abstract class Colleague { @@ -1390,7 +1396,8 @@ doSprinkler() - Caretaker:负责保存好备忘录 - Menento:备忘录,存储原始对象的的状态。备忘录实际上有两个接口,一个是提供给 Caretaker 的窄接口:它只能将备忘录传递给其它对象;一个是提供给 Originator 的宽接口,允许它访问到先前状态所需的所有数据。理想情况是只允许 Originator 访问本备忘录的内部状态。 -

+![](image/2021-04-10-15-19-24.png) + ### Implementation @@ -1563,7 +1570,8 @@ public class Client { 主题(Subject)是被观察的对象,而其所有依赖者(Observer)称为观察者。 -

+![](image/2021-04-11-10-27-18.png) + ### Class Diagram @@ -1571,13 +1579,13 @@ public class Client { 观察者(Observer)的注册功能需要调用主题的 registerObserver() 方法。 -

+![](image/2021-04-10-15-33-27.png) ### Implementation 天气数据布告板会在天气信息发生改变时更新其内容,布告板有多个,并且在将来会继续增加。 -

+![](image/2021-04-11-10-27-42.png) ```java public interface Subject { @@ -1698,13 +1706,13 @@ StatisticsDisplay.update: 1.0 1.0 1.0 ### Class Diagram -

+![](image/2021-04-10-15-48-21.png) ### Implementation 糖果销售机有多种状态,每种状态下销售机有不同的行为,状态可以发生转移,使得销售机的行为也发生改变。 -

+![](image/2021-04-10-15-48-03.png) ```java public interface State { @@ -2005,7 +2013,7 @@ No gumball dispensed - Strategy 接口定义了一个算法族,它们都实现了 behavior() 方法。 - Context 是使用到该算法族的类,其中的 doSomething() 方法会调用 behavior(),setStrategy(Strategy) 方法可以动态地改变 strategy 对象,也就是说能动态地改变 Context 所使用的算法。 -

+![](image/2021-04-10-15-22-33.png) ### 与状态模式的比较 @@ -2092,13 +2100,14 @@ quack! ### Class Diagram -

+ +![](image/2021-04-10-15-37-47.png) ### Implementation 冲咖啡和冲茶都有类似的流程,但是某些步骤会有点不一样,要求复用那些相同步骤的代码。 -

+![](image/2021-04-11-10-29-38.png) ```java public abstract class CaffeineBeverage { @@ -2195,7 +2204,8 @@ Tea.addCondiments - ConcreteVisitor:具体访问者,存储遍历过程中的累计结果 - ObjectStructure:对象结构,可以是组合结构,或者是一个集合。 -

+ +![](image/2021-04-10-15-31-46.png) ### Implementation @@ -2400,7 +2410,8 @@ Number of items: 6 ### Class Diagram -

+ +![](image/2021-04-10-15-35-35.png) ### Implementation @@ -2452,11 +2463,12 @@ public class Client { 把一个类接口转换成另一个用户需要的接口。 -

+![](image/2021-04-10-15-41-07.png) + ### Class Diagram -

+![](image/2021-04-10-15-40-27.png) ### Implementation @@ -2528,7 +2540,8 @@ public class Client { - Abstraction:定义抽象类的接口 - Implementor:定义实现类接口 -

+ +![](image/2021-04-10-15-38-25.png) ### Implementation @@ -2686,7 +2699,8 @@ public class Client { 组合对象拥有一个或者多个组件对象,因此组合对象的操作可以委托给组件对象去处理,而组件对象可以是另一个组合对象或者叶子对象。 -

+ +![](image/2021-04-10-15-48-55.png) ### Implementation @@ -2818,7 +2832,7 @@ Composite:root 装饰者(Decorator)和具体组件(ConcreteComponent)都继承自组件(Component),具体组件的方法实现不需要依赖于其它对象,而装饰者组合了一个组件,这样它可以装饰其它装饰者或者具体组件。所谓装饰,就是把这个装饰者套在被装饰者之上,从而动态扩展被装饰者的功能。装饰者的方法有一部分是自己的,这属于它的功能,然后调用被装饰者的方法实现,从而也保留了被装饰者的功能。可以看到,具体组件应当是装饰层次的最低层,因为只有具体组件的方法实现不需要依赖于其它对象。 -

+![](image/2021-04-10-15-47-29.png) ### Implementation @@ -2826,7 +2840,8 @@ Composite:root 下图表示在 DarkRoast 饮料上新增新添加 Mocha 配料,之后又添加了 Whip 配料。DarkRoast 被 Mocha 包裹,Mocha 又被 Whip 包裹。它们都继承自相同父类,都有 cost() 方法,外层类的 cost() 方法调用了内层类的 cost() 方法。 -

+ +![](image/2021-04-10-15-47-08.png) ```java public interface Beverage { @@ -2924,7 +2939,7 @@ public class Client { ### Class Diagram -

+![](image/2021-04-10-15-42-05.png) ### Implementation @@ -2983,7 +2998,7 @@ public class Client { - IntrinsicState:内部状态,享元对象共享内部状态 - ExtrinsicState:外部状态,每个享元对象的外部状态不同 -

+![](image/2021-04-10-15-43-43.png) ### Implementation @@ -3072,7 +3087,10 @@ Java 利用缓存来加速大量小对象的访问时间。 - 保护代理(Protection Proxy):按权限控制对象的访问,它负责检查调用者是否具有实现一个请求所必须的访问权限。 - 智能代理(Smart Reference):取代了简单的指针,它在访问对象时执行一些附加操作:记录对象的引用次数;当第一次引用一个对象时,将它装入内存;在访问一个实际对象前,检查是否已经锁定了它,以确保其它对象不能改变它。 -

+ + +![](image/2021-04-10-15-28-02.png) + ### Implementation diff --git a/设计模式/2 创建型设计模式.md b/设计模式/2 创建型设计模式.md index 411ecb44..fc72b320 100644 --- a/设计模式/2 创建型设计模式.md +++ b/设计模式/2 创建型设计模式.md @@ -1,88 +1,65 @@ -设计模式之美:Creational Patterns(创建型模式) +# Creational Patterns(创建型模式) -创建型模式(Creational Patterns)抽象了对象实例化过程。 +## 1 概述 -它们帮助一个系统独立于如何创建、组合和表示它的那些对象。 +### 目标 +创建型模式(Creational Patterns)**抽象了对象实例化过程**。 -- 一个类创建型模式使用继承改变被实例化的类。 +用于 **创建、组合和表示** 一个系统的所有对象。 -- 一个对象创建型模式将实例化委托给另一个对象。 +- 一个类创建型模式使用继承改变被实例化的类。 +- 一个对象创建型模式将实例化委托给另一个对象。 随着系统演化得越来越依赖于对象复合而不是类的继承,创建型模式变得更为重要。 在这些模式中,有两个不断出现的主旋律: 1. 它们都将关于该系统使用那些具体的类的信息封装起来。 - 2. 它们隐藏了这些类的实例是如何被创建和放在一起的。 -**因此,创建型模式在什么被创建,谁创建它,它是怎样被创建的,以及何时创建这些方面给予你很大的灵活性。** +> **因此,创建型模式在什么被创建,谁创建它,它是怎样被创建的,以及何时创建这些方面给予你很大的灵活性。** +> +> **Consequently, the creational patterns give you a lot of flexibility in what gets created, who creates it, how it gets created, and when.** -**Consequently, the creational patterns give you a lot of flexibility in what -gets created, who creates it, how it gets created, and when.** +## 2 具体方法 +### **Factory Method (工厂方法)** -- **Factory Method (工厂方法)** +- Define an interface for creating an object, but let subclasses decide which class to instantiate. Factory Method lets a class defer instantiation to subclasses. +- 定义一个用于创建目标对象的接口,让子类决定实例化哪一个目标类。Factory Method 使一个类的实例化延迟到其子类。 - - Define an interface for creating an object, but let subclasses decide - which class to instantiate. Factory Method lets a class defer - instantiation to subclasses. +### **Prototype (原型)** - - 定义一个用于创建目标对象的接口,让子类决定实例化哪一个目标类。Factory - Method 使一个类的实例化延迟到其子类。 +- Specify the kinds of objects to create using a prototypical instance,and create new objects by copying this prototype. -- **Prototype (原型)** +- 用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。 - - Specify the kinds of objects to create using a prototypical instance, - and create new objects by copying this prototype. +### **Abstract Factory (抽象工厂)** - - 用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。 +- Provide an interface for creating families of related or dependent objects without specifying their concrete classes. -- **Abstract Factory (抽象工厂)** +- 提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。 - - Provide an interface for creating families of related or dependent - objects without specifying their concrete classes. +### **Builder (生成器)** - - 提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。 +- Separate the construction of a complex object from its representation so that the same construction process can create different representations. -- **Builder (生成器)** +- 将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。 - - Separate the construction of a complex object from its representation so - that the same construction process can create different representations. +### **Singleton (单件)** - - 将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。 +- Ensure a class only has one instance, and provide a global point of access to it. +- 保证一个类仅有一个实例,并提供一个访问它的全局访问点。 -- **Singleton (单件)** - - - Ensure a class only has one instance, and provide a global point of - access to it. - - - 保证一个类仅有一个实例,并提供一个访问它的全局访问点。 - -用一个系统创建的那些对象的类对系统进行参数化有两种方法。 - -**方法一:生成创建对象的类的子类(Subclass);这对应于使用 Factory Method -模式。** - -这种方法的缺点是,仅为了改变产品类,就可能需要创建一个新的子类。这样的改变可能是级联的。 - -**方法二:对系统进行参数化的方法依赖于对象复合(Composition),定义一个对象负责明确产品对象的类,并将它作为该系统的参数。** - -这是 Abstract Factory、Builder、Prototype 模式的关键特征。 - -这三种模式都涉及到创建一个新的负责创建产品对象的“工厂对象”。 - -- Abstract Factory 由这个工厂对象产生多个类的对象。 - -- Builder 由这个工厂对象使用一个相对复杂的协议,逐步创建一个复杂产品。 - -- Prototype - 由该工厂对象通过拷贝原型对象来创建产品对象。在这种情况下,因为原型负责返回产品对象,所以工厂对象和原型是同一个对象。 +对**创建系统**进行参数化有两种方法: +* **方法一:依赖于被创建对象的类的继承(Subclass),定义被创建类的子类,并将它作为系统的参数** ;这对应于使用 Factory Method模式。这种方法的缺点是,仅为了改变产品类,就可能需要创建一个新的子类。这样的改变可能是级联的。 +* **方法二:依赖于对象复合(Composition),定义一个对象负责明确产品对象的类,并将它作为该系统的参数。** 这是 Abstract Factory、Builder、Prototype 模式的关键特征。这三种模式都涉及到创建一个**负责创建产品对象**的“工厂对象”。 + - Abstract Factory 由这个工厂对象产生多个类的对象。 + - Builder 由这个工厂对象使用一个相对复杂的协议,逐步创建一个复杂产品。 + - Prototype由该工厂对象通过拷贝原型对象来创建产品对象。在这种情况下,因为原型负责返回产品对象,所以工厂对象和原型是同一个对象。 Factory Method 使一个设计可以定制且只略微有一些复杂。其他设计模式需要新的类,而 Factory Method 只需要一个新的操作。 -使用 Abstract Factory、Builder、Prototype 的设计比使用 Factory Method -的设计更灵活,但它们也更加复杂。 +使用 Abstract Factory、Builder、Prototype 的设计比使用 Factory Method的设计更灵活,但它们也更加复杂。 -**通常,设计以使用 Factory Method -开始,并且当设计者发现需要更大的灵活性时,设计便会向其他创建型模式演化。** +**通常,设计以使用 Factory Method开始,并且当设计者发现需要更大的灵活性时,设计便会向其他创建型模式演化。** diff --git a/设计模式/2.3 工厂方法.md b/设计模式/2.3 工厂方法.md index 3c00c713..acb27e03 100644 --- a/设计模式/2.3 工厂方法.md +++ b/设计模式/2.3 工厂方法.md @@ -4,17 +4,11 @@ **意图** -定义一个用于创建目标对象的接口,让子类决定实例化哪一个目标类。 +定义一个用于创建目标对象的接口,让子类决定实例化哪一个目标类。Factory Method 使一个类的实例化延迟到其子类。 -Factory Method 使一个类的实例化延迟到其子类。 - -Define an interface for creating an object, but let subclasses decide which -class to instantiate. - -Factory Method lets a class defer instantiation to subclasses. +Define an interface for creating an object, but let subclasses decide which class to instantiate.Factory Method lets a class defer instantiation to subclasses. **结构** -![](image/2021-04-10-15-32-27.png) ![956473094863.png](media/2270a94077e069568d686166f5101fc9.png) diff --git a/设计模式/2.4 抽象工厂.md b/设计模式/2.4 抽象工厂.md index 20fc3e2c..c4b43499 100644 --- a/设计模式/2.4 抽象工厂.md +++ b/设计模式/2.4 抽象工厂.md @@ -17,8 +17,6 @@ 从高层次来看,抽象工厂使用了组合,即 Cilent 组合了 AbstractFactory,而工厂方法模式使用了继承。 -![](image/2021-04-10-15-26-15.png) - ![126081935533.png](media/abc2df6bb6578e6901711922fb704575.png) ### **参与者** diff --git a/设计模式/2.5 生成器.md b/设计模式/2.5 生成器.md index cf4f0bcb..6ad2eacf 100644 --- a/设计模式/2.5 生成器.md +++ b/设计模式/2.5 生成器.md @@ -3,7 +3,7 @@ 将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。 **结构** -![](image/2021-04-10-15-39-40.png) + ![215216159109.png](media/ebed27694b48db7da45d4f8a573d1001.png) **参与者** diff --git a/设计模式/2.6 原型模式.md b/设计模式/2.6 原型模式.md index 90aa5ffe..41d1bf2b 100644 --- a/设计模式/2.6 原型模式.md +++ b/设计模式/2.6 原型模式.md @@ -11,7 +11,7 @@ Specify the kinds of objects to create using a prototypical instance, and create new objects by copying this prototype. **结构** -![](image/2021-04-10-15-44-20.png) + ![049306316682.png](media/034ce7ebd324d04b21ef2ba935649ff9.png) **参与者** diff --git a/设计模式/3 结构型设计模式.md b/设计模式/3 结构型设计模式.md index 47616299..0417328b 100644 --- a/设计模式/3 结构型设计模式.md +++ b/设计模式/3 结构型设计模式.md @@ -1,128 +1,85 @@ -设计模式之美:Structural Patterns(结构型模式) +# Structural Patterns(结构型模式) +## 1 概述 +### 目标 结构型模式涉及到如何组合类和对象以获得更大的结构。 -- 结构型类模式采用继承机制来组合接口实现。 - -- 结构型对象模式不是对接口和实现进行组合,而是描述了如何对一些对象进行组合,从而实现新功能的一些方法。 +- 结构型类模式采用继承机制来组合接口实现。 +- 结构型对象模式不是对接口和实现进行组合,而是描述了如何对一些对象进行组合,从而实现新功能的一些方法。 因为可以在运行时改变对象组合关系,所以对象组合方式具有更大的灵活性,而这种机制用静态组合是不可能实现的。 -- **Adapter(适配器)** +### **Adapter(适配器)** - - 将一个类的接口转换成客户希望的另外一个接口。 +- 将一个类的接口转换成客户希望的另外一个接口。 +- Adapter 模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。 - - Adapter 模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。 - - Convert the interface of a class into another interface clients expect. +### **Bridge(桥接)** - - Adapter lets classes work together that couldn't otherwise because of - incompatible interfaces. +- 将抽象部分与它的实现部分分离,使它们都可以独立地变化。 -- **Bridge(桥接)** - - 将抽象部分与它的实现部分分离,使它们都可以独立地变化。 +### **Composite(组合)** - - Decouple an abstraction from its implementation so that the two can vary - independently. +- 将对象组合成树形结构以表示 “部分-整体” 的层次结构。 -- **Composite(组合)** +- Composite 使得用户对于单个对象和组合对象的使用具有一致性。 - - 将对象组合成树形结构以表示 “部分-整体” 的层次结构。 - - Composite 使得用户对于单个对象和组合对象的使用具有一致性。 +### **Decorator(装饰)** - - Compose objects into tree structures to represent part-whole - hierarchies. +- 动态地给一个对象添加一些额外的职责。 +- 就增加功能来说,Decorator 模式相比生成子类更为灵活。 - - Composite lets clients treat individual objects and compositions of - objects uniformly. +### **Facade(外观)** -- **Decorator(装饰)** +- 为子系统中的一组接口提供一个一致的界面。 - - 动态地给一个对象添加一些额外的职责。 +- Facade 模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。 - - 就增加功能来说,Decorator 模式相比生成子类更为灵活。 +### **Flyweight(享元)** - - Attach additional responsibilities to an object dynamically. +- 运用共享技术有效地支持大量细粒度的对象。 - - Decorators provide a flexible alternative to subclassing for extending - functionality. -- **Facade(外观)** +### **Proxy(代理)** - - 为子系统中的一组接口提供一个一致的界面。 +- 为其他对象提供一种代理以控制对这个对象的访问。 - - Facade 模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。 - - - Provide a unified interface to a set of interfaces in a subsystem. - - - Facade defines a higher-level interface that makes the subsystem easier - to use. - -- **Flyweight(享元)** - - - 运用共享技术有效地支持大量细粒度的对象。 - - - Use sharing to support large numbers of fine-grained objects - efficiently. - -- **Proxy(代理)** - - - 为其他对象提供一种代理以控制对这个对象的访问。 - - - Provide a surrogate or placeholder for another object to control access - to it. +## 2 对比 +### 相似性 结构型模式之间存在很多相似性,尤其是它们的参与者和协作之间的相似性。 这是因为结构型模式依赖于同一个很小的语言机制集合构造代码和对象: -- 单继承和多重继承机制用于基于类的模式。 +- 单继承和多重继承机制用于基于类的模式。 +- 对象组合机制用于对象式模式。 -- 对象组合机制用于对象式模式。 +### **Adapter 和 Bridge 的相似性** -**Adapter 和 Bridge 的相似性** +Adapter 模式和 Bridge模式具有一些共同的特征。它们之间的不同之处主要在于它们各自的用途。 +* Adapter模式主要是为了解决两个已有接口之间不匹配的问题。它不考虑这些接口时怎么实现的,也不考虑它们各自可能会如何演化。 +* Bridge 模式则对抽象接口和它的实现部分进行桥接。它为用户提供了一个稳定的接口。 +* Adapter 模式和 Bridge 模式通常被用于软件生命周期的不同阶段。 +* 当你发现两个不兼容的类必须同时工作时,就有必要使用 Adapter模式,以避免代码重复。此处耦合不可见。 +* 相反,Bridge的使用者必须事先知道:一个抽象将有多个实现部分,并且抽象和实现两者是独立演化得。 -Adapter 模式和 Bridge -模式具有一些共同的特征。它们之间的不同之处主要在于它们各自的用途。 +### **Composite 和 Decorator 的相似性** -Adapter -模式主要是为了解决两个已有接口之间不匹配的问题。它不考虑这些接口时怎么实现的,也不考虑它们各自可能会如何演化。 +Composite 和 Decorator模式具有类似的结构图,这说明它们都基于递归组合来组织可变数目的对象。 +* Decorator旨在使你能够不需要生成子类即可给对象添加职责。这就避免了静态实现所有功能组合,从而导致子类急剧增加。 +* Composite则有不同的目的,它旨在构造类,使多个相关的对象能够以统一的方式处理,而多重对象可以被当作一个对象来处理。它重点不在于修饰,而在于表示。 -Bridge 模式则对抽象接口和它的实现部分进行桥接。它为用户提供了一个稳定的接口。 - -Adapter 模式和 Bridge 模式通常被用于软件生命周期的不同阶段。 - -当你发现两个不兼容的类必须同时工作时,就有必要使用 Adapter -模式,以避免代码重复。此处耦合不可见。 - -相反,Bridge -的使用者必须事先知道:一个抽象将有多个实现部分,并且抽象和实现两者是独立演化得。 - -**Composite 和 Decorator 的相似性** - -Composite 和 Decorator -模式具有类似的结构图,这说明它们都基于递归组合来组织可变数目的对象。 - -Decorator -旨在使你能够不需要生成子类即可给对象添加职责。这就避免了静态实现所有功能组合,从而导致子类急剧增加。 - -Composite -则有不同的目的,它旨在构造类,使多个相关的对象能够以统一的方式处理,而多重对象可以被当作一个对象来处理。它重点不在于修饰,而在于表示。 - -**Decorator 和 Proxy 的相似性** +### **Decorator 和 Proxy 的相似性** Decorator 和 Proxy 模式描述了怎样为对象提供一定程度上的间接引用。 -Decorator 和 Proxy -对象的实现部分都保留了指向另一个对象的指针,它们向这个对象发送请求。 +Decorator 和 Proxy对象的实现部分都保留了指向另一个对象的指针,它们向这个对象发送请求。 同样,它们也具有不同的设计目的。 -Proxy -不能动态地添加和分离性质,它也不是为递归组合而设计的。它的目的是,当直接访问一个实体不方便或不符合需要时,为这个实体提供一个替代者。 - -在 Proxy 中,实体定义了关键功能,而 Proxy 提供对它的访问。 - -在 Decorator 中,组件仅提供了部分功能,而 Decorator 负责完成其他功能。 +* Proxy不能动态地添加和分离性质,它也不是为递归组合而设计的。它的目的是,当直接访问一个实体不方便或不符合需要时,为这个实体提供一个替代者。 +* 在 Proxy 中,实体定义了关键功能,而 Proxy 提供对它的访问。 +* 在 Decorator 中,组件仅提供了部分功能,而 Decorator 负责完成其他功能。 diff --git a/设计模式/3.1 适配器.md b/设计模式/3.1 适配器.md index 75234447..76b4fab1 100644 --- a/设计模式/3.1 适配器.md +++ b/设计模式/3.1 适配器.md @@ -7,8 +7,6 @@ 将一个类的接口转换成客户希望的另外一个接口。 Adapter 模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。 -![](image/2021-04-10-15-41-07.png) - **结构** 类适配器使用多重继承对一个接口与另一个接口进行匹配。 @@ -19,7 +17,6 @@ Adapter 模式使得原本由于接口不兼容而不能一起工作的那些类 ![006051933731.png](media/9bae3ff976c8470b1d6ae9e9768409e4.png) -![](image/2021-04-10-15-40-27.png) **参与者** Target diff --git a/设计模式/3.2 桥接.md b/设计模式/3.2 桥接.md index da1a5746..d4faf4c2 100644 --- a/设计模式/3.2 桥接.md +++ b/设计模式/3.2 桥接.md @@ -12,7 +12,7 @@ Decouple an abstraction from its implementation so that the two can vary independently. **结构** -![](image/2021-04-10-15-38-25.png) + ![242197409687.png](media/ee4a265f47725eacf53741680d262704.png) **参与者** diff --git a/设计模式/3.3 组合.md b/设计模式/3.3 组合.md index fc6d35c0..1508f70f 100644 --- a/设计模式/3.3 组合.md +++ b/设计模式/3.3 组合.md @@ -17,7 +17,6 @@ uniformly. ![120529122324.png](media/f2793f123ffd3e6517ffca83c3b4218e.png) -![](image/2021-04-10-15-48-55.png) **参与者** Component diff --git a/设计模式/3.4 装饰器.md b/设计模式/3.4 装饰器.md index b61fef22..77dd08e5 100644 --- a/设计模式/3.4 装饰器.md +++ b/设计模式/3.4 装饰器.md @@ -14,7 +14,7 @@ Decorators provide a flexible alternative to subclassing for extending functionality. **结构** -![](image/2021-04-10-15-47-29.png) + ![225319129467.png](media/688b6a2cfb78ed1f0b1a37b98f116dc9.png) **参与者** diff --git a/设计模式/3.5 外观.md b/设计模式/3.5 外观.md index 4d62fda8..83405371 100644 --- a/设计模式/3.5 外观.md +++ b/设计模式/3.5 外观.md @@ -7,7 +7,6 @@ Provide a unified interface to a set of interfaces in a subsystem. Facade defines a higher-level interface that makes the subsystem easier to use. **结构** -![](image/2021-04-10-15-42-05.png) ![000329435265.png](media/d95ed5b46b2cab7212804a212475ebef.png) **参与者** diff --git a/设计模式/3.6 享元.md b/设计模式/3.6 享元.md index e64306f4..3b615732 100644 --- a/设计模式/3.6 享元.md +++ b/设计模式/3.6 享元.md @@ -5,7 +5,7 @@ Use sharing to support large numbers of fine-grained objects efficiently. **结构** -![](image/2021-04-10-15-43-43.png) + ![135082566859.png](media/322c8a847832fc5d2385537079343d7c.png) 下面的对象图说明了如何共享 Flyweight: diff --git a/设计模式/3.7 代理.md b/设计模式/3.7 代理.md index 2abd6162..a07ebfd6 100644 --- a/设计模式/3.7 代理.md +++ b/设计模式/3.7 代理.md @@ -19,8 +19,6 @@ Provide a surrogate or placeholder for another object to control access to it. - 保护代理(Protection Proxy):按权限控制对象的访问,它负责检查调用者是否具有实现一个请求所必须的访问权限。 - 智能代理(Smart Reference):取代了简单的指针,它在访问对象时执行一些附加操作:记录对象的引用次数;当第一次引用一个对象时,将它装入内存;在访问一个实际对象前,检查是否已经锁定了它,以确保其它对象不能改变它。 -![](image/2021-04-10-15-28-02.png) - ![505114124457.png](media/c13421b53c7c2b2146d2198f7ac4f85b.png) 运行时一种可能的 Proxy 结构的对象图: diff --git a/设计模式/4 行为型设计模式.md b/设计模式/4 行为型设计模式.md index 64cea2b9..3d821406 100644 --- a/设计模式/4 行为型设计模式.md +++ b/设计模式/4 行为型设计模式.md @@ -1,119 +1,78 @@ -行为型模式涉及到算法和对象间职责的分配。 +# 行为型模式涉及到算法和对象间职责的分配。 +## 1 概述 + +### 目标 行为模式不仅描述对象或类的模式,还描述它们之间的通信模式。 这些模式刻划了在运行时难以跟踪的复杂的控制流。它们将你的注意力从控制流转移到对象间的联系方式上来。 -- 行为类模式使用继承机制在类间分派行为。 +- 行为类模式使用继承机制在类间分派行为。 +- 行为对象模式使用对象复合而不是继承。描述一组对等的对象怎样相互协作以完成任一个对象都无法完成的任务。 -- 行为对象模式使用对象复合而不是继承。描述一组对等的对象怎样相互协作以完成任一个对象都无法完成的任务。 +## 2 **行为型模式** -**行为型模式** +### **Chain of Responsibility(职责链)** -- **Chain of Responsibility(职责链)** +- 使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。 - - 使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。 +- 将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它位置。 - - 将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它位置。 +### **Command(命令)** - - Avoid coupling the sender of a request to its receiver by giving more - than one object a chance to handle the request. +- 将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤销的操作。 - - Chain the receiving objects and pass the request along the chain until - an object handles it. -- **Command(命令)** +### **Interpreter(解释器)** - - 将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤销的操作。 +- 给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。 - - Encapsulate a request as an object, thereby letting you parameterize - clients with different requests, queue or log requests, and support - undoable operations. +### **Iterator(迭代器)** -- **Interpreter(解释器)** +- 提供一种方法顺序访问一个聚合对象中各个元素,而又不需暴露该对象的内部表示。 - - 给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。 +### **Observer(观察者)** - - Given a language, define a represention for its grammar along with an - interpreter that uses the representation to interpret sentences in the - language. +- 定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。 -- **Iterator(迭代器)** - - 提供一种方法顺序访问一个聚合对象中各个元素,而又不需暴露该对象的内部表示。 +### **Mediator(中介者)** - - Provide a way to access the elements of an aggregate object sequentially - without exposing its underlying representation. +- 用一个中介对象来封装一系列的对象交互。 -- **Observer(观察者)** +- 中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。 - - 定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。 - - Define a one-to-many dependency between objects so that when one object - changes state, all its dependents are notified and updated - automatically. +### **Memento(备忘录)** -- **Mediator(中介者)** +- 在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态。 - - 用一个中介对象来封装一系列的对象交互。 - - 中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。 +### **State(状态)** - - Define an object that encapsulates how a set of objects interact. +- 允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它的类。 - - Mediator promotes loose coupling by keeping objects from referring to - each other explicitly, and it lets you vary their interaction - independently. +### **Strategy(策略)** -- **Memento(备忘录)** +- 定义一系列的算法,把它们一个个封装起来,并且使它们可以相互替换。使得算法可独立于使用它的客户而变化。 - - 在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态。 - - Without violating encapsulation, capture and externalize an object's - internal state so that the object can be restored to this state later. +### **Template Method(模板方法)** -- **State(状态)** +- 定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。 - - 允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它的类。 +- Template Method使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。 - - Allow an object to alter its behavior when its internal state changes. - The object will appear to change its class. -- **Strategy(策略)** +### **Visitor(访问者)** - - 定义一系列的算法,把它们一个个封装起来,并且使它们可以相互替换。使得算法可独立于使用它的客户而变化。 +- 表示一个作用于某对象结构中的各元素的操作。 - - Define a family of algorithms, encapsulate each one, and make them - interchangeable. +- Visitor 使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。 - - Strategy lets the algorithm vary independently from clients that use it. -- **Template Method(模板方法)** - - - 定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。 - - - Template Method - 使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。 - - - Define the skeleton of an algorithm in an operation, deferring some - steps to subclasses. - - - Template Method lets subclasses redefine certain steps of an algorithm - without changing the algorithm's structure. - -- **Visitor(访问者)** - - - 表示一个作用于某对象结构中的各元素的操作。 - - - Visitor 使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。 - - - Represent an operation to be performed on the elements of an object - structure. - - - Visitor lets you define a new operation without changing the classes of - the elements on which it operates. - -**封装变化** +## 3 说明 +### **封装变化** 当一个程序的某些方面的特征经常发生改变时,行为型模式就定义一个封装这个方面的对象。 @@ -121,17 +80,17 @@ 这些模式通常定义一个抽象类来描述这些封装变化的对象,并且通常该模式依赖这个对象来命名。 -- 一个 Strategy 对象封装一个 Algorithm。 +- 一个 Strategy 对象封装一个 Algorithm。 -- 一个 State 对象封装一个与状态相关的行为。 +- 一个 State 对象封装一个与状态相关的行为。 -- 一个 Mediator 对象封装对象间的协议。 +- 一个 Mediator 对象封装对象间的协议。 -- 一个 Iterator 对象封装访问和遍历一个聚合对象中的各个构件的方法。 +- 一个 Iterator 对象封装访问和遍历一个聚合对象中的各个构件的方法。 大多数模式有两种对象:封装该方面特征的新对象,和使用这些新的对象的已有对象。 -**对象作为参数** +### **对象作为参数** 一些模式引入总是被用作参数的对象。例如一个 Visitor 对象是一个多态的 Accept 操作的参数。 diff --git a/设计模式/4.1 责任链.md b/设计模式/4.1 责任链.md index c74c39b6..ff32b47b 100644 --- a/设计模式/4.1 责任链.md +++ b/设计模式/4.1 责任链.md @@ -19,7 +19,6 @@ handles it. ![212009985862.png](media/dd67bc16239c21383f68dac90175918b.png) -![](image/2021-04-10-15-45-13.png) **参与者** Handler diff --git a/设计模式/4.10 模板方法.md b/设计模式/4.10 模板方法.md index adaea9d3..9bf1bc20 100644 --- a/设计模式/4.10 模板方法.md +++ b/设计模式/4.10 模板方法.md @@ -6,7 +6,6 @@ Template Method 使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。 **结构** -![](image/2021-04-10-15-37-47.png) ![618336243562.png](media/62502293d8ec3c5ee0cb6130ba088ad9.png) **参与者** @@ -50,6 +49,7 @@ ConcreteClass 冲咖啡和冲茶都有类似的流程,但是某些步骤会有点不一样,要求复用那些相同步骤的代码。 +![](image/2021-04-11-10-29-38.png) ```java public abstract class CaffeineBeverage { diff --git a/设计模式/4.11 访问者.md b/设计模式/4.11 访问者.md index 01c4d41f..c65775bf 100644 --- a/设计模式/4.11 访问者.md +++ b/设计模式/4.11 访问者.md @@ -12,7 +12,6 @@ elements on which it operates. **结构** -![](image/2021-04-10-15-31-46.png) ![659484684950.png](media/2b90215e2319cee7220018f7e74ac572.png) diff --git a/设计模式/4.12 空对象.md b/设计模式/4.12 空对象.md index 7651a2a3..df82c012 100644 --- a/设计模式/4.12 空对象.md +++ b/设计模式/4.12 空对象.md @@ -9,7 +9,7 @@ that offers suitable default do nothing behavior. In short, a design where "nothing will come of nothing". **结构** -![](image/2021-04-10-15-35-35.png) + ![352014475871.png](media/449673a26c6c7fbe0fe391c24734c75a.png) **参与者** diff --git a/设计模式/4.2 命令.md b/设计模式/4.2 命令.md index 0b6f4cd9..18ef9eeb 100644 --- a/设计模式/4.2 命令.md +++ b/设计模式/4.2 命令.md @@ -12,7 +12,7 @@ Encapsulate a request as an object, thereby letting you parameterize clients with different requests, queue or log requests, and support undoable operations. **结构** -![](image/2021-04-10-15-36-32.png) + ![315146708441.png](media/31e9acd8d4ae264b538586670f9ffed9.png) **参与者** diff --git a/设计模式/4.3 解释器.md b/设计模式/4.3 解释器.md index a9562466..4b20f81a 100644 --- a/设计模式/4.3 解释器.md +++ b/设计模式/4.3 解释器.md @@ -6,7 +6,7 @@ Given a language, define a represention for its grammar along with an interpreter that uses the representation to interpret sentences in the language. **结构** -![](image/2021-04-10-15-34-41.png) + ![152516715319.png](media/a6c50fe1fcfff1a376d34e0af97ace54.png) **参与者** diff --git a/设计模式/4.4 迭代器.md b/设计模式/4.4 迭代器.md index e0e03c03..6b4eda1d 100644 --- a/设计模式/4.4 迭代器.md +++ b/设计模式/4.4 迭代器.md @@ -7,7 +7,6 @@ ### **结构** -![](image/2021-04-10-15-29-46.png) ![207254216383.png](media/2b415d88952f47d7d4cd707cbc009287.png) diff --git a/设计模式/4.5 中介者.md b/设计模式/4.5 中介者.md index 6f2d6bc5..e1eb972b 100644 --- a/设计模式/4.5 中介者.md +++ b/设计模式/4.5 中介者.md @@ -10,7 +10,6 @@ Mediator promotes loose coupling by keeping objects from referring to each other explicitly, and it lets you vary their interaction independently. **结构** -![](image/2021-04-10-15-46-30.png) ![217545939801.png](media/7425d22312c40949be9309f07a4f5078.png) diff --git a/设计模式/4.6 备忘录.md b/设计模式/4.6 备忘录.md index ba29a51b..c32f8dd2 100644 --- a/设计模式/4.6 备忘录.md +++ b/设计模式/4.6 备忘录.md @@ -7,8 +7,6 @@ 在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态。 **结构** -![](image/2021-04-10-15-19-24.png) - ![229273589556.png](media/5870f1e66b4dba9e3f59dcd29cf0f8bd.png) **参与者** diff --git a/设计模式/4.7 观察者.md b/设计模式/4.7 观察者.md index 075c3121..a1aacb34 100644 --- a/设计模式/4.7 观察者.md +++ b/设计模式/4.7 观察者.md @@ -10,7 +10,6 @@ **结构** -![](image/2021-04-10-15-33-27.png) ![244171718081.png](media/7f6de13b5ce6b6c8c6ed6422472d1c32.png) @@ -69,7 +68,7 @@ ConcreteObserver 天气数据布告板会在天气信息发生改变时更新其内容,布告板有多个,并且在将来会继续增加。 -

+![](image/2021-04-11-10-27-42.png) ```java public interface Subject { diff --git a/设计模式/4.8 状态.md b/设计模式/4.8 状态.md index 5244a189..5a0d09d4 100644 --- a/设计模式/4.8 状态.md +++ b/设计模式/4.8 状态.md @@ -4,7 +4,7 @@ 允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它的类。 **结构** -![](image/2021-04-10-15-48-21.png) + ![547252187237.png](media/de271ae3dd89c9f862ae1b16714ff5db.png) **参与者** diff --git a/设计模式/4.9 策略.md b/设计模式/4.9 策略.md index a776fbd3..5f5a0f29 100644 --- a/设计模式/4.9 策略.md +++ b/设计模式/4.9 策略.md @@ -10,7 +10,7 @@ 定义一系列的算法,把它们一个个封装起来,并且使它们可以相互替换。使得算法可独立于使用它的客户而变化。 ### **结构** -![](image/2021-04-10-15-22-33.png) + ![559166861981.png](media/28cabe60fc8136de5c80e251000dd2ee.png) ### **参与者** diff --git a/设计模式/image/2021-04-11-10-24-34.png b/设计模式/image/2021-04-11-10-24-34.png new file mode 100644 index 00000000..e543d076 Binary files /dev/null and b/设计模式/image/2021-04-11-10-24-34.png differ diff --git a/设计模式/image/2021-04-11-10-27-18.png b/设计模式/image/2021-04-11-10-27-18.png new file mode 100644 index 00000000..dda33692 Binary files /dev/null and b/设计模式/image/2021-04-11-10-27-18.png differ diff --git a/设计模式/image/2021-04-11-10-27-42.png b/设计模式/image/2021-04-11-10-27-42.png new file mode 100644 index 00000000..94564dbd Binary files /dev/null and b/设计模式/image/2021-04-11-10-27-42.png differ diff --git a/设计模式/image/2021-04-11-10-29-38.png b/设计模式/image/2021-04-11-10-29-38.png new file mode 100644 index 00000000..1d0d29b6 Binary files /dev/null and b/设计模式/image/2021-04-11-10-29-38.png differ