行為型模式:
策略模式
它定義了算法家族,分別封裝起來,讓它們之間可以相互替換,此模式讓算法的變化,不會影響到使用算法的客戶。
簡單工廠模式的不足:
由於工廠本身包括了所有的收費方式,商場是可能經常性的更改打折額度和返利額度,每次維護或擴展收費方法都要改動這個工廠,以致代碼需重新編譯部署,很麻煩
方法:
1,定義一個所有支持的算法的公共接口
2,將所有具體算法或行為封裝在一起
3,維護對公共接口的引用
客戶端代碼是將所有的算法實例化
這個模式涉及到三個角色:
環境(Context)角色:持有一個Strategy類的引用。
抽象策略(Strategy)角色:這是一個抽象角色,通常由一個接口或抽象類實現。此角色給出所有的具體策略類所需的接口。
具體策略(ConcreteStrategy)角色:包裝了相關的算法或行為
優點:
使用策略模式可以把行為和環境分割開來。環境類負責維持和查詢行為類,各種算法則在具體策略類(ConcreteStrategy)中提供。由於算法和環境獨立開來,算法的增減、修改都不會影響環境和客戶端。當出現新的促銷折扣或現有的折扣政策出現變化時,只需要實現新的策略類,並在客戶端登記即可。策略模式相當於"可插入式(Pluggable)的算法"
個人理解:
策略模式與工廠模式
工廠模式是將需要實例化的所有對象放到一個類中,然後在客戶端直接使用工廠的方法,實現不同對象的不同操作
策略模式是將工廠中的方法提取出來,然後將需要實例化的對象都放到了客戶端去實例。當我需要添加不同的策略時,只在客戶端添加它的實例即可,然後將對象作為參數傳到策略模式中即可
策略模式結構圖:
課本實例:商場打折
代碼如下:
[csharp]
class cashcontext
{
//基類類型的對像
private CashSuper cs;
//初始化時(構造函數),傳入具體的對象
public cashcontext(CashSuper csuper)
{
this.cs = csuper;
//將csuper賦給cs,然後計算cs對象的收到的現金數
//通過傳入參數的不同,計算不同方式的收到現金數
}
public double getresult(double money)
//根據具體的策略對象,調用其算法的方法
{
return cs.acceptCash(money);
}
}
備忘錄模式
在不破壞封裝性的前提下,捕獲一個對象的內部狀態,並在該對象之外保存這個狀態.這樣以後就可將該對象恢復到原先保存的狀態.
Memento模式比較適用於功能比較 復雜的,但需要維護或記錄屬性歷史的類,或者需要保存的屬性只是眾多屬性中的一小部分時,Originator可以根據保存的Memento信息還原到前一狀態
課本實例:游戲的狀態保存
代碼如下:
[csharp]
//一個發起人類:有攻擊力,生命力,還有創建備忘和恢復備忘的功能等
class GameRole
{
//生命力
private int vit;
public int Vitality
{
get { return vit; }
set { vit = value; }
}
//攻擊力
private int atk;
public int Attack
{
get { return atk ; }
set { atk = value; }
}
//防御類
private int def;
public int Defense
{
get { return def ; }
set { def = value; }
}
//狀態顯示
public void StateDisplay()
{
Console.WriteLine("角色當前狀態:");
Console.WriteLine("體力:{0}", this.vit);
Console.WriteLine("攻擊力:{0}", this.atk);
Console.WriteLine("防御類:{0}", this.def);
Console.WriteLine("");
}
//獲得初始狀態
public void GetInitState()
{
this.vit = 100;
this.atk = 100;
this.def = 100;
}
//戰斗
public void Fight()
{
this.vit = 0;
this.atk = 0;
this.def = 0;
}
//保存角色狀態
public RoleStateMemento SaveState()
{
//保存狀態時,創建存儲箱
return (new RoleStateMemento(vit, atk, def));
}
//恢復角色狀態
public void RecoveryState(RoleStateMemento memento)
{
this.vit = memento.Vitality ;
this.atk = memento .Attack ;
this.def = memento.Defense ;
}
}
//一個備忘錄類:將要備忘的內容存儲在備忘錄中
//角色狀態存儲箱
class RoleStateMemento
{
private int vit;
private int atk;
private int def;
//以上是角色狀態存儲箱的一些屬性
public RoleStateMemento(int vit, int atk, int def)
{
this.vit = vit;
this.atk = atk;
this.def = def;
}
//生命力
public int Vitality
{
get { return vit; }
set { vit = value; }
}
//攻擊力
public int Attack
{
get { return atk ; }
set {atk = value; }
}
//防御力
public int Defense
{
get { return def ; }
set {def = value; }
}
//以上是存儲箱的一些函數,是指可以對生命力等狀態進行讀寫
}
//一個管理者類:將備忘錄類進行封裝,以便在客戶端只需要知道管理者這個類,將備忘的
//角色狀態管理者
class RoleStateCaretaker
{
private RoleStateMemento memento;
public RoleStateMemento Memento
{
get { return memento; }
set { memento = value; }
}
}
//客戶端:
//大戰前
GameRole hejingyuan = new GameRole();
hejingyuan.GetInitState();
hejingyuan.StateDisplay();
//保存進度
RoleStateCaretaker stateAdmin = new RoleStateCaretaker();
stateAdmin.Memento = hejingyuan.SaveState();
//大戰時,損耗嚴重
hejingyuan.Fight();
hejingyuan.StateDisplay();
//恢復之前狀態
hejingyuan.RecoveryState(stateAdmin.Memento);
hejingyuan.StateDisplay();
Console.Read();
個人理解:
備忘錄模式:當我要保存備忘時,再發起人(游戲角色)這個類中就創建備忘錄,備忘錄這個類中具有要備忘的一些內容(屬性和方法)等,管理者是對備忘錄進行包裝,在客戶端將發起人備忘賦給管理者這個對象,這樣客戶端的人就不需要知道我備忘的是什麼內容了。
迭代器模式
提供一種方法順序訪問一個聚合對象中各個元素,而又不暴露該對象的內部表示。
當你需要訪問一個聚集對象,而且不管這些對象是什麼都需要遍歷的時候,你就應該考慮用迭代器模式
應用:
當你需要對聚集有多種方法遍歷時,可以考慮用迭代器模式
總的來說,迭代器模式就是分離了集合對象的遍歷行為,抽象出一個迭代器類來負責,這樣既可以做到不暴露集合的內部結構,又可讓外部代碼透明地訪問集合內部的數據.
課本實例:乘車買票
代碼如下:
[csharp]
//Iterator迭代器抽象類
abstract class Iterator
{
public abstract object First();
public abstract object Next();
public abstract object IsDone();
public abstract object CurrentItem();
}
//迭代器就是對一個聚集對象遍歷
//ConcreteIterator具體迭代器類,繼承Iterator
class ConcreteIterator : Iterator
{
//創建了一個具體聚集對象
private ConcreteAggregate aggregate;
private int current = 0;
public ConcreteIterator(ConcreteAggregate aggregate)
{
this.aggregate = aggregate;
}
//初始化時將具體的聚集對象傳入
public override object First()
{
return aggregate[0];
}
public override object Next()
{
object ret = null;
current++;
if (current < aggregate.Count)
{
ret = aggregate[current];
}
return ret;
}
public override object IsDone()
{
return current >= aggregate.Count ? true : false;
}
public override object CurrentItem()
{
return aggregate[current];
}
}
//具體迭代器就是對具體聚集對象的操作,也是對抽象迭代器的重寫
//Aggregate
abstract class Aggregate
{
public abstract Iterator CreateIterator();
}
//抽象聚集類就是要創建迭代器
//ConcreteAggregate具體聚集類 繼承Aggregate
class ConcreteAggregate : Aggregate
{
private IList<object> items = new List<object>();
public override Iterator CreateIterator()
{
return new ConcreteIterator(this);
}
public int Count
{
get { return items.Count; }
}
public object this[int index]
{
get { return items[index]; }
set
{
items.Insert(index, value);
}
}
}
//具體聚集類中有用於存放聚合對象的變量,對抽象聚集類重寫,還有聚集總數,和聲明一個索引器