星期日, 8月 06, 2006

[設計模式]裝飾者模式

最近想包一個簡單好用的2D動畫程式,以前寫c++時遺留的產物該讓它消失了,C#的在物件導向的編寫上的確有著一定的優勢,雖然這個例子中不會顯示出來,但用純物件導向語言來實現設計模式是再適合不過了。
一直傷腦筋要怎樣才能設計一個相依性低,擴充又方便的動畫類別呢?當時腦中就想到Decorator這個好用的設計模式,也就是裝飾者模式,只是當時在趕案子就把它擱在一旁,現在有時間就好好把它完成。何謂裝飾者模式,用一個最簡單說法,就是你現在想要實現一個主要的功能,但是它可以附加許多小功能,這些小功能就是所謂的裝飾者,怎麼樣?是不是猜到如何應用到動畫程式上。典型的2D動畫程式,不外乎就是讓圖片動;而秀圖就是我們的主要功能,因為無論怎麼動都是要秀圖吧,但要怎麼動?動法有很多種,有換圖片、透明度變化,平移、旋轉、縮放‧‧等,anyway,這些都是使用者可以去做延伸,很明顯的,這些動法就是我的們附加功能,今天我想要縮放加平移,或是我想要透明度高低變化加上換圖片,這些都可以透過裝飾者模式來達成,覺得很神奇嗎?看看範例就知道實踐上一點都不難。

//裝飾者模式
using System;

namespace Decorator
{
///
/// 裝置者模式主要是包裹被裝飾者,可以用來將附加功能抽離
///

///
//可以是抽象類別或是介面
public abstract class Animation
{
public Animation()
{

}
public virtual void Perform()
{
}
}
//裝飾者類別
public abstract class Decorator:Animation
{
//有一個父類別的參考
public Animation anim;
//建構時 指向實體
public Decorator(Animation a)
{
anim=a;
}
//整個範例的精隨 覆寫執行方法
public override void Perform()
{
//會去呼叫指到實體的方法
anim.Perform();
}
}
//繼承動畫類別 假設這是要做2D動畫
public class Animation2D:Animation
{
public Animation2D()
{}
//一樣覆寫執行方法
public override void Perform()
{
Console.WriteLine("最後由我來畫圖\n");
}
}
//平移類別 繼承裝飾者類別
public class Translate:Decorator
{
public Translate(Animation anim):base(anim)
{}
//一樣覆寫執行方法
public override void Perform()
{
Console.WriteLine("我作了平移\n");
//要注意的是這行 他會去呼叫Dector所指向實體的方法 也就是說會去呼叫上一層的執行方法 類似遞迴的作法
base.Perform();
}
};
//旋轉類別 繼承裝飾者類別
public class Rotate:Decorator
{
public Rotate(Animation anim):base(anim)
{}
//同平移
public override void Perform()
{
Console.WriteLine("我作了旋轉\n");
base.Perform();
}
};
//縮放類別 繼承裝飾者類別
public class Scale:Decorator
{
public Scale(Animation anim):base(anim)
{}
//同平移
public override void Perform()
{
Console.WriteLine("我作了縮放\n");
base.Perform();
}
};

class Client
{
///
/// 應用程式的主進入點。
///

[STAThread]
static void Pause()
{
Console.WriteLine("Press Enter To Continue....");
Console.ReadLine();
}
static void Main(string[] args)
{
//很簡單的應用 我生成了一個動畫物件 我打包了旋轉 縮放 平移 而且這個動畫物件是2D的
//如此一來我就可以很方便的選取這個動畫需要哪些功能,就跟點菜一樣方便,不要的時候也可以抽離
Animation anim=new Rotate(new Scale(new Translate(new Animation2D())));
anim.Perform();
Pause();
}
}
}

//建議您載下來完整編譯執行看看會更了解。

沒有留言: