技術交流,DH講解
如果我們想在不改變已有類的情況下,然後加上新的功能.
這個時候我們就可以使用裝飾模式了.
慣例先看下這個設計模式的UML圖.
裝飾模式關鍵是方法重載.override.
說了這麼多我們來用代碼來說話.
老規矩,第一個是PHP了.
class Person{ var $name=''; function __construct($a){ $this->name=$a; } public function show(){
echo("this is ".$this->name."!!!\n");
}
}
//穿著的基類
class Finery extends Person{ protected $component; public function decorator($aPerson){ $this->component=$aPerson; } public function show() { if(isset($this->component)) $this->component->show(); }}//具體的類.
Class Tshirt extends Finery{ public function show() {
echo("My TShirt@!\n");
parent::show();
}
}
//具體類2
class Tie extends Finery{
public function show(){
echo("My Tie!!\n");
parent::show();
}
}
//Test $p = new Person("HuangJacky");
$tshirt = new Tshirt();
$tie = new Tie();
$tshirt->decorator($p);
$tie->decorator($tshirt);
$tie->show();
我們看看輸出結果吧.
My Tie!! My TShirt@! this is HuangJacky!!!
我們可以看見關鍵的地方:
parent::show();
接下來我們還是用Java來
class Person{ private String Name; public Person(){
this.Name="HuangJacky";
}
public Person(String aName){
this.Name=aName;
}
public void show(){
System.out.println("my name is " + Name + "!\n");
}
}
class Finery extends Person{ protected Person cmp=null; public void decorator(Person a){ this.cmp=a; } public void show(){ if(cmp!=null) cmp.show(); }}
class TShirt extends Finery{ public void show(){ System.out.println("My TShirt!\n"); super.show(); }}
class Tie extends Finery{ public void show(){ System.out.println("My Tie!\n"); super.show(); }}class Person{
private String Name;
public Person(){
this.Name="HuangJacky";
}
public Person(String aName){
this.Name=aName;
}
public void show(){
System.out.println("my name is " + Name + "!\n");
}
}
class Finery extends Person{
protected Person cmp=null;
public void decorator(Person a){
this.cmp=a;
}
public void show(){
if(cmp!=null)
cmp.show();
}
}
class TShirt extends Finery{
public void show(){
System.out.println("My TShirt!\n");
super.show();
}
}
class Tie extends Finery{
public void show(){
System.out.println("My Tie!\n");
super.show();
}
}
public class Main {
public static void main(String[] args) {
Person p = new Person("TheFiend");
TShirt t = new TShirt();
Tie T = new Tie();
t.decorator(p);
T.decorator(t);
T.show();
}
}
其實代碼都是一樣,只是語言不同而已.
super.show();
在C#裡面我們就需要改成base.show();
最後進入Delphi Time.
Type
TPerson =
Class
Private
Name:
String;
Public
Constructor Create(
Const AName:
String );
Procedure Show( );
Virtual;
End;
TFinery =
Class( TPerson )
Private
FPerson: TPerson;
Public
Procedure Show( );
Override;
Property Person: TPerson
Read FPerson
Write FPerson;
End;
TTShirt =
Class( TFinery )
Public
Procedure Show( );
Override;
End;
TTie =
Class( TFinery )
Public
Procedure Show( );
Override;
End;
{ TPerson }
Constructor TPerson.Create(
Const AName:
String );
Begin
Self.Name := AName;
End;
Procedure TPerson.Show;
Begin
Writeln( 'my name is ' + Name );
End;
{ TFinery }
Procedure TFinery.Show;
Begin
If Assigned( FPerson )
Then
FPerson.Show;
End;
{ TTShirt }
Procedure TTShirt.Show;
Begin
Writeln( 'My Shirt' );
Inherited;
End;
{ TTie }
Procedure TTie.Show;
Begin
Writeln( 'My Tie!' );
Inherited;
End;
測試:
Var
P: TPerson;
T: TTShirt;
I: TTie;
S:
String;
Begin
P := TPerson.Create( 'HuangJacky' );
T := TTShirt.Create( '' );
I := TTie.Create( '' );
T.Person := P;
I.Person := T;
I.Show;
Readln( S );
End.
OK,Delphi也是這樣的.
我們可以看到Delphi裡面是一句Inherited;因為調用的是父類的同名同參數的函數 所以函數名可以省略掉.不然就要寫成
Inherited show();了
總結下,裝飾模式適用的情況:
- 在不影響其他對象的情況下,以動態、透明的方式給單個對象添加職責。
- 處理那些可以撤消的職責。
- 當不能採用產生子類的方法進行擴充時。一種情況是,可能有大量獨立的擴充,
- 為支援每一種組合將產生大量的子類,使得子類數目呈爆炸性增長。
- 另一種情況可能是因為類定義被隱藏,或類定義不能用於產生子類。
就到這裡,我是DH.