我們來想想TSerialNumberGenerator的這兩個方法應該如何實現。我們只要運用組合模式(Composite Pattern),把serialNumber拆分開來,並委托給相應的Generator實例處理就好了。我們需要再調整一下ISerialNumberGenerator 接口:
ISerialNumberGenerator
1ISerialNumberGenerator =interface
2 function NextSerialNumber(const serialNumber: string): string; overload;
3 function NextSerialNumber(const serialNumber: string; var repeated: Boolean): string; overload;
4 function Validate(const serialNumber: string): Boolean;
5 function GetTotalLength: Integer;
6 property TotalLength: Integer read GetTotalLength;
7end
TSerialNumberGenerator
1function TSerialNumberGenerator.DoNextSerialNumber(
2 const serialNumber: string; var repeated: Boolean): string;
3var
4 generator: ISerialNumberGenerator;
5 sn: string;
6 pos: Integer;
7 i: Integer;
8 list: TStrings;
9begin
10 if Length(serialNumber) <> fTotalLength then
11 begin
12 raise ESerialNumberException.CreateFmt(SIllegalSerialNumber, [serialNumber]);
13 end;
14 pos :=1;
15 list := TStringList.Create;
16 try
17 for i :=0to fGenerators.Count -1do
18 begin
19 generator := ISerialNumberGenerator(fGenerators[i]);
20 sn := MidStr(serialNumber, pos, generator.TotalLength);
21 list.Add(sn);
22 Inc(pos, generator.TotalLength);
23 end;
24 repeated := False;
25 for i := list.Count -1downto0do
26 begin
27 generator := ISerialNumberGenerator(fGenerators[i]);
28 list[i] := generator.NextSerialNumber(list[i], repeated);
29 ifnot repeated then Break;
30 end;
31 for i :=0to list.Count -1do
32 begin
33 Result := Result + list[i];
34 end;
35 finally
36 list.Free;
37 end;
38end;
39
40function TSerialNumberGenerator.Validate(const serialNumber: string): Boolean;
41var
42 generator: ISerialNumberGenerator;
43 sn: string;
44 pos: Integer;
45 i: Integer;
46begin
47 if Length(serialNumber) <> fTotalLength then
48 begin
49 raise ESerialNumberException.CreateFmt(SIllegalSerialNumber, [serialNumber]);
50 end;
51 Result := True;
52 pos :=1;
53 for i :=0to fGenerators.Count -1do
54 begin
55 generator := ISerialNumberGenerator(fGenerators[i]);
56 sn := MidStr(serialNumber, pos, generator.TotalLength);
57 Inc(pos, generator.TotalLength);
58 Result := generator.Validate(sn);
59 ifnot Result then Break;
60 end;
61end
再運行Test Case,呵呵,綠色進度條: )
寫到這裡,我們已經成功了一半了。接下來,希望大家提出批評意見,我將繼續重構代碼。下集將更加精彩,敬請關注:)