软件工程 设计模式学习之装饰模式Decorator

技术交流,DH讲解

如果我们想在不改变已有类的情况下,然后加上新的功能.
这个时候我们就可以使用装饰模式了.
惯例先看下这个设计模式的UML图.
decorator
装饰模式关键是方法重载.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.
原文地址:https://www.cnblogs.com/huangjacky/p/1619796.html