我是靠谱客的博主 大胆萝莉,这篇文章主要介绍装饰器模式、适配器模式装饰器模式、适配器模式,现在分享给大家,希望可以做个参考。

装饰器模式、适配器模式

1.Decorator 装饰器模式

基本原理

装饰器模式主要解决继承关系过于复杂的问题,通过组合来替代继承。它主要的作用是给原始类添加增强功能。这也是判断是否该用装饰器模式的一个重要的依据。除此之外,装饰器模式还有一个特点,那就是可以对原始类嵌套使用多个装饰器。为了满足这个应用场景,在设计的时候,装饰器类需要跟原始类继承相同的抽象类或者接口

  • Component Interface:对象的接口(共可装饰类和装饰类使用)
  • Component:可装饰的对象
  • Decorator:装饰器类,将额外任务应用于组件的类,它还实现了相同的组件接口

在这里插入图片描述

复制代码
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
interface IComponent { method(): string } //生成装饰器对象的类 class Component implements IComponent { method(): string { return 'Component Method' } } //装饰器类 class Decorator implements IComponent { #object: IComponent // 接受一个被装饰类 constructor(object: IComponent) { this.#object = object } method(): string { return `Decorator Method(${this.#object.method()})` } } const COMPONENT = new Component() console.log(COMPONENT.method()) //Component Method // Component类被Decorator类装饰 const Decorated = new Decorator(COMPONENT) console.log(Decorated.method()) //Decorator Method(Component Method) //被装饰过的类Component可以在被装饰(套娃咯) const Decorated2 = new Decorator(Decorated) console.log(Decorated2.method()) //Decorator Method(Decorator Method(Component Method))

应用举例

让我们创建一个名为Value类来保存一个数组,然后添加对数字(Value)进行加法 (Add)和减法 (Sub) 的装饰器来实现给对象添加新的功能,而不改变对象本身的。

AddSub 装饰器可以直接接受数字、自定义 Value 对象或其他 AddSub 装饰器

在这里插入图片描述

复制代码
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
interface IValue { value: number } class Sub implements IValue { value: number constructor(val1: IValue | number, val2: IValue | number) { const left = Object.prototype.hasOwnProperty.call(val1, 'value') ? (val1 as IValue).value : (val1 as number) const right = Object.prototype.hasOwnProperty.call(val2, 'value') ? (val2 as IValue).value : (val2 as number) this.value = left - right } } class Add implements IValue { value: number constructor(val1: IValue | number, val2: IValue | number) { const left = Object.prototype.hasOwnProperty.call(val1, 'value') ? (val1 as IValue).value : (val1 as number) const right = Object.prototype.hasOwnProperty.call(val2, 'value') ? (val2 as IValue).value : (val2 as number) this.value = left + right } } //装饰器类 class Value implements IValue { value: number constructor(value: number) { this.value = value } } //装饰器 const A = new Value(1) const B = new Value(2) const C = new Value(5) console.log(new Add(A, B).value) //3 console.log(new Add(A, 100).value) //101 console.log(new Sub(C, A).value) //4 console.log(new Sub(new Add(C, B), A).value) //6 console.log(new Sub(100, 101).value) //-1 console.log(new Add(new Sub(new Add(C, B), A), 100).value)//106 console.log(new Sub(123, Add(C, C)).value)//113 console.log(new Add(new Sub(new Add(C, 10), A), 100).value) //114 console.log(A.value) //1 console.log(B.value) //2 console.log(C.value) //5

2.Adapter适配器模式

一个比较常用构造型设计模式——Adapter适配器模式,关于适配器模式,我们主要需要学习它的两种实现方式,类适配器对象适配器,以及 5 种常见的应用场景

基本原理

适配器模式的英文翻译是 Adapter Design Pattern。顾名思义,这个模式就是用来做适配的,它将不兼容的接口转换为可兼容的接口,让原本由于接口不兼容而不能一起工作的类可以一起工作。对于这个模式,有一个经常被拿来解释它的例子,就是 USB 转接头充当适 配器,把两种不兼容的接口,通过转接变得可以一起工作。

比如:你可能有两个相似的类,但它们具有不同的方法签名,因此你在其中一个方法签名之上创建一个适配器,以便更容易在调用时中实现和扩展

适配器模式与前面的装饰器模式有些类似,都是创建完对象后使用,不过设配器模式不能像装饰器模式一样递归调用

在这里插入图片描述

  • Target: 需要适配的目标接口/类
  • Adapter:适配器类
  • Adapter Interface: 适配器需要实现的接口,以使目标与客户端兼容(插口和线同)
  • Client:调用适配器的应用程序
