首页 Flutter 设计模式之合成复用原则
文章
取消

Flutter 设计模式之合成复用原则

什么是合成复用原则?

合成复用原则(Composite/Aggregate Reuse Principle,CARP)指尽量使用对象组合(has-a)或对象聚合(contanis-a)的方式实现代码复用,而不是用继承关系达到代码复用的目的。合成复用原则可以使系统更加灵活,降低类与类之间的耦合度,一个类的变化对其他类造成的影响相对较小。

合成复用原则有什么作用?

合成复用原则分为继承复用合成复用,我们来看看这两种之间的区别

继承复用

1、破坏类的封装性

2、子类和父类耦合度高

3、限制复用的灵活性

合成复用

1、维持类的封装性

2、降低耦合度

3、复用的灵活性高

案例分析

手机按“功能”可分为智能手机、老人机等,按“颜色”可分为黑色、白色、粉色等。如果同时考虑使用继承复用合成复用我们来具体看下它们如何实现

方案一:继承复用

1、定义手机抽象类

1
2
3
4
abstract class IPhone {
  // 打电话功能
  void call();
}

2、苹果手机实现类

1
2
3
4
5
6
class ApplePhone extends IPhone {
  @override
  void call() {
    print("苹果手机打电话");
  }
}

3、诺基亚手机实现类

1
2
3
4
5
6
class NokiaPhone extends IPhone {
  @override
  void call() {
    print("诺基亚手机打电话");
  }
}

4、苹果手机颜色实现类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class WhiteApplePhone extends ApplePhone {
  @override
  void call() {
    print("白色的苹果手机打电话");
  }
}

class BlackApplePhone extends ApplePhone {
  @override
  void call() {
    print("黑色的苹果手机打电话");
  }
}

class PinkApplePhone extends ApplePhone {
  @override
  void call() {
    print("粉色的苹果手机打电话");
  }
}

5、诺基亚手机颜色实现类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class WhiteNokiaPhone extends NokiaPhone {
  @override
  void call() {
    print("白色的诺基亚手机打电话");
  }
}

class BlackNokiaPhone extends NokiaPhone {
  @override
  void call() {
    print("黑色的诺基亚手机打电话");
  }
}

class PinkNokiaPhone extends NokiaPhone {
  @override
  void call() {
    print("粉色的诺基亚手机打电话");
  }
}

6、使用

1
2
3
4
5
6
7
void main(List<String> args) {
  IPhone whiteApplePhone = WhiteApplePhone();
  whiteApplePhone.call();

  IPhone whiteNokiaPhone = WhiteNokiaPhone();
  whiteNokiaPhone.call();
}

7、运行结果

1
2
3
4
Connecting to VM Service at http://127.0.0.1:51259/FmL9R3fZuN0=/
白色的苹果手机打电话
白色的诺基亚手机打电话
Exited

8、完整代码

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
void main(List<String> args) {
  IPhone whiteApplePhone = WhiteApplePhone();
  whiteApplePhone.call();

  IPhone whiteNokiaPhone = WhiteNokiaPhone();
  whiteNokiaPhone.call();
}


abstract class IPhone {
  // 打电话功能
  void call();
}

class ApplePhone extends IPhone {
  @override
  void call() {
    print("苹果手机打电话");
  }
}

class WhiteApplePhone extends ApplePhone {
  @override
  void call() {
    print("白色的苹果手机打电话");
  }
}

class BlackApplePhone extends ApplePhone {
  @override
  void call() {
    print("黑色的苹果手机打电话");
  }
}

class PinkApplePhone extends ApplePhone {
  @override
  void call() {
    print("粉色的苹果手机打电话");
  }
}

class NokiaPhone extends IPhone {
  @override
  void call() {
    print("诺基亚手机打电话");
  }
}

class WhiteNokiaPhone extends NokiaPhone {
  @override
  void call() {
    print("白色的诺基亚手机打电话");
  }
}

class BlackNokiaPhone extends NokiaPhone {
  @override
  void call() {
    print("黑色的诺基亚手机打电话");
  }
}

