一、概述
在軟件系統中,有時候面臨著復雜的對象創建,該對象由一定算法構成的子對象組成,由於需求變化,這些子對象會經常變換,但組合在一起的算法卻是穩定的。生成器模式可以處理這類對象的構建,它提供了一種封裝機制來隔離各類子對象的變化,從而保證系統的穩定。
二、生成器模式
生成器模式將一個復雜對象的構建與它的表示分離,使得同樣的構建過程可以創建不同的表示。其結構圖如下:
三、示例
using
System;
using
System.Collections.Generic;
using
System.Text;
namespace
BuilderPattern
{
/// <summary>
/// 所有課程
/// </summary>
public
class
Coures
{
/// <summary>
/// 保存課程信息
/// </summary>
IDictionary<
string
,
decimal
> coures =
new
Dictionary<
string
,
decimal
>();
/// <summary>
/// 選課
/// </summary>
/// <param name="serialNumber"></param>
/// <param name="score"></param>
public
void
Select(
string
serialNumber,
decimal
score)
{
coures.Add(serialNumber, score);
}
/// <summary>
/// 計算總學分
/// </summary>
/// <returns>總學分</returns>
public
decimal
ComputeScores()
{
decimal
scores = 0;
foreach
(KeyValuePair<
string
,
decimal
> kvp
in
coures)
{
Console.WriteLine(kvp.Key +
":"
+ kvp.Value);
Console.WriteLine(
" "
);
scores += kvp.Value;
}
return
scores;
}
}
/// <summary>
/// 選課建造者抽象類,表現(下面的抽象函數)是相對穩定的。
/// </summary>
public
abstract
class
Builder
{
/// <summary>
/// 必修課程成績
/// </summary>
public
abstract
void
BuildCompulsory();
/// <summary>
/// 選修課程成績
/// </summary>
public
abstract
void
BuildElective();
/// <summary>
/// 限制課程成績
/// </summary>
public
abstract
void
BuildRestriction();
/// <summary>
/// 獲得課程字典對象
/// </summary>
/// <returns></returns>
public
abstract
Coures GetCoures();
}
/// <summary>
/// 本科生選課成績
/// </summary>
public
class
UndergraduateBuilder : Builder
{
private
Coures coures =
new
Coures();
/// <summary>
/// 本科生選必修課程成績
/// </summary>
public
override
void
BuildCompulsory()
{
coures.Select(
"001"
, 80M);
}
/// <summary>
/// 本科生選選修課程成績
/// </summary>
public
override
void
BuildElective()
{
coures.Select(
"101"
, 85M);
}
/// <summary>
/// 本科生選限制課程成績
/// </summary>
public
override
void
BuildRestriction()
{
coures.Select(
"201"
, 95M);
}
/// <summary>
/// 本科生選獲得課程字典對象
/// </summary>
/// <returns></returns>
public
override
Coures GetCoures()
{
return
coures;
}
}
/// <summary>
/// 研究生選課成績
/// </summary>
public
class
GraduateBuilder : Builder
{
private
Coures coures =
new
Coures();
/// <summary>
/// 研究生選必修課程成績
/// </summary>
public
override
void
BuildCompulsory()
{
coures.Select(
"S001"
, 70M);
}
/// <summary>
/// 研究生選選修課程成績
/// </summary>
public
override
void
BuildElective()
{
coures.Select(
"S101"
, 75M);
}
/// <summary>
/// 研究生選限制課程成績
/// </summary>
public
override
void
BuildRestriction()
{
coures.Select(
"S201"
, 80M);
}
/// <summary>
/// 研究生選獲得課程字典對象
/// </summary>
/// <returns></returns>
public
override
Coures GetCoures()
{
return
coures;
}
}
/// <summary>
/// 課程成績管理類
/// </summary>
public
class
CourseScoresManager
{
/// <summary>
/// 這裡的參數便是未確定的
/// </summary>
/// <param name="builder"></param>
public
void
CourseScoresManager(Builder builder)
{
builder.BuildCompulsory();
builder.BuildElective();
builder.BuildRestriction();
}
}
class
Program
{
static
void
Main(
string
[] args)
{
/* Builder instance = new UndergraduateBuilder(); */
Builder instance =
new
GraduateBuilder();
CourseScoresManager courseScoresManager =
new
CourseScoresManager(instance);
Coures coures = instance.GetCoures();
decimal
totalScores = coures.ComputeScores();
Console.WriteLine(totalScores);
Console.WriteLine(
" "
);
Console.ReadLine();
}
}
}
四、使用場景
應用場景是當創建一個復雜的對象時,這個對象由各個子對象構成,而由於需求的變化導致子對象的性質也是未確定的。
我們一般為一個類提供構造函數,並利用這個構造函數完成對象的創建工作。當客戶知道為哪個類創建實例,並知道構造函數的參數時(假設是用帶參數的構造函數)。然而由於條件的現限制,是無法用通常的方式來構造對象的實例! 在進行對象構造之前,要逐步收集與構造相關的信息.那麼創建對象的過程和對象的表現就應該分離開來。此時對象的表現是相對穩定的。