复制代码
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
// Adapter Concept Sample Code interface IA { methodA(): void } class ClassA implements IA { methodA() { console.log('method A') } } interface IB { methodB(): void } class ClassB implements IB { methodB() { console.log('method B') } } class ClassBAdapter implements IA { //ClassB中没有methodA,所以就需要创建适配器来兼容 #classB: ClassB constructor() { this.#classB = new ClassB() } methodA() { 'calls the class b method_b instead' this.#classB.methodB() } } const ITEMS = [new ClassA(), new ClassB()] ITEMS.forEach((item) => { if (item instanceof ClassB) { item.methodB() } else { item.methodA() } }) const ADAPTED = [new ClassA(), new ClassBAdapter()] ADAPTED.forEach((item) => { item.methodA() }) method A method B method A method B

就只是在外部包了一层,因此除了上面的对象适配器还有一种称为类适配器也是同样的效果,类适配器则是采用继承来实现,将将原method继承到复合Target接口的method上,比上面的示例还简单,这里就不写出示例了。

而具体选用那种需要根据实际情况选择

应用举例

假设有一个使用不同工具生产立方体的情形,而不同的工具是由不同的公司发明的,应用程序通过UI界面输入width、height、depth来生产立方体(接口),而输入的这些参数只与A公司的生产工具所需参数相同,而B公司的生产工具的所需参数与A公司并不同(接口也就不同了),那么为了连个接口适配,将B公司的生产工具适配A公司生产工具的接口。

这样在有一个公司(供应商)在忙时就可以使用另一个供应商了

在这里插入图片描述

复制代码
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
interface ICubeA { manufacture(width: number, height: number, depth: number): boolean } class CubeA implements ICubeA { static last_time = Date.now() manufacture(width: number, height: number, depth: number): boolean { //如果是忙碌中则制作一个正方体 const now = Date.now() if (now > CubeA.last_time + 1500) { console.log( `Company A built Cube with dimensions ${width}x${height}x${depth}` ) CubeA.last_time = now return true } return false //忙碌中 } } //一个假想的B公司的立方体制作工具 interface ICubeB { create( top_left_front: [number, number, number], bottom_right_back: [number, number, number] ): boolean } class CubeB implements ICubeB { static last_time = Date.now() create( top_left_front: [number, number, number], bottom_right_back: [number, number, number] ): boolean { // 如果不忙,那就用坐标制造一个立方体 const now = Date.now() if (now > CubeB.last_time + 3000) { console.log( `Company B built Cube with coords [${top_left_front[0]},${top_left_front[1]},${top_left_front[2]}],[${bottom_right_back[0]},${bottom_right_back[1]},${bottom_right_back[2]}]` ) CubeB.last_time = now return true } else { return false // busy } } } //适配器类,使CubeB类也能使用ICubeA接口 export default class CubeBAdapter implements ICubeA { #cube: CubeB constructor() { this.#cube = new CubeB() } manufacture(width: number, height: number, depth: number): boolean { const success = this.#cube.create( [0 - width / 2, 0 - height / 2, 0 - depth / 2], [0 + width / 2, 0 + height / 2, 0 + depth / 2] ) return success } } const totalCubes = 5 let counter = 0 const manufactureCube = () => { const width = Math.floor(Math.random() * 10) + 1 const height = Math.floor(Math.random() * 10) + 1 const depth = Math.floor(Math.random() * 10) + 1 let cube = new CubeA() let success = cube.manufacture(width, height, depth) if (success) { counter = counter + 1 } else { // try other manufacturer console.log('Company A was busy, so trying company B') cube = new CubeBAdapter() success = cube.manufacture(width, height, depth) if (success) { counter = counter + 1 } else { console.log('Company B was busy, so trying company A') } } } // wait some time between manufacturing each cube const interval = setInterval(() => { manufactureCube() if (counter >= totalCubes) { clearInterval(interval) console.log(`${totalCubes} cubes have been manufactured`) } }, 1000)
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
Company A was busy, so trying company B Company B was busy, so trying company A Company A built Cube with dimensions 6x5x10 Company A was busy, so trying company B Company B built Cube with coords [-4,-3,-2.5],[4,3,2.5] Company A built Cube with dimensions 4x5x3 Company A was busy, so trying company B Company B was busy, so trying company A Company A built Cube with dimensions 10x2x1 Company A was busy, so trying company B Company B built Cube with coords [-0.5,-2,-2.5],[0.5,2,2.5] 5 cubes have been manufactured

最后

以上就是大胆萝莉最近收集整理的关于装饰器模式、适配器模式装饰器模式、适配器模式的全部内容,更多相关装饰器模式、适配器模式装饰器模式、适配器模式内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(60)

评论列表共有 0 条评论

立即
投稿
返回
顶部