class PinkNokiaPhone extends NokiaPhone {
  @override
  void call() {
    print("粉色的诺基亚手机打电话");
  }
}

9、分析

我们通过继承复用原则对手机的需求进行了实现,但是这样破坏了类的封装性,而且子类和父类的耦合度太高导致了复用的灵活性不高。

方案二:合成复用

1、定义手机颜色抽象类和实现类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
abstract class IPhoneColor {
  late String color;
  IPhoneColor(this.color);
}

class WhitePhoneColor extends IPhoneColor {
  WhitePhoneColor(String color) : super(color);
}

class BlackPhoneColor extends IPhoneColor {
  BlackPhoneColor(String color) : super(color);
}

class PinkPhoneColor extends IPhoneColor {
  PinkPhoneColor(String color) : super(color);
}

2、定义手机抽象类

1
2
3
4
5
6
7
abstract class IPhone {
  // 手机颜色
  late IPhoneColor phoneColor;
  IPhone(this.phoneColor);
  // 打电话功能
  void call();
}

3、定义苹果手机实现类

1
2
3
4
5
6
7
8
9
class ApplePhone extends IPhone {

  ApplePhone(IPhoneColor color):super(color);

  @override
  void call() {
    print("苹果手机打电话");
  }
}

4、定义诺基亚手机实现类

1
2
3
4
5
6
7
8
class NokiaPhone extends IPhone {
  NokiaPhone(IPhoneColor color) : super(color);

  @override
  void call() {
    print("诺基亚手机打电话");
  }
}

5、使用

1
2
3
4
5
6
7
8
9
void main(List<String> args) {
  ApplePhone applePhone = ApplePhone(WhitePhoneColor("白色"));
  applePhone.call();
  print(applePhone.phoneColor.color);

  NokiaPhone nokiaPhone = NokiaPhone(PinkPhoneColor("粉色"));
  nokiaPhone.call();
  print(nokiaPhone.phoneColor.color);
}

6、运行结果

1
2
3
4
5
6
Connecting to VM Service at http://127.0.0.1:51924/yuNcRaUGX4Q=/
苹果手机打电话
白色
诺基亚手机打电话
粉色
Exited

7、完整代码

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
void main(List<String> args) {
  ApplePhone applePhone = ApplePhone(WhitePhoneColor("白色"));
  applePhone.call();
  print(applePhone.phoneColor.color);

  NokiaPhone nokiaPhone = NokiaPhone(PinkPhoneColor("粉色"));
  nokiaPhone.call();
  print(nokiaPhone.phoneColor.color);
}

abstract class IPhone {
  // 手机颜色
  late IPhoneColor phoneColor;
  IPhone(this.phoneColor);
  // 打电话功能
  void call();
}

class ApplePhone extends IPhone {

  ApplePhone(IPhoneColor color):super(color);

  @override
  void call() {
    print("苹果手机打电话");
  }
}

class NokiaPhone extends IPhone {
  NokiaPhone(IPhoneColor color) : super(color);

  @override
  void call() {
    print("诺基亚手机打电话");
  }
}


abstract class IPhoneColor {
  late String color;
  IPhoneColor(this.color);
}

class WhitePhoneColor extends IPhoneColor {
  WhitePhoneColor(String color) : super(color);
}

class BlackPhoneColor extends IPhoneColor {
  BlackPhoneColor(String color) : super(color);
}

class PinkPhoneColor extends IPhoneColor {
  PinkPhoneColor(String color) : super(color);
}

8、分析

这里我们采用组合复用的方式对手机的需求进行了优化,手机颜色和手机区别开来并通过组合复用的方式进行重构,这样既维持了类的封装性并降低了类与类之间的耦合度,而且提高了代码的灵活性。

总结

在我们遵守合成复用原则的同时,尽量能使用合成复用就不要使用继承复用的方式,不然破坏了类的封装性,而且子类和父类的耦合度太高导致了复用的灵活性不高。

本文由作者按照 CC BY 4.0 进行授权

Flutter 设计模式之迪米特原则

Flutter 设计模式创建型设计模式