設計模式---結構型
結構型模式共七種:
- 介面卡模式(Adapter)
- 外觀模式(Facade)
- 橋接模式(Bridge)
- 裝飾器模式(Decorator)
- 代理模式(Proxy)
- 享元模式(Flyweight)
- 組合模式(Composite)
其中又分為
介面適配:介面卡、外觀、橋接模式
行為擴充套件:裝飾
效能與物件訪問:代理、享元模式
抽象集合:組合模式
介面卡模式(Adapter)
定義:將一個類的介面轉換成客戶希望的另外一個介面,Adapter模式使得原本由於介面不相容而不能一起工作的那些類可以一起工作。
角色:介面卡(Adapter)、被適配類、物件(Adaptee)
理解:客戶需要Target,現實只有Adaptee,可以用一個實現Target協議的介面卡通過類繼承或者物件組合類獲得被Adaptee。
結構圖
介面卡模式實現程式
//球員類 abstract class Player { protected string name; public Player(string name) { this.name = name; } public abstract void Attack(); public abstract void Defense(); } //前鋒類 class Forwards : Player { public Forwards(string name) : base(name) { } public override void Attack() { Console.WriteLine("前鋒 {0} 進攻", name); } public override void Defense() { Console.WriteLine("前鋒 {0} 防守", name); } } //中鋒類 class Center : Player { public Center(string name) : base(name) { } public override void Attack() { Console.WriteLine("中鋒 {0} 進攻", name); } public override void Defense() { Console.WriteLine("中鋒 {0} 防守", name); } } //後衛類 class Guards : Player { public Guards(string name) : base(name) { } public override void Attack() { Console.WriteLine("後衛 {0} 進攻", name); } public override void Defense() { Console.WriteLine("後衛 {0} 防守", name); } } //外籍中鋒 class ForeignCenter { private string name; public string Name { get { return name; } set { name = value; } } public void 進攻() { Console.WriteLine("外籍中鋒 {0} 進攻", name); } public void 防守() { Console.WriteLine("外籍中鋒 {0} 防守", name); } } //翻譯者類 class Translator : Player { private ForeignCenter wjzf = new ForeignCenter(); public Translator(string name) : base(name) { wjzf.Name = name; } public override void Attack() { wjzf.進攻(); } public override void Defense() { wjzf.防守(); } } //客戶端 class Program { static void Main(string[] args) { Player b = new Forwards("巴蒂爾"); b.Attack(); Player m = new Guards("麥克格雷迪"); m.Attack(); Player ym = new Translator("姚明"); ym.Attack(); ym.Defense(); Console.Read(); } }
橋接模式(Bridge)
定義:將抽象部分與它的實現部分分離,使它可以獨立的變更
角色:抽象層介面(Abstraction)、具體抽象層、實現者介面、具體實現者。
理解:這裡有兩個介面,一個是抽象層介面Abstraction,一個是Implementor介面,其中Abstraction持有Implementor的引用。客戶端通過Abstraction來連線Implementor,以後Implementor可以動態的改變而不影響Abstraction。
什麼時候用:
1.不想在抽象與實現之間形成固定的繫結關係(這樣就能在執行時切換實現)。
2.抽象與實現都應可以通過子類化獨立進行擴充套件。
3.對抽象的實現進行修改不應影響客戶端程式碼。4.如果每個實現需要額外的子類以細化抽象,則說明有必要把它們分成兩個部分。5.想在帶有不同抽象介面的多個物件之間共享一個實現。
結構圖
橋接模式實現程式
//手機品牌類
abstract class HandsetBrand
{
protected HandsetSoft soft;
//設定手機軟體
public void SetHandsetSoft(HandsetSoft soft)
{
this.soft = soft;
}
//執行
public abstract void Run();
}
//手機遊戲類
class HandsetGame : HandsetSoft
{
public override void Run()
{
Console.WriteLine("執行手機遊戲");
}
}
//手機品牌N的遊戲
class HandsetBrandNGame : HandsetBrandN
{
public override void Run()
{
Console.WriteLine("執行M品牌手機遊戲");
}
}
//手機品牌M的遊戲
class HandsetBrandMGame : HandsetBrandM
{
public override void Run()
{
Console.WriteLine("執行M品牌手機遊戲");
}
}
//手機品牌N
class HandsetBrandN : HandsetBrand
{
public override void Run()
{
soft.Run();
}
}
//手機品牌M
class HandsetBrandM : HandsetBrand
{
public override void Run()
{
soft.Run();
}
}
//手機軟體
abstract class HandsetSoft
{
public abstract void Run();
}
//手機通訊錄類
class HandsetAddressList : HandsetSoft
{
public override void Run()
{
Console.WriteLine("執行手機通訊錄");
}
}
//手機品牌M的通訊錄
class HandsetBrandMAddressList : HandsetBrandM
{
public override void Run()
{
Console.WriteLine("執行M品牌手機通訊錄");
}
}
//手機品牌N的通訊錄
class HandsetBrandNAddressList : HandsetBrandN
{
public override void Run()
{
Console.WriteLine("執行N品牌手機通訊錄");
}
}
//客戶端
class Program
{
static void Main(string[] args)
{
HandsetBrand ab;
ab = new HandsetBrandN();
ab.SetHandsetSoft(new HandsetGame());
ab.Run();
ab.SetHandsetSoft(new HandsetAddressList());
ab.Run();
ab = new HandsetBrandM();
ab.SetHandsetSoft(new HandsetGame());
ab.Run();
ab.SetHandsetSoft(new HandsetAddressList());
ab.Run();
Console.Read();
}
}
組合模式(Composite)
定義:將物件組合成樹形結構以表示’部分-整體’的層次結構。組合模式使得使用者對單個物件和組合物件的使用具有一致性。
理解:組合模式讓我們可以把相同的基型別的物件組合到樹狀結構中,其中父節點包含同類型的子節點。
什麼時候用:
1.想獲得物件抽象的樹形表示(部分-整體層次結構)。
2.想讓客戶端統一處理組合結構中的所有物件。
結構圖
組合模式實現程式
//公司類 抽象類或介面
abstract class Company
{
protected string name;
public Company(string name)
{
this.name = name;
}
public abstract void Add(Company c); //增加
public abstract void Remove(Company c); //移除
public abstract void Display(int depth); //顯示
public abstract void LineOfDuty(); //履行職責
}
//具體公司類 實現介面 樹枝節點
class ConcreteCompany : Company
{
private List<Company> children = new List<Company>();
public ConcreteCompany(string name) : base(name)
{
}
public override void Add(Company c)
{
children.Add(c);
}
public override void Remove(Company c)
{
children.Remove(c);
}
public override void Display(int depth)
{
Console.WriteLine(new string(' ', depth) + name);
foreach (Company component in children)
{
component.Display(depth + 2);
}
}
//履行職責
public override void LineOfDuty()
{
foreach (Company component in children)
{
component.LineOfDuty();
}
}
}
//人力資源部
class HRDepartment : Company
{
public HRDepartment(string name) : base(name)
{ }
public override void Add(Company c)
{
}
public override void Remove(Company c)
{
}
public override void Display(int depth)
{
Console.WriteLine(new String('-', depth) + name);
}
public override void LineOfDuty()
{
Console.WriteLine("{0} 員工招聘培訓管理", name);
}
}
//財務部
class FinanceDepartment : Company
{
public FinanceDepartment(string name) : base(name)
{ }
public override void Add(Company c)
{
}
public override void Remove(Company c)
{
}
public override void Display(int depth)
{
Console.WriteLine(new String('-', depth) + name);
}
public override void LineOfDuty()
{
Console.WriteLine("{0} 公司財務收支管理", name);
}
}
//客戶端
class Program
{
static void Main(string[] args)
{
ConcreteCompany root = new ConcreteCompany("北京總公司");
root.Add(new HRDepartment("總公司人力資源部"));
root.Add(new FinanceDepartment("總公司財務部"));
ConcreteCompany comp = new ConcreteCompany("上海華東分公司");
comp.Add(new HRDepartment("華東分公司人力資源部"));
comp.Add(new FinanceDepartment("華東分公司財務部"));
root.Add(comp);
ConcreteCompany comp1 = new ConcreteCompany("南京辦事處");
comp1.Add(new HRDepartment("南京辦事處人力資源部"));
comp1.Add(new FinanceDepartment("南京辦事處財務部"));
comp.Add(comp1);
ConcreteCompany comp2 = new ConcreteCompany("杭州辦事處");
comp2.Add(new HRDepartment("杭州辦事處人力資源部"));
comp2.Add(new FinanceDepartment("杭州辦事處財務部"));
comp.Add(comp2);
Console.WriteLine("\n結構圖: ");
root.Display(1);
Console.WriteLine("\n職責: ");
root.LineOfDuty();
Console.Read();
}
}
裝飾模式(Decorator)
定義:動態的給物件新增一些額外的責任,就增加功能來說,裝飾比生成子類更為靈活。
角色:元件介面(Component)、具體的元件、繼承至Component的修飾介面(Decorator)、具體的修飾
理解:修飾介面Decorator繼承Component,並持有Component的一個引用,所以起到了複用Component並增加新的功能。
什麼時候用:
1.想要在不影響其他物件的情況下,以動態、透明的方式給單個物件新增職責。
2.想要擴充套件一個類的行為,卻做不到。類定義可能被隱藏,無法進行子類化;或者對類的每個行為的擴充套件,哦支援每種功能組合,將產生大量的子類。
結構圖
裝飾模式實現程式
class Person
{
public Person ()
{ }
private readonly string name;
public Person (string name)
{
this.name = name;
}
public virtual void Show()
{
Console.WriteLine("裝扮的{0}", name);
}
}
class Finery:Person
{
protected Person component;
//打扮
public void Decorate(Person component)
{
this.component = component;
}
public override void Show()
{
if (component != null)
{
component.Show();
}
}
}
class TShirts:Finery
{
public override void Show()
{
Console.Write("大T恤 ");
base.Show();
}
}
class BigTrouser : Finery
{
public override void Show()
{
Console.Write("垮褲 ");
base.Show();
}
}
class Sneakers : Finery
{
public override void Show()
{
Console.Write("破球鞋 ");
base.Show();
}
}
class Suit : Finery
{
public override void Show()
{
Console.Write("西裝 ");
base.Show();
}
}
class Tie : Finery
{
public override void Show()
{
Console.Write("領帶 ");
base.Show();
}
}
class LeatherShoes : Finery
{
public override void Show()
{
Console.Write("皮鞋 ");
base.Show();
}
}
}
外觀模式(Facade)
定義:為子系統中一組不同的介面提供統一的介面
什麼時候用:
1.子系統正逐漸變得複雜,應用模式的過程中演化出許多類。可以使用外觀為這些子系統類提供一個較簡單的介面。
2.可以使用外觀對子系統分層,每個字系統級別有一個外觀做為入口。讓她們通過外觀進行通訊,可以簡化他們的依賴關係。
結構圖
外觀模式實現程式
//股票1類
class Stock1
{
//賣股票
public void Sell()
{
Console.WriteLine("股票1賣出");
}
//買股票
public void Buy()
{
Console.WriteLine("股票1買入");
}
}
//股票2類
class Stock2
{
//賣股票
public void Sell()
{
Console.WriteLine("股票2賣出");
}
//買股票
public void Buy()
{
Console.WriteLine("股票2買入");
}
}
//股票3類
class Stock3
{
//賣股票
public void Sell()
{
Console.WriteLine("股票3賣出");
}
//買股票
public void Buy()
{
Console.WriteLine("股票3買入");
}
}
//國債1類
class NationalDebt1
{
//賣國債
public void Sell()
{
Console.WriteLine("國債1賣出");
}
//買國債
public void Buy()
{
Console.WriteLine("國債1買入");
}
}
//房地產1類
class Realty1
{
//賣房地產1股份
public void Sell()
{
Console.WriteLine("房地產1股份賣出");
}
//買房地產1股份
public void Buy()
{
Console.WriteLine("房地產1股份買入");
}
}
//基金類
class Fund
{
Stock1 gu1;
Stock2 gu2;
Stock3 gu3;
NationalDebt1 nd1;
Realty1 rt1;
public Fund()
{
gu1 = new Stock1();
gu2 = new Stock2();
gu3 = new Stock3();
nd1 = new NationalDebt1();
rt1 = new Realty1();
}
public void BuyFund()
{
gu1.Buy();
gu2.Buy();
gu3.Buy();
nd1.Buy();
rt1.Buy();
}
public void SellFund()
{
gu1.Sell();
gu2.Sell();
gu3.Sell();
nd1.Sell();
rt1.Sell();
}
}
//客戶端
class Program
{
static void Main(string[] args)
{
Fund jijin = new Fund();
//基金購買
jijin.BuyFund();
//基金贖回
jijin.SellFund();
Console.Read();
}
}
享元模式(Flyweight)
定義:運用共享技術有效地支援大量細粒度的物件。
角色:享元池、享元介面、具體享元物件。
理解:客戶端需要享元物件時,先去享元池尋找,如果找到了就直接複用,如果沒有找到就建立享元物件並儲存到享元池。
結構圖
享元模式實現程式
//網站抽象類
abstract class WebSite
{
public abstract void Use(User user);
}
//具體網站類
class ConcreteWebSite : WebSite
{
private string name = "";
public ConcreteWebSite(string name)
{
this.name = name;
}
public override void Use(User user)
{
Console.WriteLine("網站分類: " + name + " 使用者: " + user.Name);
}
}
//使用者
public class User
{
private string name;
public User(string name)
{
this.name = name;
}
public string Name
{
get { return name; }
}
}
//網站工廠類
class WebSiteFactory
{
private Hashtable flyweights = new Hashtable();
//獲得網站分類
public WebSite GetWebSiteCategory(string key)
{
if (!flyweights.ContainsKey(key))
flyweights.Add(key, new ConcreteWebSite(key));
return ((WebSite)flyweights[key]);
}
//獲得網站分類總數
public int GetWebSiteCount()
{
return flyweights.Count;
}
}
//客戶端
class Program
{
static void Main(string[] args)
{
WebSiteFactory f = new WebSiteFactory();
WebSite fx = f.GetWebSiteCategory("產品展示");
fx.Use(new User("小菜"));
WebSite fy = f.GetWebSiteCategory("產品展示");
fy.Use(new User("大鳥"));
WebSite fl = f.GetWebSiteCategory("產品展示");
fl.Use(new User("倩倩"));
WebSite fm = f.GetWebSiteCategory("產品展示");
fm.Use(new User("富力士"));
WebSite fn = f.GetWebSiteCategory("產品展示");
fn.Use(new User("薩拉赫"));
Console.WriteLine("得到網站分類總數為 {0}", f.GetWebSiteCount());
Console.Read();
}
}
代理模式(Proxy)
定義:為其他物件提供一種代理以控制對這個物件的訪問
角色:客戶端(Client)、目標介面(subject)代理物件(Proxy)、真正的目標物件(RealSubject)
虛擬代理:客戶端擁有Subject的引用,其實就是Proxy物件,Proxy物件持有RealSubject的引用,呼叫Proxy.request Proxy會實際呼叫RealSubject.request
結構圖
代理模式實現程式
//代理介面
interface IGiveGift
{
void GiveDolls();
void GiveFlowers();
void GiveChocolate();
}
//被追求者類
class SchoolGirl
{
private string name;
public string Name
{
get { return name; }
set { name = value; }
}
}
//追求者類
class Pursuit : IGiveGift
{
SchoolGirl mm;
public Pursuit(SchoolGirl mm)
{
this.mm = mm;
}
public void GiveDolls()
{
Console.WriteLine(mm.Name + " 送你洋娃娃");
}
public void GiveFlowers()
{
Console.WriteLine(mm.Name + "送你鮮花");
}
public void GiveChocolate()
{
Console.WriteLine(mm.Name + "送你巧克力");
}
}
//代理類
class Proxy : IGiveGift
{
Pursuit gg;
public Proxy(SchoolGirl mm)
{
gg = new Pursuit(mm);
}
public void GiveDolls()
{
gg.GiveDolls();
}
public void GiveFlowers()
{
gg.GiveFlowers();
}
public void GiveChocolate()
{
gg.GiveChocolate();
}
}
//客戶端程式碼
class Program
{
static void Main(string[] args)
{
SchoolGirl chihan = new SchoolGirl();
chihan.Name = "痴漢";
Proxy daili = new Proxy(chihan);
daili.GiveDolls();
daili.GiveFlowers();
daili.GiveChocolate();
Console.Read();
}
}