结构型模式
举个例子:新学期开始大家都要开始选课了,对于不同的系所会有不同的选课要求,就拿数学课来说,数学下面有很多分支,高等数学,数学分析,矩阵论等,对于数学系的同学而言需要的数学课是数学分析,对于计算机学院的同学而言需要的是高等数学,虽然院系里他们都是数学课但是其内容又有所不同。如果我们只是简单地利用继承的关系来处理,一个抽象的父类math,高等数学和数学分析都继承math,然后不同的系所也继承同一个抽象的系所类。这样虽然可行,但如果需要增加英语类呢?不同的院系有不同的英语要求,意味着,应该以系所分类,最上层是系所,下面有计算机系和数学系,每个子类下面又有数学子类和英语子类。这样将会使代码变得很混乱。造成这个的原因就是继承。
对象的继承关系在进行编译时就规定好了,运行时子类无法改变从父类继承来的实现,也就是说子类对父类有很强的依赖性,这种情况导致父类中某个实现的修改一定会导致子类的实现发生变化。当子类需要复用时,往往因为其继承下来的实现不适合解决新的问题而迫使去重写父类或以其他类来代替。可以使用聚合和合成。聚合表示一种弱拥有关系,比如对象A可以包含对象B,对象B不一定是对象A的一部分,合成是一种强的拥有关系,是严格的部分和整体的关系(具有相同的生命周期)。
对应上例,不同的数学课程是不一样的,高等数学和数学分析组成了数学课程,数学课程这个概念缺少了其中任何一门任然是数学课程,而对于系所来说,数学系和计算机系合成了系所这个概念,缺一不可。每个系可以包含数学课程也不可以不包含,系所与课程是聚合的关系。
具体类代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
public abstract class Math { public abstract void select(); } public class MathAnalysis extends Math { @Override public void select() { System.out.println( "choose the math analysis" ); } } public class AdvanceMath extends Math { @Override public void select() { System.out.println( "choose advanced math" ); } } |
系所类:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
public abstract class Departments { protected Math mathCource; public void setCource(Math math){ mathCource = math; } public abstract void select(); } public class Computer extends Departments { @Override public void select() { System.out.println( "计算机系的同学开始选课了" ); ((Math)mathCource).select(); } } public class Mathematics extends Departments { @Override public void select() { System.out.println( "数学系的开始选课了" ); ((Math)mathCource).select(); } } |
客户端:
1
2
3
4
5
6
7
8
9
10
|
public static void main( String args[]) { Departments dp; dp = new Computer(); dp.setCource( new AdvanceMath()); dp.select(); dp = new Mathematics(); dp.setCource( new MathAnalysis()); dp.select(); } |
上述交接模式的定义就是:将抽象部分和实现部分分离,使他们都可以独立的变化。什么是抽象与实现分离呢?实现指的就是抽象类和派生类用来实现自己的对象,也就是说课程既可以按照课程类别来分,也可以按照系所来分,桥接模式适用于这种有多重分类并且每种分类都需要独立变化的情况。现在无论是新增一门数学课还是系所,都只要增加一个子类就可以了,这样降低了工作量,还解决了继承的高耦合的问题。
桥接模式基本代码:
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
|
public abstract class Implementor { public abstract void operation(); } public class ConcreteImplementA extends Implementor{ @Override public void operation() { // TODO Auto-generated method stub System.out.println( "the concrete operation of class A" ); } } public class ConcreteImplementB extends Implementor { @Override public void operation() { // TODO Auto-generated method stub System.out.println( "the concrete operation of classB " ); } } public class Abstraction { protected Implementor implementor; public void setImplementor(Implementor implementor){ this .implementor = implementor; } public void operation(){ implementor.operation(); } } public class RefinedAbstration extends Abstraction { @Override public void operation() { // TODO Auto-generated method stub implementor.operation(); } } public static void main(String args[]) { Abstraction abstraction = new Abstraction(); abstraction.setImplementor( new ConcreteImplementA()); abstraction.operation(); abstraction.setImplementor( new ConcreteImplementB()); abstraction.operation(); } |
总结:桥接模式解决了不同分类的实现之间的耦合问题,使其可以独立的变化。将前面提到的抽象操作的集合转移到一个接口中,就可以创建所谓的桥,这样做的好处就是使我们想要的抽象取决于对这个借口的实现。而桥接模式的目的正是将一个抽象和其他抽象操作实现进行分离。使其可以独立的改变。