装饰模式
装饰模式
装饰模式
题目链接
基本概念
通常情况下,扩展类的功能可以通过继承实现,但是扩展越多,子类越多,装饰模式(Decorator Pattern
, 结构型设计模式)可以在不定义子类的情况下动态的给对象添加一些额外的功能。具体的做法是将原始对象放入包含行为的特殊封装类(装饰类),从而为原始对象动态添加新的行为,而无需修改其代码。
举个简单的例子,假设你有一个基础的图形类,你想要为图形类添加颜色、边框、阴影等功能,如果每个功能都实现一个子类,就会导致产生大量的类,这时就可以考虑使用装饰模式来动态地添加,而不需要修改图形类本身的代码,这样可以使得代码更加灵活、更容易维护和扩展。
基本结构:
装饰模式包含以下四个主要角色:
- 组件
Component
:通常是抽象类或者接口,是具体组件和装饰者的父类,定义了具体组件需要实现的方法,比如说我们定义Coffee
为组件。 - 具体组件
ConcreteComponent
: 实现了Component接口的具体类,是被装饰的对象。 - 装饰类
Decorator
: 一个抽象类,给具体组件添加功能,但是具体的功能由其子类具体装饰者完成,持有一个指向Component对象的引用。 - 具体装饰类
ConcreteDecorator
: 扩展Decorator类,负责向Component对象添加新的行为,加牛奶的咖啡是一个具体装饰类,加糖的咖啡也是一个具体装饰类。
基本实现
装饰模式的实现包括以下步骤:
- 定义Component接口
1
2
3
4
5
6
// 组件接口
public interface Component {
void operation();
}
- 实现 ConcreteComponent
1
2
3
4
5
6
7
8
9
// 具体组件
public class ConcreteComponent implements Component {
@Override
public void operation() {
System.out.println("ConcreteComponent operation");
}
}
- 定义Decorator装饰类,继承自Component
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 定义一个抽象的装饰者类,继承自Component
public abstract class Decorator implements Component {
protected Component component;
public Decorator(Component component) {
this.component = component;
}
@Override
public void operation() {
component.operation();
}
}
- 定义具体的装饰者实现,给具体组件对象添加功能。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 具体的装饰者实现
public class ConcreteDecorator extends Decorator {
public ConcreteDecorator(Component component) {
super(component);
}
// 根据需要添加额外的方法
@Override
public void operation() {
// 可以在调用前后添加额外的行为
System.out.println("Before operation in ConcreteDecorator");
super.operation();
System.out.println("After operation in ConcreteDecorator");
}
}
- 在客户端使用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class Main {
public static void main(String[] args) {
// 创建具体组件
Component concreteComponent = new ConcreteComponent();
// 使用具体装饰者包装具体组件
Decorator decorator = new ConcreteDecorator(concreteComponent);
// 调用操作
decorator.operation();
}
}
应用场景
装饰模式通常在以下几种情况使用:
当需要给一个现有类添加附加功能,但由于某些原因不能使用继承来生成子类进行扩充时,可以使用装饰模式。
动态的添加和覆盖功能:当对象的功能要求可以动态地添加,也可以再动态地撤销时可以使用装饰模式。
在Java的I/O库中,装饰者模式被广泛用于增强I/O流的功能。例如,BufferedInputStream
和BufferedOutputStream
这两个类提供了缓冲区的支持,通过在底层的输入流和输出流上添加缓冲区,提高了读写的效率,它们都是InputStream
和OutputStream
的装饰器。BufferedReader
和BufferedWriter
这两个类与BufferedInputStream
和BufferedOutputStream
类似,提供了字符流的缓冲功能,是Reader和Writer的装饰者。
本题代码
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
import java.util.Scanner;
// 咖啡接口
interface Coffee {
void brew();
}
// 具体的黑咖啡类
class BlackCoffee implements Coffee {
@Override
public void brew() {
System.out.println("Brewing Black Coffee");
}
}
// 具体的拿铁类
class Latte implements Coffee {
@Override
public void brew() {
System.out.println("Brewing Latte");
}
}
// 装饰者抽象类
abstract class Decorator implements Coffee {
protected Coffee coffee;
public Decorator(Coffee coffee) {
this.coffee = coffee;
}
@Override
public void brew() {
coffee.brew();
}
}
// 具体的牛奶装饰者类
class MilkDecorator extends Decorator {
public MilkDecorator(Coffee coffee) {
super(coffee);
}
@Override
public void brew() {
super.brew();
System.out.println("Adding Milk");
}
}
// 具体的糖装饰者类
class SugarDecorator extends Decorator {
public SugarDecorator(Coffee coffee) {
super(coffee);
}
@Override
public void brew() {
super.brew();
System.out.println("Adding Sugar");
}
}
// 客户端代码
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
while (scanner.hasNext()) {
int coffeeType = scanner.nextInt();
int condimentType = scanner.nextInt();
// 根据输入制作咖啡
Coffee coffee;
if (coffeeType == 1) {
coffee = new BlackCoffee();
} else if (coffeeType == 2) {
coffee = new Latte();
} else {
System.out.println("Invalid coffee type");
continue;
}
// 根据输入添加调料
if (condimentType == 1) {
coffee = new MilkDecorator(coffee);
} else if (condimentType == 2) {
coffee = new SugarDecorator(coffee);
} else {
System.out.println("Invalid condiment type");
continue;
}
// 输出制作过程
coffee.brew();
}
}
}
其他语言版本
C++
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
#include <iostream>
#include <memory>
// 咖啡接口
class Coffee {
public:
virtual ~Coffee() {}
virtual void brew() = 0;
};
// 具体的黑咖啡类
class BlackCoffee : public Coffee {
public:
void brew() override {
std::cout << "Brewing Black Coffee" << std::endl;
}
};
// 具体的拿铁类
class Latte : public Coffee {
public:
void brew() override {
std::cout << "Brewing Latte" << std::endl;
}
};
// 装饰者抽象类
class Decorator : public Coffee {
protected:
std::unique_ptr<Coffee> coffee;
public:
Decorator(std::unique_ptr<Coffee> coffee) : coffee(std::move(coffee)) {}
void brew() override {
if (coffee) {
coffee->brew();
}
}
};
// 具体的牛奶装饰者类
class MilkDecorator : public Decorator {
public:
MilkDecorator(std::unique_ptr<Coffee> coffee) : Decorator(std::move(coffee)) {}
void brew() override {
Decorator::brew();
std::cout << "Adding Milk" << std::endl;
}
};
// 具体的糖装饰者类
class SugarDecorator : public Decorator {
public:
SugarDecorator(std::unique_ptr<Coffee> coffee) : Decorator(std::move(coffee)) {}
void brew() override {
Decorator::brew();
std::cout << "Adding Sugar" << std::endl;
}
};
// 客户端代码
int main() {
int coffeeType, condimentType;
while (std::cin >> coffeeType >> condimentType) {
// 根据输入制作咖啡
std::unique_ptr<Coffee> coffee;
if (coffeeType == 1) {
coffee = std::make_unique<BlackCoffee>();
} else if (coffeeType == 2) {
coffee = std::make_unique<Latte>();
} else {
std::cout << "Invalid coffee type" << std::endl;
continue;
}
// 根据输入添加调料
if (condimentType == 1) {
coffee = std::make_unique<MilkDecorator>(std::move(coffee));
} else if (condimentType == 2) {
coffee = std::make_unique<SugarDecorator>(std::move(coffee));
} else {
std::cout << "Invalid condiment type" << std::endl;
continue;
}
// 输出制作过程
coffee->brew();
}
return 0;
}
Python
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
from abc import ABC, abstractmethod
from typing import Type
# 咖啡接口
class Coffee(ABC):
@abstractmethod
def brew(self):
pass
# 具体的黑咖啡类
class BlackCoffee(Coffee):
def brew(self):
print("Brewing Black Coffee")
# 具体的拿铁类
class Latte(Coffee):
def brew(self):
print("Brewing Latte")
# 装饰者抽象类
class Decorator(Coffee, ABC):
def __init__(self, coffee: Type[Coffee]):
self._coffee = coffee
def brew(self):
self._coffee.brew()
# 具体的牛奶装饰者类
class MilkDecorator(Decorator):
def brew(self):
super().brew()
print("Adding Milk")
# 具体的糖装饰者类
class SugarDecorator(Decorator):
def brew(self):
super().brew()
print("Adding Sugar")
# 客户端代码
if __name__ == "__main__":
try:
while True:
coffee_type, condiment_type = map(int, input().split())
# 根据输入制作咖啡
if coffee_type == 1:
coffee = BlackCoffee()
elif coffee_type == 2:
coffee = Latte()
else:
print("Invalid coffee type")
continue
# 根据输入添加调料
if condiment_type == 1:
coffee = MilkDecorator(coffee)
elif condiment_type == 2:
coffee = SugarDecorator(coffee)
else:
print("Invalid condiment type")
continue
# 输出制作过程
coffee.brew()
except EOFError:
pass
Go
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
package main
import "fmt"
// 咖啡接口
type Coffee interface {
brew()
}
// 具体的黑咖啡类
type BlackCoffee struct{}
func (bc *BlackCoffee) brew() {
fmt.Println("Brewing Black Coffee")
}
// 具体的拿铁类
type Latte struct{}
func (l *Latte) brew() {
fmt.Println("Brewing Latte")
}
// 装饰者抽象类
type Decorator struct {
coffee Coffee
}
func (d *Decorator) brew() {
d.coffee.brew()
}
// 具体的牛奶装饰者类
type MilkDecorator struct {
Decorator
}
func (md *MilkDecorator) brew() {
md.Decorator.brew()
fmt.Println("Adding Milk")
}
// 具体的糖装饰者类
type SugarDecorator struct {
Decorator
}
func (sd *SugarDecorator) brew() {
sd.Decorator.brew()
fmt.Println("Adding Sugar")
}
func main() {
for {
var coffeeType, condimentType int
if _, err := fmt.Scan(&coffeeType, &condimentType); err != nil {
break
}
// 根据输入制作咖啡
var coffee Coffee
if coffeeType == 1 {
coffee = &BlackCoffee{}
} else if coffeeType == 2 {
coffee = &Latte{}
} else {
fmt.Println("Invalid coffee type")
continue
}
// 根据输入添加调料
if condimentType == 1 {
coffee = &MilkDecorator{Decorator: Decorator{coffee: coffee}}
} else if condimentType == 2 {
coffee = &SugarDecorator{Decorator: Decorator{coffee: coffee}}
} else {
fmt.Println("Invalid condiment type")
continue
}
// 输出制作过程
coffee.brew()
}
}
This post is licensed under CC BY 4.0 by the author.