软件工程 - 设计模式学习之装饰模式Decorator
技术交流,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();了
总结下,装饰模式适用的情况:
- 在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。
- 处理那些可以撤消的职责。
- 当不能采用生成子类的方法进行扩充时。一种情况是,可能有大量独立的扩展,
- 为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长。
- 另一种情况可能是因为类定义被隐藏,或类定义不能用于生成子类。