结构型模式共七种:
- 适配器模式(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();
}
}