设计模式—适配器、组合、桥接及享元模式
来源:互联网 发布:农村淘宝logo矢量图 编辑:程序博客网 时间:2024/05/18 01:32
适配器模式、组合模式、桥接及享元模式它们均属于结构型模式,先简单说一下它们各自的特点。
Ø 适配器模式
适配器模式分为类适配器模式和对象适配器模式。区别仅在于适配器角色对于被适配角色的适配是通过继承完成的还是通过组合来完成的。由于类适配器模式通过多继承对一个接口与另一个接口进行匹配,然而我们知道在C#、VB.NET、Java等语言是不支持多重继承的,也就是一个类只有一个父类,所以上图为对象适配器。
适配器模式:将一个类的接口转化成客户希望的另外一个接口。Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。
u 使用场合
使用一个已经存在的类,如果它的接口,也就是方法和你的要求不相同时,可以使用适配器模式。这样客户端可以统一调用同一接口,使得其更简单、更直接及紧凑。
在双方都不太易修改的时候再使用适配器模式适配。
适配模式强调的是接口的转换。
代码展示:
using System;using System.Collections.Generic;using System.Linq;using System.Text;namespace ConsoleApplication13{ abstract class Player //目标对于运动员要求 { protected string name; public Player(string name) { this.name = name; } public abstract void Attack(); //可以明白指令并能做出相应行动的运动员 public abstract void Defense(); } 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() //翻译者将Attack翻译为进攻告诉外籍中锋 { wjzf .进攻 (); } public override void Defense() //同理,即调用了player的方法 { wjzf .防御 (); } }客户端
static void Main(string[] args) { Player b = new Forwards("巴蒂尔"); //对于客户端来说就是调用的目标的方法 b.Attack(); Player m = new Guards("麦克格雷迪"); m.Attack(); Player ym = new Translator("姚明"); //对于客户端来说,调用的就是player的方法 ym.Attack(); ym.Defense(); Console.Read(); }
Ø 组合模式
组合模式(Composite):将对象组合成树形结构以表示‘部分-整体’的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。
u 使用场合
如果需求是体现部分与整体层次的结构时。
还有就是希望用户可以忽略组合对象与单个对象的不同,统一地使用组合结构中的所有对象时,可以用组合模式。
程序代码
using System;using System.Collections.Generic;using System.Linq;using System.Text;namespace ConsoleApplication14{ abstract class Company { protected string name; public Company(string name) { this.name = name; } public abstract void Add(Company c); //通常使用add与remove来增加和删除树枝或树叶功能 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); } }}
客户端
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(); }
Ø 桥接模式
桥接模式(Bridge):将抽象部分与它的实现部分分离,使它们都可以独立地变化。
实现指的是抽象类和它的派生类用来实现自己的对象。其核心的意图是把这些实现独立出来,让它们各自地变化。这就使得每种实现的变化不会影响其他实现,从而达到应对变化的目的。
我们知道继承是一种强耦合的结构,父类变,子类也得变,继承的多了之后可能增长为不可控制的庞然大物,并且如果需要修改的话,父类、子类均得改,这种依赖限制了灵活性并最终限制了复用性。而组合/聚成原则告诉我们组合是一个解决这种情况的不错的选择。
何为组合/聚合原则?
定义:组合/聚合(CARP):尽量使用组合/聚合,尽量不要使用继承。
组合是一种强“拥有”关系,体现了严格的部分与整体的关系,部分和整体的生命周期是一样的。而聚合则是一种弱“拥有”关系,体现的是A可以包含B,但是B不是A对象的一部分。
好处:有助于保持每个类被封装,并被集中在单个任务上。这样类和类继承层次会保持较小规模。不太可能会增大为庞然大物。
书上以手机软件统一为例,通过抽象与实现的分类,达到了某些类可以独立变化。
Ø 享元模式
享元模式(Flyweight):运用共享技术有效地支持大量细粒度的对象。
外部状态:随着环境改变而改变的,不可以共享的状态。
内部状态:相反,享元对象内部并且不会随着环境的改变而改变的状态。
享元模式作用:避免大量非常相类似的开销。
角色介绍:
抽象享元(Flyweight)角色:此角色是所有的具体享元类的超类,为这些类规定出需要实现的公共接口。那些需要外部状态(External State)的操作可以通过调用商业方法以参数形式传入。
具体享元(ConcreteFlyweight)角色:实现抽象享元角色所规定的接口。如果有内部状态的话,必须负责为内部状态提供存储空间。享元对象的内部状态必须与对象所处的周围环境无关,从而使得享元对象可以在系统内共享的。
享元工厂(FlyweightFactory)角色:本角色负责创建和管理享元角色。本角色必须保证享元对象可以被系统适当地共享。当一个客户端对象调用一个享元对象的时候,享元工厂角色会检查系统中是否已经有一个符合要求的享元对象。如果已经有了,享元工厂角色就应当提供这个已有的享元对象;如果系统中没有一个适当的享元对象的话,享元工厂角色就应当创建一个合适的享元对象。
u 使用场合
如果一个应用程序使用了大量的对象,而大量的这些对象造成了很大的存储开销时可以考虑应用。
对象的大多数状态可以外部状态,如果删除对象的外部状态,那么可以用相对较少的共享对象取代很多组对象。此时可以考虑使用。
Ø 小结
适配器模式(adapter):用于两个不兼容接口之间的转接。
组合模式(composite)用于构造对象组合结构。
桥接模式(bridge):用于将一个抽象与多个可能的实现连接起来。
享元模式(flyweight):针对细粒度对象的一种全局控制手段。
- 设计模式—适配器、组合、桥接及享元模式
- 23种设计模式3--结构型模式(适配器模式、装饰模式、代理模式、外观模式、桥接模式、组合模式、享元模式)
- 23种设计模式--结构型模式(适配器模式、装饰模式、代理模式、外观模式、桥接模式、组合模式、享元模式)
- JAVA基础10 设计模式:结构型模式(适配器 代理模式 桥接模式 享元模式 组合模式 装饰器模式)
- 代理模式、装饰模式、适配器模式、组合模式、桥梁模式、外观模式、享元模式【读书笔记】设计模式4章:结构型模式
- 结构型设计模式(一)(适配器模式,桥接模式,组合模式,装饰模式)
- java设计模式(工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式、适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式,。 行为型模式,共十一种:策略模式、模板方法)
- 编程常用设计模式详解--(中篇)(适配器、装饰、代理、外观、桥接、组合、享元)
- "围观"设计模式(30)--结构型设计模式总结(适配器、代理、装饰、外观、桥梁、组合、享元)
- 《大话设计模式》——学习笔记之"结构型模式"(适配器&装饰&桥接&组合&亨元&代理&外观)
- 设计模式:适配器模式,桥接模式
- 模式设计--适配器、桥接模式
- 适配器模式之享元模式
- 设计模式—适配器模式
- 设计模式—适配器模式
- 设计模式—适配器模式
- 设计模式—适配器模式
- 设计模式—适配器模式
- HDU 3790 最短路径问题(dijk最短路变形)
- startup and shut immediate
- 解决ubuntukylin 13.10安装wine时无法解决软件包依赖问题
- mac下matlab和c混编的问题
- Mybatis第一个例子
- 设计模式—适配器、组合、桥接及享元模式
- Android源代码仓库及其管理工具Repo分析
- 第十一话.写程序时身边坐了一只胖太,分分钟想一巴掌呼死她!
- 两个数组的元素之和最大的前k项
- 练习写C++代码(110)--让我猜猜你在想什么?
- mysql导入导出数据中文乱码解决方法小结
- 杭电 1233 (并查集)
- mtk 通过perl客制化
- android使用c语言编程