顯示具有 讀書會 標籤的文章。 顯示所有文章
顯示具有 讀書會 標籤的文章。 顯示所有文章

2008年8月7日 星期四

物件導向程式設計_介面(Interface)(8.6)

何謂介面(Interface):
在google上,的確有著非常多相關於介面(Interface)的討論、說明。
不曉得是不是本人智商過低,亦或是人家講的不清楚? 我是都有看沒有懂。
不過,看大家在都可以在各論壇討論得沸沸騰騰,所以,猜想答案應該是前者吧(本人智商過低)。
但是,畢竟用一種說法,並不代表可以說懂每一個人嘛,不然,哪來的「因材施教」呢?
也幸好,本人並非「朽木不可雕也」,看了一堆人的說法,總算是有點心得。
其實,透過字面上,我們也可以看得出來「介面(Interface)」是什麼東西。
就是某個東西,要操控、使用另一個東西時,中間的橋梁,
就像我們在使用電腦時,會有一個介面(window畫面),來指引你使用,
我們在看電視轉台時,會有個搖控器或是選台的按鈕讓你來轉台。
這邊主要的觀念是想說,「介面(Interface)」主要就是構成二者互動的橋梁。
有了這個概念後,我們把概念帶到程式這邊來:
介面(Interface)就是「程式碼」與「類別(Class)」之間的橋梁。
當然,我們在寫程式時,也不見得會採取介面(Interface)的方法,
我們會直接「程式碼--->類別」,並不會「程式碼--->介面--->類別」的流程。
只是說,若使用介面(Interface)的話,它們的關係,是這樣子的。
介面(Interface)的使用:(C#)
interface IHardDisk
{
void setDefault(); //設定硬碟容量的起始值
bool compareHD(int HD); //比較看哪個容量大
int HD_gigabyte{ set;get;} //設定/取得硬碟容量
public void errtest();
}
小提醒:
  1. 一般習慣,在命名介面(Interface)時,都以「I」為開頭表示Interface。
  2. 在定義介面(Interface)時,裡面的方法,屬性都只「定義」而已,並未真正的實作內容
  3. 由於,此為測試,所以真正在應用時,請適時地加上「Public」修飾詞。ex: Public interface IHardDisk {...}。
  4. 上面紅色字體,表示為錯誤的使用方法:不用加上「Public」修飾詞.
看完了如何定義一個介面(Interface)後,我們接著看範例。
介面(Interface)範例:
範例說明(實作):
  1. 定義介面(IHardDisk)
  2. 利用類別(HardDisk)實作介面
  3. 程式中,一改以往呼叫類別的方法,改以呼叫介面
  4. 使用該介面的各屬性、方法
小提醒:
  1. 在實作介面時,該介面所定義的方法、屬性,在類別那,都要一一實作
  2. 在實作介面時,每個「方法」都請加上修飾詞「Public
  3. 程式宣告時「IHardDisk ComputerHD=new HardDisk() ; 」,後面是 new 一個類別。
程式碼:
---------------------------------------------
interface IHardDisk
{
void setDefault(); //設定硬碟容量的起始值
bool compareHD(int HD); //比較看哪個容量大
int HD_gigabyte{ set;get;} //設定/取得硬碟容量

}
class HardDisk : IHardDisk //實作IHardDisk的介面
{
//將介面的各個方法、屬性實作出來
int hd_gigabyte;//宣告一個變數來存取硬碟容量的值

public void setDefault()//實作「設定起始值」的方法
{
hd_gigabyte = 520;
}

public bool compareHD(int HD)//實作「比較大小」的方法
{
if (HD > hd_gigabyte){return true;}
else{return false;}
}

public int HD_gigabyte //實作「取得/設定容量」的屬性
{
get { return hd_gigabyte; }
set {hd_gigabyte=value;}
}
}

protected void Page_Load(object sender, EventArgs e)
{
IHardDisk ComputerHD=new HardDisk() ; //宣告
ComputerHD.setDefault(); //設定硬碟容量的預設值
Response.Write(ComputerHD.HD_gigabyte); //取得硬碟容量
Response.Write(ComputerHD.compareHD(567)); //比較大小

}
--------------------------------------------
為何要使用介面(Interface):
看了以上的範例,會有個想法:這種作法,比我直接呼叫類別的方法還要繁瑣
我直接將方法寫在類別裡,再呼叫類別使用就好啦!(「程式碼--->類別」)
何必要這麼麻煩,還透過介面,多了一道手續(「程式碼--->介面--->類別」)
沒錯,藉由以上的範例,的確看不出用介面(Interface)的好處。
然而,使用介面的好處在於「泛用」。
所謂的「泛用」或許可以解釋成「廣泛地使用」,
也就是說,我們只要使用介面,就可以使用不同的類別(前提為,該類別必須實作該介面)
範例說明:(實作)
  1. 相同地我們定義一個介面(Interface)
  2. 另外,我們產生兩個類別一個適用於小型硬碟(miniHardDisk),另一個適用於大型硬碟(bigHardDisk)
  3. 兩者也都實作了IHardDisk的介面
  4. 再來,我們又新增了一個類別,這個類別裡,定義的方法為回傳一個介面的型態(將來都實作產生這個類別)
  5. 在程式碼中,可看到,我們在Computer的類別裡,我們目前是使用「小型硬碟」
  6. 在Page_Load中,我們輸出了介面,及二類別的資料
程式重點:
  1. 程式中,我們目前是使用「小型硬碟」,若突然要改成「大型硬碟」時,我們只需更動,Computer的類別即可,程式碼,完全不用更動
  2. 將類別中的「miniHardDisk cc = new miniHardDisk();」,改成「bigHardDisk cc = new bigHardDisk ();」
程式碼:
======================================

interface IHardDisk
{
void setDefault();//設定硬碟容量的起始值
bool compareHD(int HD);//比較看哪個容量大
int HD_gigabyte { set;get;}//設定/取得硬碟容量

}

class miniHardDisk : IHardDisk //實作IHardDisk的介面
{
//將介面的各個方法、屬性實作出來

int hd_gigabyte=0;//宣告一個變數來存取硬碟容量的值
public void setDefault()
{
hd_gigabyte = 40;

}
public bool compareHD(int HD)
{
if (HD > hd_gigabyte){return true;}
else{return false;}
}
public int HD_gigabyte
{
get { return hd_gigabyte; }
set {hd_gigabyte=value;}

}
}
class bigHardDisk : IHardDisk //實作IHardDisk的介面
{
//將介面的各個方法、屬性實作出來

int hd_gigabyte=0;//宣告一個變數來存取硬碟容量的值
public void setDefault()
{
hd_gigabyte = 1024;

}
public bool compareHD(int HD)
{
if (HD > hd_gigabyte) { return true; }
else { return false; }
}
public int HD_gigabyte
{
get { return hd_gigabyte; }
set { hd_gigabyte = value; }

}
}

class Computer
{
public IHardDisk Disk()
{
miniHardDisk cc = new miniHardDisk();
cc.setDefault();
return cc;
}
}


protected void Page_Load(object sender, EventArgs e)
{

IHardDisk Iabc = new Computer().Disk();
Response.Write("使用介面取得的值:");
Response.Write(Iabc.HD_gigabyte);
Response.Write("<br><br>");

Response.Write("使用bigHardDisk類別取得的值:");
bigHardDisk bHD = new bigHardDisk();
bHD.setDefault();
Response.Write(bHD.HD_gigabyte);
Response.Write("<br><br>");

Response.Write("使用miniHardDisk類別取得的值:");
miniHardDisk mHD = new miniHardDisk();
mHD.setDefault();
Response.Write(mHD.HD_gigabyte);



}

======================================
議題:
這時,也會有個疑問:
既然這樣的話,我還是一樣可以使用類別呀,
反正也是一定要創造兩個類別,那我在Page_Load時,再改呀
類別的寫法-->
Response.Write("使用bigHardDisk類別取得的值:");
miniHardDisk mHD = new miniHardDisk ();
mHD .setDefault();
Response.Write(mHD .HD_gigabyte);
Response.Write("<br><br>");
那當我要由小型硬碟改成大型時,就把
miniHardDisk mHD = new miniHardDisk ();
改成
bigHardDisk bHD = new bigHardDisk();
也行呀。
------------>
很好,說得沒錯,不過,首先,會先遇到個問題
「命名」,已由 mHD --> bHD ,勢必程式碼裡面的名稱都要修改
再者,假設,不修改名稱,我就硬用 mHD 用到底,反正都可以用嘛。
是啊,可以用,可是,又面臨到另個問題,
目前程式是只有一頁而已,那假設,我們已經使用原先物件的寫法,寫了10頁,
甚至於好幾十頁,請問,你要一支一支改嗎?
那如果我們使用「介面」的方法,就只要修改我們類別庫裡的該Computer類別即可。

2008年7月11日 星期五

2008年5月21日 星期三

AJAX 初探 (Part 1)(5.21)

書刊:Learning ASP.NET 2.0 with AJAX



AJAX所包含的技術:


  • 畫面部份:XHTML、CSS、DOM

  • 資料處理部份:XML、XSLT

  • 資料前後端的傳送:XMLHttpRequest


ScriptManager



  • 使用 VS 2005 需再另外下載「ASPAJAXExtSetup.exe」。

  • 微軟用來整合各種技術來達成 AJAX 技術的元件

  • UpdatePanel 搭配使用

  • 下載網頁:http://www.asp.net/ajax/downloads/

AjaxControlToolkit



  • 使用 VS 2005 需再另外下載「AjaxControlToolkit」。

  • 將下載的範例裡「AjaxControlToolkit\SampleWebSite\Bin」裡的「dll」檔,複製至想要的地方。

  • 在工具箱中加入「新索引標籤」,並加入「AjaxcontrolToolkit.dll」即可載入39個 Toolkit工具。

  • 下載網頁:http://www.asp.net/ajax/downloads/

  • 嵌入Ajax control Toolkit工具箱教學



2008年4月24日 星期四

Threading (Part 4)(4.24)

書刊:Application Development Foundation


其它同步的方法(p.398)
  • ReaderWriterLock
  • Mutex
  • Sempaphore
  • AutoResetEvent
  • ManualResetEvent

ReaderWriterLock(p.398)

  • 定義鎖定:單一寫入器和多重讀取器
  • 不像其它同步的方法,它可以容許同時多個執行緒進行讀取
  • 如果資源不常變更的話,此方式的效能會比 Monitor 佳
  • 使用 AcquireReaderLock 來取得讀取鎖定
  • 使用 AcquireWriterLock 來取得寫入鎖定
  • 使用 ReleaseReaderLock/ReleaseWriterLock 來解除鎖定
  • 使用 UpgradeToWriterLock 來由讀取升級為寫入鎖定
  • 使用 DowngradFromWriterLock 來由寫入還原為讀取鎖定

Mutex(p.402)

  • 和 Monitor 類似
  • 具有跨 AppDomain 的功能

Semaphore(p.405)

  • 具有跨 AppDomain 的功能
  • 可以自行限制允許的緒行緒數量(一般只能一個)

Event(p.406)

  • 具有跨 AppDomain 的功能
  • 分為「AutoResetEvent」及「ManualResetEvent」

2008年4月17日 星期四

Threading (Part 3)(4.17)

書刊:Application Development Foundation



Lession 2 : 共享資料的存取(Sharing Data)(p.387)


防止資料衝突(Avoiding Collisions)


  • 在多個執行緒同時共用同個全域變數執行時,會發生重覆存取的狀況

生活範例 :

假設在Server上有個 Word 檔,希望3個人(A,B,C)在上面簽名,

命令一發出去,3個人跑來要簽名,A 很快的取得頭籌搶先簽到名,

所以在該檔上,有了 A 的簽名,再來 B 也很快的把 Word 檔讀出去要簽名,

此時,C 也把檔案讀了出去,當 B 簽好名,把 Word 檔存了進去,

進而,C 也簽好了,把他的 Word 檔存了進去。

這時候發生了個狀況,發現,上面居然沒有 B 的簽名。

因為,B 簽名的那個檔案,被 C 的檔案蓋掉了。

這就是該本課的重點,教導如何將這些全域的資料鎖定(只有單一執行緒能讀取)



單一數值變數適用(p.390) :

  • Interlocked Static Methods
  • Add : 將兩個64位元的整數相加,並以總合取代第一個整數
  • Decrement :遞減特定變數並將其儲存
  • Exchange : 將平台特定的控制代碼或指標設定為指定值,然後傳回
  • Increment : 遞增特定變數並將其儲存
  • Read :傳回64位字的值
  • 以上皆為「不可部份完成」(鎖定)
  • 效能比較好(如果只做遞增減運算)

程式範例



區域型適用 :

  • lock(簡單型)(p.394)
  • Monitor Static Methods(進階型)(p.395)
  • Enter :取得指定物件的獨佔鎖定
  • Exit :釋出指定物件的獨佔鎖定
  • TryEnter :嘗試取得指定物件的獨佔鎖定(在指定時間內)
  • Wait :釋出物件的鎖定,並且封鎖執行緒,直到此執行緒重新取得鎖定

程式範例


Understanding Deadlocks(p.396)

  • 由於要執行的程式,被鎖定,而使程式在那
  • 可利用 Monitor.TryEnter 方法,並設定鎖定時間來解決


程式範例


2008年4月10日 星期四

Threading (Part 2)(4.10)

書刊:Application Development Foundation




















帶參數的執行緒(Passing Data to Threads)(p.377)
  • 必須使用 ParameterizedThreadStart 的物件來委派
  • 指定委派的方法,必須是個有帶 object 型態參數的方法
終止執行緒(Stopping Threads)(p.379)
  • 使用 theThread.Abort() 來執行終止執行緒( theThread 是物件名稱)
  • 適情況來使用「關鍵區域(CriticalRegion)」,防止執行緒執行不完全
  • Thread.BeginCriticalRegion() => 關鍵區域起點
  • Thread.EndCriticalRegion() => 關鍵區域終點
  • 當執行緒處於關鍵區域時,它會繼續執行直到離開關鍵區域才終止(Stop)
執行背景內容(Execution Context)(p.381)
  • 每個執行緒都有散播相關資訊給下一代的能力
  • 相反地,每個執行緒都會繼承其相關資訊
  • 優點:直接可接收相關資訊來使用
  • 缺點:繼承的過程中比較耗效能
  • ExecutionContext 類別提供「SuppressFlow」、「RestorFlow」來控制是否繼承
  • 透過 AsyncFlowControl 來移轉資料流達到關閉的效果
  • 利用 theFlow.Undo() 重新開啟散播功能( theFlow 是 AsyncFlowControl 物件名」
  • 若要在關閉散播功能後,繼續使用相關資訊,可在「前面」加入 ExecutionContext.Capture()來備份一份,之後要使用時,再利用 ExecutionContext.Run 來執行指定的內容
相關的使用方法,請參見「程式範例」


程式範例


2008年4月3日 星期四

Threading (part 1)(4.2)

書刊:Application Development Foundation

何謂「Threading」?(p.367)


  • 「Threading」為開發軟體裡中,甚為重要的一個觀念,主要就是能使程式正確地同時執行數個運算。也就是大家所稱的「多工」。

本章的內容,將分成三個課程。

  • Lesson 1 : Creating Threads
  • Lesson 2 : Sharing Data
  • Lesson 3 : The Asynchronous Programming Model

測試練習的方法(p.368) :

  1. 新增一個「主控台應用程式(Console application)」
  2. 在前面的部份加入參考「Using System.Threading」(C#)
Lession 1 : 產生執行緒(Creading Threads)(p.369)


介紹執行緒(Threads)

  • 執行緒重要屬性(Threads Properties) (p.369)
  • IsAlive : 指出目前的執行狀態
  • IsBackground : 是否背景執行
  • IsThreadPoolThread : 是否屬於Managed執行結果
  • ManagedThreadId : 唯一識別項
  • Name : 執行緒名稱
  • Priority : 指定或取得優先權
  • ThreadState : 目前執行緒的狀態
  • 執行緒方法(Threads Methods)(p.370)
  • Abort : 結束執行緒(無法再用Start啟動)
  • Interrupt : 插斷在WaitJoinSleep的執行
  • Join : 封鎖呼叫執行緒
  • Resume : 恢復執行緒
  • Start : 把目前的執行個體改成以thread執行(啟動執行緒)
  • Supend : 將執行緒暫停
  • 執行緒靜態屬性(Static Thread Properties)(p.370)
  • CurrentContext : 取得執行緒正在執行的內容
  • CurrentPrincipal : 角色架構安全性用
  • CurrentThread : 取得目前執行的執行緒
  • 執行緒靜態方法(Static Thread Methods)(p.371)
  • BeginCriticalRegion
  • EndCriticalRegion
  • GetDomain
  • GetDomainID
  • ResetAbort
  • Sleep : 封鎖目執行緒一段指定的時間
  • SpinWait
  • VolatileRead
  • VolatileWrite
  • 執行緒狀態列舉(ThreadState Enumeration)(p.371)
  • Aborted : 結束狀態
  • AbortRequested : 被要求結束中
  • Background : 背景執行
  • Running : 已啟動
  • Stopped : 已停止
  • StopRequested : 被要停止中
  • Suspended : 已經暫停
  • SuspendedRequested : 被要求暫停中
  • Unstarted : 未被呼叫啟用
  • WaitSleepJoin : 因為呼叫「Momtor.Wait」「Thread.Sleep」「Thread.Join」而被封鎖
  • 執行緒的優先權列舉(Thread Priority)(由最高到最低)(p.376)
  • Highest
  • AboveNormal
  • Normal
  • BelowNormal
  • Lowest


程式範例 (主要介紹「委派產生執行緒、啟動Start()、延緩Sleep()、封鎖Join()」)


2008年3月26日 星期三

Events and Code (3.27)

書刊:Beginning.ASP.NET.2.0(Wrox)


Web Server 架構(p.181)

  1. Post:將資料包裝在Http標頭內傳送給WebServer
  2. Get:把資料直接加在URL之後傳送

使用Server Controls可以克服Http的「Statelss(無記錄狀態)」的特性(p.182)

  • 一般的Html Controls在執行Sumit(Post)動作時,網頁元件會回復成原來未輸入資料的樣子,但Server Controls有著「PostBack」的功能,可以將元件資料Sumit給自己,所以便可保留狀態

PostBack 架構(p.190)

  1. PostBack顧名思議就是「post」->「back」,將網頁資料先post給自己後(記錄狀態)再傳送到WebServer
  2. 另外由於 PostBack的緣故,網頁在執行時每次都重跑一次「Page_Load」,所以可以另外加「IsPostBack」判斷是否「PostBack」來執行指令

事件觸發時機((p.195)

  1. 使用者控制(ex. Click)
  2. 繫結資料庫時(ex. DataBound、ItemDataBound)
  3. ASP.NET引發(ex.DataBind)(使用者另外要求)

取消事件(Canceling Events)(p.203)

  • 在對資料庫進行異動時(Inserting、Updating等...),另外可以有「取消」的事件,進行取消的動作。指令: e.Cancel(2.0新功能)

Global事件(Global Events)(p.206)

  1. Application_Start:在Web伺服器(IIS)啟動時,並且有第一個使用者執行程式時觸發
  2. Application_End:Web伺服器(IIS)關閉或停止時觸發
  3. Session_Start:網頁開始執行時(開始存取網頁)時觸發
  4. Session_End:Session TimeOut時觸發
  5. Application_Error:程式執行期間的例外狀況,如果沒有用「try...catch」攔的話,都會跑到此事件
  6. Profile_OnMigrateAnonymous:當設定檔的匿名使用者登入時觸發(2.0新功能)