定義對象間一對多依賴,當一個對象狀態改變,所有依賴者自動收到通知並更新。
Web 分頁顯示:初期僅需「上/下頁」按鈕 + GridView。後續需求疊加:顯示頁碼 Label、頁碼列表控制器。每新增一個觀察者,按鈕點擊事件就得多一行通知代碼,耦合失控。引入 Observer 解耦。
using System;
using System.Collections.Generic;
using System.Text;
namespace ObserverExample
{
class Program
{
static void Main(string[] args)
{
ButtonPager buttonPager = new ButtonPager();
ListPager listPager = new ListPager();
Control gridview = new GridView();
Control label = new Label();
buttonPager.changePageHandler += new Pager.ChangePageHandler(buttonPager.ChangePage);
buttonPager.changePageHandler += new Pager.ChangePageHandler(gridview.ChangePage);
buttonPager.changePageHandler += new Pager.ChangePageHandler(label.ChangePage);
buttonPager.changePageHandler += new Pager.ChangePageHandler(listPager.ChangePage);
listPager.changePageHandler += new Pager.ChangePageHandler(buttonPager.ChangePage);
listPager.changePageHandler += new Pager.ChangePageHandler(gridview.ChangePage);
listPager.changePageHandler += new Pager.ChangePageHandler(label.ChangePage);
listPager.changePageHandler += new Pager.ChangePageHandler(listPager.ChangePage);
buttonPager.NextPage();
Console.WriteLine();
buttonPager.NextPage();
Console.WriteLine();
buttonPager.NextPage();
Console.WriteLine();
buttonPager.PreviousPage();
Console.WriteLine();
buttonPager.PreviousPage();
Console.WriteLine();
listPager.SelectPage(2);
Console.WriteLine();
listPager.SelectPage(1);
Console.WriteLine();
listPager.SelectPage(0);
}
}
abstract class Pager
{
protected int pageIndex = 0;
public int PageIndex { get => pageIndex; set => pageIndex = value; }
protected int pageCount = 3;
public int PageCount => pageCount;
public event ChangePageHandler changePageHandler;
public delegate void ChangePageHandler(Pager sender);
protected void ChangePage()
{
changePageHandler?.Invoke(this);
}
}
class ButtonPager : Pager, Control
{
public void NextPage()
{
if (pageIndex < pageCount - 1)
{
Console.WriteLine("Click NextPage Button...");
pageIndex++;
ChangePage();
}
}
public void PreviousPage()
{
if (pageIndex > 0)
{
Console.WriteLine("Click PreviousPage Button...");
pageIndex--;
ChangePage();
}
}
public void ChangePage(Pager sender)
{
base.pageIndex = sender.PageIndex;
if (pageIndex > 0 && pageIndex < pageCount - 1)
Console.WriteLine("<<Previous Next>>");
else if (pageIndex == 0)
Console.WriteLine("Next>>");
else
Console.WriteLine("<<Previous");
}
}
class ListPager : Pager, Control
{
public void SelectPage(int pageIndex)
{
if (pageIndex >= 0 && pageIndex < pageCount)
{
Console.WriteLine($"Click <{pageIndex + 1}> Link...");
base.pageIndex = pageIndex;
ChangePage();
}
}
public void ChangePage(Pager sender)
{
base.pageIndex = sender.PageIndex;
for (int i = 1; i <= pageCount; i++)
Console.Write(pageIndex + 1 == i ? $" <{i}> " : $" {i} ");
Console.WriteLine();
}
}
interface Control { void ChangePage(Pager sender); }
class GridView : Control
{
public void ChangePage(Pager sender) => Console.WriteLine($"GridView->Show data of page {sender.PageIndex + 1}");
}
class Label : Control
{
public void ChangePage(Pager sender) => Console.WriteLine($"Label.Text=[{sender.PageIndex + 1}/{sender.PageCount}]");
}
}
ChangePage() 觸發事件;委派參數傳遞主體自身,讓觀察者可讀取狀態。NextPage/PreviousPage 驗證邊界、更新索引、呼叫 ChangePage() 通知觀察者。EventHandler<T>、EventArgs、虛擬 OnEvent 等)。