设计模式之结构型模式

结构型模式

作用

  • 从程序的结构上实现松耦合,从而可以扩大整体的类结构,用来解决更大的问题。

分类

  • 适配器模式
  • 代理模式
  • 桥接模式
  • 装饰模式
  • 组合模式
  • 外观模式
  • 享元模式

适配器模式

  • 将一个类的接口转换成客户希望的另一个接口。Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以在一起工作。
  • 角色分析
    • 目标接口:客户所期待的接口,目标可以是具体的或抽象的类,也可以是接口。
    • 需要适配的类:需要适配的类或适配者类。
    • 适配器:通过包装一个需要适配的对象,把原接口转换成目标对象。

优缺点

优点
  1. 一个对象适配器可以把多个不同的适配者适配到同一个目标
  2. 可以适配一个适配者的子类,由于适配器和适配者之间是关联关系,根据“里氏代换原则”,适配者的子类也可以通过该适配器进行适配
缺点
  1. 对于Java、C#等不支持多重类继承的语言,一次最多只能适配一个适配者类,不能同时适配多个适配者;
  2. 对于Java、C#等语言中,类适配模式中的目标抽象类只能为借口,不能为类,其使用有一定局限性。
适用场景
  1. 系统需要使用一些现有的类,而这些类的接口(方法名)不符合系统的需要,甚至没有这些类的源代码。
  2. 想创建一个可以重复使用的类,用于与一些彼此之间没有太大关联的一些类,包括一些可能在将来引进的类一起工作。

代码

以网线适配器为例:

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
package com.design_patterns.adapter;

/**
* @Author {xiheya}
* @Date: 2022/03/20/ 23:06
* @Description
*/
//客户端类:电脑
public class Computer {
//我们的电脑需要连接上转接器才可以上网
public void net(NetToUsb adapter){
//上网的具体实现,找一个转接头
adapter.handleRequest();
}

public static void main(String[] args) {
//电脑
Computer computer = new Computer();
//网线
Adaptee adaptee = new Adaptee();
//适配器
Adapter adapter = new Adapter();

computer.net(adapter);
System.out.println("==========================");
Adapter2 adapter2 = new Adapter2(adaptee);

computer.net(adapter2);
}
}
/**
* //要被适配的类:网线
* public class Adaptee {
* public void request(){
* System.out.println("连接网线开始上网");
* }
* }
*
* //接口转换器的抽象实现
* public interface NetToUsb {
* //作用:处理请求 网线---》USB
* public void handleRequest();
* }
*
* // 1. 继承(类适配器,单继承有局限性)
* public class Adapter extends Adaptee implements NetToUsb{
* @Override
* public void handleRequest() {
* System.out.println("我是通过类适配器实现的上网功能(继承)");
* super.request();
* }
* }
*
* // 2. 组合(对象适配器,常用)
* public class Adapter2 implements NetToUsb{
* private Adaptee adaptee;
*
* public Adapter2(Adaptee adaptee) {
* this.adaptee = adaptee;
* }
*
* @Override
* public void handleRequest() {
* System.out.println("我是通过对象适配器实现的上网功能(组合)");
* adaptee.request();
* }
* }
*/

结果

适配器模式

流程图

流程图


桥接模式

定义

桥接模式是将抽象部分与它的实现部分分离,使它们都可以独立地变化。它是一种对象结构型模式,又称为(Handle and Body)模式或接口(Interface)模式。

实例模型

桥接模式

分析:这个场景中有两个变化的维度:品牌,类型。

代码

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
package com.design_patterns.bridge;

/**
* @Author {xiheya}
* @Date: 2022/03/21/ 15:10
* @Description
*/
public class Test {
public static void main(String[] args) {
//
Computer computer = new Desktop(new Apple());
computer.info();
//
Computer computer1 = new Laptop(new Lenovo());
computer1.info();
//
Computer computer2 = new Pad(new Apple());
computer2.info();
}
}
/**
* public interface Brand {
*
* void info();
* }
*
* public class Apple implements Brand{
*
* @Override
* public void info() {
* System.out.print("苹果");
* }
* }
*
* public class Lenovo implements Brand{
*
* @Override
* public void info() {
* System.out.print("联想");
* }
* }
*
* public abstract class Computer {
* //组合 品牌
* protected Brand brand;
*
* public Computer(Brand brand) {
* this.brand = brand;
* }
* //自带品牌
* public void info(){
* brand.info();
* }
* }
*
* class Desktop extends Computer {
* public Desktop(Brand brand) {
* super(brand);
*
* }
*
* @Override
* public void info() {
* super.info();
* System.out.println("台式机");
* }
* }
*
* class Laptop extends Computer {
* public Laptop(Brand brand) {
* super(brand);
*
* }
*
* @Override
* public void info() {
* super.info();
* System.out.println("笔记本");
* }
* }
*
* class Pad extends Computer {
* public Pad(Brand brand) {
* super(brand);
*
* }
*
* @Override
* public void info() {
* super.info();
* System.out.println("平板");
* }
* }
*/

运行结果

桥接模式


结构图

结构图


优缺点

优点
  • 桥接模式偶尔类似于多继承方案,但是多继承方案违背了类的单一职责原则,复用性比较差,类的个数也非常多,桥接模式是比多集成方案更好的解决方法,极大的减少了子类的个数,从而降低了管理和维护成本。
  • 桥接模式提高了系统的可扩充性,在两个变化维度中任意扩展一个维度,都不需要修改原有系统。符合开闭原则,就像一座桥,可以把两个变化的维度连接起来。
缺点
  • 桥接模式的引入会增加系统的理解与设计难度,由于聚合关联关系建立在抽象层,要求开发者针对抽象进行设计与编程。
  • 桥接模式要求正确识别出系统中两个独立变化的维度,因此其使用范围具有一定的局限性

适用场景

  1. 如果一个系统需要在构建的抽象化角色和具体化角色之间增加更多的灵活性,避免在两个层次之间建立静态的继承联系,通过桥接模式可以使它们在抽象层建立一个关联关系。抽象化角色和实现化角色可以以继承的方式独立扩展而互不影响,在程序运作时可以动态将一个抽象化子类的对象和一个实现化子类的对象进行组合,即系统需要对抽象化角色和实现化角色进行动态耦合

  2. 一个类存在两个独立变化的维度,且这两个维度都需要进行扩展。

  3. 虽然在系统中使用继承时没有问题的,但是由于抽象化角色和具体化角色需要独立变化,设计要求需要独立管理这两者。对于那些不希望使用继承或因为多层次继承导致系统类的个数急剧增加的系统,桥接模式尤为适用。

  4. 场景

    1. Java语言通过Java虚拟机实现了平台无关性,
    2. AWT的Peer架构
    3. JDBC驱动程序也是桥接模式的应用之一。