本篇博客我們說的是行為型模式,其中包括以下一種模式:觀察者模式、模板方法模式、命令模式、狀態模式、職責鏈模式、解釋器模式、中介者模式、訪問者模式、策略模式、備忘錄模式、迭代器模式。
13.管擦者模式
定義瞭一種一對多的依賴關系,讓多個觀察者對象同時監聽某個主題對象。這個主題對象在狀態發生變化時,會通知所有觀察者,使他們能夠自動更新自己。委托是一種很好的觀察者模式。(舉個例子:在Adidas廠商生產出來瞭一款新的衣服,所有的連鎖店(觀察者)都會得到通知)
UML圖:
代碼:
view plaincopy to clipboardprint?namespace 觀察者模式
{
class Class2
{
static void Main(string[] args)
{
Boss huhansan = new Boss();
StockObserver2 tongshi1 = new StockObserver2("為貫徹",huhansan );
NBAObserver2 tongshi2 = new NBAObserver2("以觀察",huhansan );
huhansan.Attach(tongshi1 );
huhansan.Attach(tongshi2);
huhansan.Detach(tongshi1 );
huhansan.SubjectState = "老板我回來瞭";
huhansan.Notify();
}
}
interface Subject //通知者接口
{
void Attach(Observer2 observer);
void Detach(Observer2 observer);
void Notify();
string SubjectState
{
get;
set;
}
}
class Boss : Subject //老板類
{
private IList<Observer2> observers = new List<Observer2>();
private string action;
public void Attach(Observer2 observer)
{
observers.Add(observer );
}
public void Detach(Observer2 observer)
{
observers.Remove(observer);
}
public void Notify()
{
foreach (Observer2 o in observers)
o.Update();
}
public string SubjectState
{
get
{
return action;
}
set
{
action = value;
}
}
}
class Secretary2 : Subject //老板類
{
private IList<Observer2> observers = new List<Observer2>();
private string action;
public void Attach(Observer2 observer)
{
observers.Add(observer);
}
public void Detach(Observer2 observer)
{
observers.Remove(observer);
}
public void Notify()
{
foreach (Observer2 o in observers)
o.Update();
}
public string SubjectState
{
get
{
return action;
}
set
{
action = value;
}
}
}
abstract class Observer2 //抽象觀察者
{
protected string name;
protected Subject sub;
public Observer2(string name, Subject sub)
{
this.name = name;
this.sub = sub;
}
public abstract void Update();
}
class StockObserver2 : Observer2
{
public StockObserver2(string name, Subject sub)
: base(name, sub)
{ }
public override void Update()
{
Console.WriteLine("{0}{1}關閉股票行情,繼續工作!",sub.SubjectState ,name );
}
}
class NBAObserver2 : Observer2
{
public NBAObserver2(string name, Subject sub)
: base(name, sub)
{ }
public override void Update()
{
Console.WriteLine("{0}{1}關閉NBA直播,繼續工作!", sub.SubjectState, name);
}
}
}
namespace 觀察者模式
{
class Class2
{
static void Main(string[] args)
{
Boss huhansan = new Boss();
StockObserver2 tongshi1 = new StockObserver2("為貫徹",huhansan );
NBAObserver2 tongshi2 = new NBAObserver2("以觀察",huhansan );
huhansan.Attach(tongshi1 );
huhansan.Attach(tongshi2);
huhansan.Detach(tongshi1 );
huhansan.SubjectState = "老板我回來瞭";
huhansan.Notify();
}
}
interface Subject //通知者接口
{
void Attach(Observer2 observer);
void Detach(Observer2 observer);
void Notify();
string SubjectState
{
get;
set;
}
}
class Boss : Subject //老板類
{
private IList<Observer2> observers = new List<Observer2>();
private string action;
public void Attach(Observer2 observer)
{
observers.Add(observer );
}
public void Detach(Observer2 observer)
{
observers.Remove(observer);
}
public void Notify()
{
foreach (Observer2 o in observers)
o.Update();
}
public string SubjectState
{
get
{
return action;
}
set
{
action = value;
}
}
}
class Secretary2 : Subject //老板類
{
private IList<Observer2> observers = new List<Observer2>();
private string action;
public void Attach(Observer2 observer)
{
observers.Add(observer);
}
public void Detach(Observer2 observer)
{
observers.Remove(observer);
}
public void Notify()
{
foreach (Observer2 o in observers)
o.Update();
}
public string SubjectState
{
get
{
return action;
}
set
{
action = value;
}
}
}
abstract class Observer2 //抽象觀察者
{
protected string name;
protected Subject sub;
public Observer2(string name, Subject sub)
{
this.name = name;
this.sub = sub;
}
public abstract void Update();
}
class StockObserver2 : Observer2
{
public StockObserver2(string name, Subject sub)
: base(name, sub)
{ }
public override void Update()
{
Console.WriteLine("{0}{1}關閉股票行情,繼續工作!",sub.SubjectState ,name );
}
}
class NBAObserver2 : Observer2
{
public NBAObserver2(string name, Subject sub)
: base(name, sub)
{ }
public override void Update()
{
Console.WriteLine("{0}{1}關閉NBA直播,繼續工作!", sub.SubjectState, name);
}
}
}
14. 模板方法模式
定義一個操作中的算法的骨架,而將一些步驟延遲到子類中。模板方法使得子類可以不改變一個算法的結構即可重新定義算法的某些特定步驟。將不變的行為搬到超類中,去除子類中的重復代碼來體現他的優勢,提供瞭一個很好的代碼復用平臺(舉個例子:學生考試有考試卷作為模板,之後通過不同的學生添加不同的答案得到不同的分數形成具體的類)
UML圖:
代碼:
view plaincopy to clipboardprint?//10.3 把容易改變的設置為虛方法
namespace 模板方法模式
{
class Class2
{
static void Main(string[] args)
{
TestPaper2 studentA = new TestPaperA2();
studentA.TestQuestion1();
studentA.TestQuestion2();
studentA.TestQuestion3();
}
}
class TestPaper2
{
public void TestQuestion1()
{
Console.WriteLine("楊過得到,後來給瞭郭靖,煉成倚天劍、屠龍刀的玄鐵可能是【】a.球墨鑄鐵 b.馬口鐵 c.高速合金鋼 d.碳素纖維");
Console.WriteLine("答案是:" + Answer1()); //使用虛方法
}
public virtual string Answer1() //添加一個虛方法,子類來實現這個虛方法
{
return "";
}
public void TestQuestion2()
{
Console.WriteLine("楊過、程英、陸無雙鏟除瞭青花,造成【】 a.使這種植物不再傷害人 b. 使一種珍惜物種滅絕 c.破壞瞭生物圈的生態平衡 d.造成該地區沙漠化");
Console.WriteLine("答案是:" + Answer2()); //使用虛方法
}
public virtual string Answer2() //添加一個虛方法,子類來實現這個虛方法
{
return "";
}
public void TestQuestion3()
{
Console.WriteLine("藍鳳凰致使華山師徒、桃谷六仙嘔吐不止,如果你是大夫,會給他們開什麼藥【】 a.阿司匹林 b.牛黃解毒片 c.氟哌酸 d.讓他們喝大量的牛奶 e.以上全不對");
Console.WriteLine("答案是:" + Answer3()); //使用虛方法
}
public virtual string Answer3() //添加一個虛方法,子類來實現這個虛方法
{
return "";
}
}
class TestPaperA2 : TestPaper2 //學生甲抄的試卷
{
public override string Answer1()
{
return "b";
}
public override string Answer2()
{
return "b";
}
public override string Answer3()
{
return "b";
}
}
class TestPaperB2 : TestPaper2 //學生乙抄的試卷
{
public override string Answer1()
{
return "b";
}
public override string Answer2()
{
return "b";
}
public override string Answer3()
{
return "b";
}
}
}
//10.3 把容易改變的設置為虛方法
namespace 模板方法模式
{
class Class2
{
static void Main(string[] args)
{
TestPaper2 studentA = new TestPaperA2();
studentA.TestQuestion1();
studentA.TestQuestion2();
studentA.TestQuestion3();
}
}
class TestPaper2
{
public void TestQuestion1()
{
Console.WriteLine("楊過得到,後來給瞭郭靖,煉成倚天劍、屠龍刀的玄鐵可能是【】a.球墨鑄鐵 b.馬口鐵 c.高速合金鋼 d.碳素纖維");
Console.WriteLine("答案是:" + Answer1()); //使用虛方法
}
public virtual string Answer1() //添加一個虛方法,子類來實現這個虛方法
{
return "";
}
public void TestQuestion2()
{
Console.WriteLine("楊過、程英、陸無雙鏟除瞭青花,造成【】 a.使這種植物不再傷害人 b. 使一種珍惜物種滅絕 c.破壞瞭生物圈的生態平衡 d.造成該地區沙漠化");
Console.WriteLine("答案是:" + Answer2()); //使用虛方法
}
public virtual string Answer2() //添加一個虛方法,子類來實現這個虛方法
{
return "";
}
public void TestQuestion3()
{
Console.WriteLine("藍鳳凰致使華山師徒、桃谷六仙嘔吐不止,如果你是大夫,會給他們開什麼藥【】 a.阿司匹林 b.牛黃解毒片 c.氟哌酸 d.讓他們喝大量的牛奶 e.以上全不對");
Console.WriteLine("答案是:" + Answer3()); //使用虛方法
}
public virtual string Answer3() //添加一個虛方法,子類來實現這個虛方法
{
return "";
}
}
class TestPaperA2 : TestPaper2 //學生甲抄的試卷
{
public override string Answer1()
{
return "b";
}
public override string Answer2()
{
return "b";
}
public override string Answer3()
{
return "b";
}
}
class TestPaperB2 : TestPaper2 //學生乙抄的試卷
{
public override string Answer1()
{
return "b";
}
public override string Answer2()
{
return "b";
}
public override string Answer3()
{
return "b";
}
}
}
15. 命令模式
將一個請求封裝為一個對象,從而使你可以用不同的請求對客戶進行參數化;對請求排隊或記錄請求日志,以及支持可撤銷的操作。它能比較容易的設計一個命令隊列,可以容易的實現對請求的撤銷和重做,添加命令不影響其他類
UML圖:
代碼:
view plaincopy to clipboardprint?//23.6命令模式——通過參數達到不同的命令
namespace 命令模式
{
class Class2
{
static void Main(string[] args)
{
Receiver r = new Receiver();
Command2 c = new ConcreteCommand(r);
Invoker i = new Invoker();
i.SetCommand(c);
i.ExecuteCommand();
Console.Read();
}
}
abstract class Command2 //抽象命令接口
{
protected Receiver receiver;
public Command2(Receiver receiver)
{
this.receiver=receiver ; //設置執行命令的對象
}
abstract public void Execute(); //執行命令
}
class ConcreteCommand : Command2
{
public ConcreteCommand(Receiver receiver)
: base(receiver)
{ }
public override void Execute()
{
receiver.Action(); //調用執行者的執行方法
}
}
class Invoker //命令的傳遞者——服務員
{
private Command2 command;
public void SetCommand(Command2 command)
{
this.command =command ;
}
public void ExecuteCommand()
{
command.Execute();
}
}
class Receiver //命令的接受者——執行者
{
public void Action()
{
Console.WriteLine("執行請求!");
}
}
}
//23.6命令模式——通過參數達到不同的命令
namespace 命令模式
{
class Class2
{
static void Main(string[] args)
{
Receiver r = new Receiver();
Command2 c = new ConcreteCommand(r);
Invoker i = new Invoker();
i.SetCommand(c);
i.ExecuteCommand();
Console.Read();
}
}
abstract class Command2 //抽象命令接口
{
protected Receiver receiver;
public Command2(Receiver receiver)
{
this.receiver=receiver ; //設置執行命令的對象
}
abstract public void Execute(); //執行命令
}
class ConcreteCommand : Command2
{
public ConcreteCommand(Receiver receiver)
: base(receiver)
{ }
public override void Execute()
{
receiver.Action(); //調用執行者的執行方法
}
}
class Invoker //命令的傳遞者——服務員
{
private Command2 command;
public void SetCommand(Command2 command)
{
this.command =command ;
}
public void ExecuteCommand()
{
command.Execute();
}
}
class Receiver //命令的接受者——執行者
{
public void Action()
{
Console.WriteLine("執行請求!");
}
}
}
16. 狀態模式
當一個對象的內在狀態改變時允許改變其行為,這個對象看起來是改變瞭其類。狀態模式主要解決的是當控制一個對象狀態轉換的條件表達式過於復雜的時候,狀態的判斷邏輯轉移到表示不同狀態的一系列類當中,可以把復雜的判斷邏輯簡化。通過將各種狀態轉移到狀態類的子類中減少相互之間的依賴。通過類中的函數將本身轉換為下一個類,調用相應的方法。(舉個例子:你想去辦點事去找人,先是去得鄉政府,鄉長說這事不歸我管你得去找書記,找到書記,書記又說這事不歸我管你得去找縣長,找到縣長他說這事你得等我也沒辦法)
UML圖:
代碼:
view plaincopy to clipboardprint?//16.5狀態模式
namespace 狀態模式
{
class Class2
{
static void Main(string[] args)
{
Context c = new Context(new ConcreteStateA());
c.Request();
c.Request();
c.Request();
c.Request();
Console.Read();
}
}
abstract class State
{
public abstract void Handle(Context context);
}
class ConcreteStateA : State
{
public override void Handle(Context context)
{
context.State = new ConcreteStateB();
}
}
class ConcreteStateB : State
{
public override void Handle(Context context)
{
context.State = new ConcreteStateA();
}
}
class Context
{
private State state;
public Context(State state)
{
this.state = state;
}
public State State
{
get { return state; }
set
{
state = value;
Console.WriteLine("當前狀態:"+state.GetType().Name );
}
}
public void Request()
{
state.Handle(this );
}
}
}
//16.5狀態模式
namespace 狀態模式
{
class Class2
{
static void Main(string[] args)
{
Context c = new Context(new ConcreteStateA());
c.Request();
c.Request();
c.Request();
c.Request();
Console.Read();
}
}
abstract class State
{
public abstract void Handle(Context context);
}
class ConcreteStateA : State
{
public override void Handle(Context context)
{
context.State = new ConcreteStateB();
}
}
class ConcreteStateB : State
{
public override void Handle(Context context)
{
context.State = new ConcreteStateA();
}
}
class Context
{
private State state;
public Context(State state)
{
this.state = state;
}
public State State
{
get { return state; }
set
{
state = value;
Console.WriteLine("當前狀態:"+state.GetType().Name );
}
}
public void Request()
{
state.Handle(this );
}
}
}
17. 職責鏈模式
使多個對象都有機會處理請求,從而避免請求的發送者和接受者之間的耦合關系。將這個對象連成一條鏈,並沿著這條鏈傳遞該請求,直到有一個對象處理它位置。接受者和發送者沒有對方的明確信息,鏈中對象不知道鏈的結構,他們僅需要保持一個指向後繼者的引用(還拿上個狀態模式的例子為例,你去求鄉長辦事,但是這次鄉長沒有說讓你去找書記,而是說行瞭這事我辦吧,你回去吧,而是鄉長自己去找得書記,找瞭書記,書記也解決不瞭,書記找縣長,最後縣長給你打電話瞭說這事你必須得等)
UML圖:
代碼:
view plaincopy to clipboardprint?//24.5 加薪代碼重構,在客戶端讓管理者形成鏈
namespace 職責鏈模式
{
class Class2
{
static void Main(string[] args)
{
CommonManager jinli = new CommonManager("精力");
Majordomo zongjian = new Majordomo("總見");
GeneralManager zongjingli = new GeneralManager("總警力");
jinli.SetSuperior(zongjian );
zongjian.SetSuperior(zongjingli );
Request request = new Request();
request.RequestType = "請假";
request.RequestContent = "小菜請假";
request.Number = 1;
jinli.RequestApplications(request );
Request request2 = new Request();
request2.RequestType = "請假";
request2.RequestContent = "小菜請假";
request2.Number = 4;
jinli.RequestApplications(request2 );
Request request3 = new Request();
request3.RequestType = "加薪";
request3.RequestContent = "小菜請求加薪";
request3.Number = 500;
jinli.RequestApplications(request3 );
Request request4 = new Request();
request4.RequestType = "加薪";
request4.RequestContent = "小菜請求加薪";
request4.Number = 1000;
jinli.RequestApplications(request4);
Console.Read();
}
}
abstract class Manager1 //管理者接口
{
protected string name; //管理者的姓名
protected Manager1 superior; //管理者的上級
public Manager1(string name)
{
this.name = name;
}
//設置管理者的上級
public void SetSuperior(Manager1 superior)
{
this.superior = superior;
}
//申請請求
abstract public void RequestApplications(Request request);
}
class CommonManager : Manager1 //經理
{
public CommonManager(string name)
: base(name)
{ }
public override void RequestApplications(Request request)
{
if (request.RequestType == "請假" && request.Number <= 2)
{
Console.WriteLine("{0}:{1}數量{2}被批準", name, request.RequestContent, request.Number);
}
else
{
if (superior != null) //其餘的申請都需要轉移到上級
superior.RequestApplications(request);
}
}
}
class Majordomo : Manager1 //總監
{
public Majordomo(string name)
: base(name)
{ }
public override void RequestApplications(Request request)
{
if (request.RequestType == "請假" && request.Number <= 5)
{
Console.WriteLine("{0}:{1}數量{2}被批準", name, request.RequestContent, request.Number);
}
else
{
if (superior != null) //其餘的申請都需要轉移到上級
superior.RequestApplications(request);
}
}
}
class GeneralManager : Manager1 //總經理
{
public GeneralManager(string name)
: base(name)
{ }
public override void RequestApplications(Request request)
{
if (request.RequestType == "請假" && request.Number <= 5)
{
Console.WriteLine("{0}:{1}數量{2}被批準", name, request.RequestContent, request.Number);
}
else if (request.RequestType == "加薪" && request.Number <= 500)
{
Console.WriteLine("{0}:{1}數量{2}被批準", name, request.RequestContent, request.Number);
}
else if (request.RequestType == "加薪" && request.Number > 500)
{
Console.WriteLine("{0}:{1}數量{2}再說吧", name, request.RequestContent, request.Number);
}
}
}
}
//24.5 加薪代碼重構,在客戶端讓管理者形成鏈
namespace 職責鏈模式
{
class Class2
{
static void Main(string[] args)
{
CommonManager jinli = new CommonManager("精力");
Majordomo zongjian = new Majordomo("總見");
GeneralManager zongjingli = new GeneralManager("總警力");
jinli.SetSuperior(zongjian );
zongjian.SetSuperior(zongjingli );
Request request = new Request();
request.RequestType = "請假";
request.RequestContent = "小菜請假";
request.Number = 1;
jinli.RequestApplications(request );
Request request2 = new Request();
request2.RequestType = "請假";
request2.RequestContent = "小菜請假";
request2.Number = 4;
jinli.RequestApplications(request2 );
Request request3 = new Request();
request3.RequestType = "加薪";
request3.RequestContent = "小菜請求加薪";
request3.Number = 500;
jinli.RequestApplications(request3 );
Request request4 = new Request();
request4.RequestType = "加薪";
request4.RequestContent = "小菜請求加薪";
request4.Number = 1000;
jinli.RequestApplications(request4);
Console.Read();
}
}
abstract class Manager1 //管理者接口
{
protected string name; //管理者的姓名
protected Manager1 superior; //管理者的上級
public Manager1(string name)
{
this.name = name;
}
//設置管理者的上級
public void SetSuperior(Manager1 superior)
{
this.superior = superior;
}
//申請請求
abstract public void RequestApplications(Request request);
}
class CommonManager : Manager1 //經理
{
public CommonManager(string name)
: base(name)
{ }
public override void RequestApplications(Request request)
{
if (request.RequestType == "請假" && request.Number <= 2)
{
Console.WriteLine("{0}:{1}數量{2}被批準", name, request.RequestContent, request.Number);
}
else
{
if (superior != null) //其餘的申請都需要轉移到上級
superior.RequestApplications(request);
}
}
}
class Majordomo : Manager1 //總監
{
public Majordomo(string name)
: base(name)
{ }
public override void RequestApplications(Request request)
{
if (request.RequestType == "請假" && request.Number <= 5)
{
Console.WriteLine("{0}:{1}數量{2}被批準", name, request.RequestContent, request.Number);
}
else
{
if (superior != null) //其餘的申請都需要轉移到上級
superior.RequestApplications(request);
}
}
}
class GeneralManager : Manager1 //總經理
{
public GeneralManager(string name)
: base(name)
{ }
public override void RequestApplications(Request request)
{
if (request.RequestType == "請假" && request.Number <= 5)
{
Console.WriteLine("{0}:{1}數量{2}被批準", name, request.RequestContent, request.Number);
}
else if (request.RequestType == "加薪" && request.Number <= 500)
{
Console.WriteLine("{0}:{1}數量{2}被批準", name, request.RequestContent, request.Number);
}
else if (request.RequestType == "加薪" && request.Number > 500)
{
Console.WriteLine("{0}:{1}數量{2}再說吧", name, request.RequestContent, request.Number);
}
}
}
}
18. 解釋器模式
給定一個語音,定義它的文法的一種表示,並定義一個解釋器,這個解釋器使用該表示來解釋語言中的句子。如果一種特定類型的問題發生的頻率足夠高,就值得將該問題的各個實例表述為一個簡單語言中的句子,這就是解釋器。其實就是咱們平時說的“行話”(例如:小偷公司中的上天窗,下平臺;掏底兜,插馬後都有特殊的含義,大傢可以查查看,呵呵)
UML圖:
代碼:
view plaincopy to clipboardprint?namespace 解釋器模式
{
class Program
{
static void Main(string[] args)
{
Context context = new Context();
IList<AbstractExpression> list = new List<AbstractExpression>();
list.Add(new TerminalExpression());
list.Add(new NonterminalExpression ());
list.Add(new TerminalExpression ());
list.Add(new TerminalExpression());
foreach (AbstractExpression exp in list)
{
exp.Interpret(context );
}
Console.Read();
}
}
abstract class AbstractExpression
{
public abstract void Interpret(Context context );
}
class TerminalExpression : AbstractExpression
{
public override void Interpret(Context context)
{
Console.WriteLine("終端解釋器");
}
}
class NonterminalExpression : AbstractExpression
{
public override void Interpret(Context context)
{
Console.WriteLine("非終端解釋器");
}
}
class Context //解釋器之外的信息
{
private string input;
public string Input
{
get { return input; }
set { input = value; }
}
private string output;
public string Output
{
get { return output; }
set { output = value; }
}
}
}
作者“許德鵬的專欄”