动机:
在软件系统中,经常面临着“一系列相互依赖的对象”的创建工作;同时,由于需求的变化,往往存在更多系列对象的创建工作。
如何应对这种变化?如何绕过常规的对象创建方法(new),提供一种“封装机制”来避免客房程序和这种“多系列具体对象创建工作”的支耦合?
意图:
提供一个接口,让该接口负责创建一系列“相关或者相互依赖的对象”,无需指定它们具体的类。
出自:《设计模式》GoF
Abstract Factory模式的几个要点:
1、如果没有应对“多系列对象构建”的需求变化,则没有必要使用Abstract Factroy模式,这里使用简单的静态工厂完全可以。
2、“系列对象”指的是这些对象之间有相互依赖、或作用的关系,例如游戏开发场景中的“道路”与“房屋”的依赖,“道路”与“地道”的依赖。
3、Abstract Factory模式主要在于应对“新系列”的需求变动。其缺点在于难以应用“新对象”的需求变动。
4、Abstract Factory模式经常和Factory Method模式共同组合来应对“对象创建”的需求变化。
稳定部分
1
using System;
2
using System.Drawing ;
3
namespace Gardener
4
{
5
/// <summary>
6
/// Summary description for Garden.
7
/// </summary>
8
public class Garden {
9
protected Plant center, shade, border;
10
protected bool showCenter, showShade, showBorder;
11
//select which ones to display
12
public void setCenter() {showCenter = true;}
13
public void setBorder() {showBorder =true;}
14
public void setShade() {showShade =true;}
15
//draw each plant
16
public void draw(Graphics g) {
17
if (showCenter) center.draw (g, 100, 100);
18
if (showShade) shade.draw (g, 10, 50);
19
if (showBorder) border.draw (g, 50, 150);
20
}
21
}
22
}
23
变化部分:
2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

1
using System;
2
using System.Drawing ;
3
4
namespace Gardener
5
{
6
/// <summary>
7
/// Summary description for AnnualGarden.
8
/// </summary>
9
public class AnnualGarden : Garden
10
{
11
public AnnualGarden () {
12
shade = new Plant("Coleus");
13
border = new Plant ("Alyssum");
14
center = new Plant ("Marigold");
15
}
16
}
17
public class PerennialGarden : Garden
18
{
19
public PerennialGarden() {
20
shade = new Plant("Astilbe");
21
border = new Plant ("Dicentrum");
22
center = new Plant ("Sedum");
23
}
24
}
25
public class VeggieGarden : Garden {
26
public VeggieGarden() {
27
shade = new Plant("Broccoli");
28
border = new Plant ("Peas");
29
center = new Plant ("Corn");
30
}
31
}
32
}
33
工厂:

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

1
using System;
2
using System.Collections;
3
using System.ComponentModel;
4
using System.Drawing;
5
using System.Data;
6
using System.Windows.Forms;
7
8
namespace Gardener
9
{
10
/// <summary>
11
/// Summary description for GdPic.
12
/// </summary>
13
public class GdPic : System.Windows.Forms.PictureBox
14
{
15
/// <summary>
16
/// Required designer variable.
17
/// </summary>
18
private System.ComponentModel.Container components = null;
19
private Brush br;
20
private Garden gden;
21
private void init () {
22
br = new SolidBrush (Color.LightGray );
23
}
24
public GdPic() {
25
// This call is required by the Windows.Forms Form Designer.
26
InitializeComponent();
27
init();
28
}
29
public void setGarden(Garden garden) {
30
gden = garden;
31
}
32
protected override void OnPaint ( PaintEventArgs pe ){
33
Graphics g = pe.Graphics;
34
g.FillEllipse (br, 5, 5, 100, 100);
35
if(gden != null)
36
gden.draw (g);
37
}
38
39
/// <summary>
40
/// Clean up any resources being used.
41
/// </summary>
42
protected override void Dispose( bool disposing )
43
{
44
if( disposing )
45
{
46
if(components != null)
47
{
48
components.Dispose();
49
}
50
}
51
base.Dispose( disposing );
52
}
53
54
Component Designer generated code
67
68
}
69
}
70
主程序:
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

67

68

69

70

1
using System;
2
using System.Drawing;
3
using System.Collections;
4
using System.ComponentModel;
5
using System.Windows.Forms;
6
using System.Data;
7
8
namespace Gardener
9
{
10
/// <summary>
11
/// Summary description for Form1.
12
/// </summary>
13
public class Form1 : System.Windows.Forms.Form
14
{
15
private System.Windows.Forms.GroupBox groupBox1;
16
private Gardener.GdPic gdPic1;
17
private System.Windows.Forms.RadioButton opAnnual;
18
private System.Windows.Forms.RadioButton opVegetable;
19
private System.Windows.Forms.RadioButton opPerennial;
20
private System.Windows.Forms.CheckBox ckCenter;
21
private System.Windows.Forms.CheckBox ckBorder;
22
private System.Windows.Forms.CheckBox ckShade;
23
/// <summary>
24
/// Required designer variable.
25
/// </summary>
26
private System.ComponentModel.Container components = null;
27
private Garden garden;
28
private void init() {
29
}
30
public Form1()
31
{
32
//
33
// Required for Windows Form Designer support
34
//
35
InitializeComponent();
36
init();
37
//
38
// TODO: Add any constructor code after InitializeComponent call
39
//
40
}
41
42
/// <summary>
43
/// Clean up any resources being used.
44
/// </summary>
45
protected override void Dispose( bool disposing )
46
{
47
if( disposing )
48
{
49
if (components != null)
50
{
51
components.Dispose();
52
}
53
}
54
base.Dispose( disposing );
55
}
56
57
Windows Form Designer generated code
169
170
/// <summary>
171
/// The main entry point for the application.
172
/// </summary>
173
[STAThread]
174
static void Main()
175
{
176
Application.Run(new Form1());
177
}
178
179
180
private void opAnnual_CheckedChanged(object sender, EventArgs e) {
181
setGarden( new AnnualGarden ());
182
}
183
//-----
184
private void opVegetable_CheckedChanged(object sender, EventArgs e) {
185
setGarden( new VeggieGarden ());
186
}
187
//-----
188
private void opPerennial_CheckedChanged(object sender, EventArgs e) {
189
setGarden( new PerennialGarden ());
190
}
191
//-----
192
private void setGarden(Garden gd) {
193
garden = gd; //save current garden
194
gdPic1.setGarden ( gd); //tell picture bos
195
gdPic1.Refresh (); //repaint it
196
ckCenter.Checked =false; //clear all
197
ckBorder.Checked = false; //check
198
ckShade.Checked = false; //boxes
199
}
200
private void ckCenter_CheckedChanged(object sender, System.EventArgs e) {
201
garden.setCenter ();
202
gdPic1.Refresh ();
203
}
204
//-----
205
private void ckBorder_CheckedChanged(object sender, System.EventArgs e) {
206
garden.setBorder();
207
gdPic1.Refresh ();
208
}
209
//-----
210
private void ckShade_CheckedChanged(object sender, System.EventArgs e) {
211
garden.setShade ();
212
gdPic1.Refresh ();
213
}
214
}
215
}
216

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

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

203

204

205

206

207

208

209

210

211

212

213

214

215

216
