复合模式(Compound Pattern)是通过两个或以上的设计模式形成一个可以解决一般性问题的通用框架。

MVC 框架就是一种组合模式,ControllerView之间使用了策略模式, View中只存Controller的接口,进而达到可以随时切换不同Controller的目的。ModelView之间使用了观察者模式,View作为观察者,Model作为被观察者,当Model的数据发生变化时,View相应改变。而View本身使用了组合模式,比如按钮中可能存在子按钮,窗口中存在子窗口等等。

我们以音量调节作为一个最简的 MVC 框架示例。

关于 MVC 更多的减少,见 MVC

#代码示例

#框架接口

观察者接口
1
2
3
4
public interface IVolumeObserver
{
void VolumeUpdated();
}
Model接口
1
2
3
4
5
6
public interface IVolumeModel
{
int Volume { get; set; }
void RegisterObserver(IVolumeObserver observer);
void UnRegisterObserver(IVolumeObserver observer);
}
Controller接口
1
2
3
4
5
6
public interface IViewController
{
void VolumeUp();
void VolumeDown();
void SetVolume(int volume);
}

#接口实现

Model
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
public class VolumeModel : IVolumeModel
{
private int volume = 0;
public int Volume
{
get { return volume; }
set
{
volume = value;
observersList.ForEach(observer => observer.VolumeUpdated());
}
}
private List<IVolumeObserver> observersList = null;

public VolumeModel()
{
observersList = new List<IVolumeObserver>();
}

public void RegisterObserver(IVolumeObserver observer)
{
observersList.Add(observer);
}

public void UnRegisterObserver(IVolumeObserver observer)
{
observersList.Remove(observer);
}
}
View
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
public class VolumeView : IVolumeObserver
{
private IViewController controller = null;
private IVolumeModel model = null;

public VolumeView(IViewController controller, IVolumeModel model)
{
this.controller = controller;
this.model = model;
this.model.RegisterObserver(this);
Console.WriteLine("View: volume init is " + model.Volume);
}

public void OnVolumeUpButtonClick()
{
controller.VolumeUp();
}

public void OnVolumeDownButtonClick()
{
controller.VolumeDown();
}

public void VolumeUpdated()
{
Console.WriteLine("View: volume updated " + model.Volume);
}

~VolumeView()
{
model.UnRegisterObserver(this);
}
}
Controller
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class VolumeController : IViewController
{
private VolumeModel model = null;
public VolumeController(VolumeModel model)
{
this.model = model;
}

public void SetVolume(int volume)
{
model.Volume = volume;
}

public void VolumeDown()
{
--model.Volume;
}

public void VolumeUp()
{
++model.Volume;
}
}

#测试代码及结果

测试代码
1
2
3
4
5
VolumeModel model = new VolumeModel();
VolumeView view = new VolumeView(new VolumeController(model), model);
view.OnVolumeUpButtonClick();
view.OnVolumeUpButtonClick();
view.OnVolumeDownButtonClick();

运行结果:

复合模式运行结果