1、结构模式设计模式之Adapter(适配器) 定义:将两个不兼容的类纠合在一起使用,属于结构型模式,需要有Adaptee(被适配者)和Adaptor(适配器)两个身份.为何使用?我们经常碰到要将两个没有关系的类组合在一起使用,第一解决方案是:修改各自类的接口,但是如果我们没有源代码,或者,我们不愿意为了一个应用而修改各自的接口。 怎么办? 使用Adapter,在这两种接口之间创建一个混合接口(混血儿).如何使用?实现Adapter方式,其实think in Java的类再生一节中已经提到,有两种方式:组合(composition)和继承(inheritance).假设我们要打桩,有两种类:方形桩
2、 圆形桩.public class SquarePegpublic void insert(String str)System.out.println(SquarePeg insert():+str);public class RoundPegpublic void insertIntohole(String msg)System.out.println(RoundPeg insertIntoHole():+msg);现在有一个应用,需要既打方形桩,又打圆形桩.那么我们需要将这两个没有关系的类综合应用.假设RoundPeg我们没有源代码,或源代码我们不想修改,那么我们使用Adapter来实现这
3、个应用:public class PegAdapter extends SquarePegprivate RoundPeg roundPeg;public PegAdapter(RoundPeg peg)(this.roundPeg=peg;)public void insert(String str) roundPeg.insertIntoHole(str);在上面代码中,RoundPeg属于Adaptee,是被适配者.PegAdapter是Adapter,将Adaptee(被适配者RoundPeg)和Target(目标SquarePeg)进行适配.实际上这是将组合方法(compositio
4、n)和继承(inheritance)方法综合运用.PegAdapter首先继承SquarePeg,然后使用new的组合生成对象方式,生成RoundPeg的对象roundPeg,再重载父类insert()方法。从这里,你也了解使用new生成对象和使用extends继承生成对象的不同,前者无需对原来的类修改,甚至无需要知道其内部结构和源代码.如果你有些Java使用的经验,已经发现,这种模式经常使用。进一步使用上面的PegAdapter是继承了SquarePeg,如果我们需要两边继承,即继承SquarePeg 又继承RoundPeg,因为Java中不允许多继承,但是我们可以实现(implements
5、)两个接口(interface)public interface IRoundPegpublic void insertIntoHole(String msg);public interface ISquarePegpublic void insert(String str);下面是新的RoundPeg 和SquarePeg, 除了实现接口这一区别,和上面的没什么区别。public class SquarePeg implements ISquarePegpublic void insert(String str)System.out.println(SquarePeg insert():+s
6、tr);public class RoundPeg implements IRoundPegpublic void insertIntohole(String msg)System.out.println(RoundPeg insertIntoHole():+msg);下面是新的PegAdapter,叫做two-way adapter:public class PegAdapter implements IRoundPeg,ISquarePegprivate RoundPeg roundPeg;private SquarePeg squarePeg;/ 构造方法public PegAdapte
7、r(RoundPeg peg)this.roundPeg=peg;/ 构造方法public PegAdapter(SquarePeg peg)(this.squarePeg=peg;)public void insert(String str) roundPeg.insertIntoHole(str);还有一种叫Pluggable Adapters,可以动态的获取几个adapters中一个。使用Reflection技术,可以动态的发现类中的Public方法。设计模式之Bridge Bridge定义 :将抽象和行为划分开来,各自独立,但能动态的结合.为什么使用?通常,当一个抽象类或接口有多个具体
8、实现(concrete subclass),这些concrete之间关系可能有以下两种:1. 这多个具体实现之间恰好是并列的,如前面举例,打桩,有两个concrete class:方形桩和圆形桩;这两个形状上的桩是并列的,没有概念上的重复,那么我们只要使用继承就可以了.2.实际应用上,常常有可能在这多个concrete class之间有概念上重叠.那么需要我们把抽象共同部分和行为共同部分各自独立开来,原来是准备放在一个接口里,现在需要设计两个接口,分别放置抽象和行为.例如,一杯咖啡为例,有中杯和大杯之分,同时还有加奶 不加奶之分. 如果用单纯的继承,这四个具体实现(中杯 大杯 加奶 不加奶)之
9、间有概念重叠,因为有中杯加奶,也有中杯不加奶, 如果再在中杯这一层再实现两个继承,很显然混乱,扩展性极差.那我们使用Bridge模式来实现它.如何实现?以上面提到的咖啡 为例. 我们原来打算只设计一个接口(抽象类),使用Bridge模式后,我们需要将抽象和行为分开,加奶和不加奶属于行为,我们将它们抽象成一个专门的行为接口.先看看抽象部分的接口代码:public abstract class CoffeeCoffeeImp coffeeImp;public void setCoffeeImp() this.CoffeeImp = CoffeeImpSingleton.getTheCoffeImp
10、();public CoffeeImp getCoffeeImp() return this.CoffeeImp;public abstract void pourCoffee();其中CoffeeImp 是加不加奶的行为接口,看其代码如下:public abstract class CoffeeImppublic abstract void pourCoffeeImp();现在我们有了两个抽象类,下面我们分别对其进行继承,实现concrete class:/中杯public class MediumCoffee extends Coffeepublic MediumCoffee() setC
11、offeeImp();public void pourCoffee()CoffeeImp coffeeImp = this.getCoffeeImp();/我们以重复次数来说明是冲中杯还是大杯 ,重复2次是中杯for (int i = 0; i 2; i+)coffeeImp.pourCoffeeImp();/大杯public class SuperSizeCoffee extends Coffeepublic SuperSizeCoffee() setCoffeeImp();public void pourCoffee()CoffeeImp coffeeImp = this.getCoffe
12、eImp();/我们以重复次数来说明是冲中杯还是大杯 ,重复5次是大杯for (int i = 0; i 5; i+)coffeeImp.pourCoffeeImp();上面分别是中杯和大杯的具体实现.下面再对行为CoffeeImp进行继承:/加奶public class MilkCoffeeImp extends CoffeeImpMilkCoffeeImp() public void pourCoffeeImp()System.out.println(加了美味的牛奶);/不加奶public class FragrantCoffeeImp extends CoffeeImpFragrantC
13、offeeImp() public void pourCoffeeImp()System.out.println(什么也没加,清香);Bridge模式的基本框架我们已经搭好了,别忘记定义中还有一句:动态结合,我们现在可以喝到至少四种咖啡:1.中杯加奶2.中杯不加奶3.大杯加奶4.大杯不加奶看看是如何动态结合的,在使用之前,我们做个准备工作,设计一个单态类(Singleton)用来hold当前的CoffeeImp:public class CoffeeImpSingletonprivate static CoffeeImp coffeeImp;public CoffeeImpSingleton(
14、CoffeeImp coffeeImpIn) this.coffeeImp = coffeeImpIn;public static CoffeeImp getTheCoffeeImp()return coffeeImp;看看中杯加奶 和大杯加奶 是怎么出来的:/拿出牛奶CoffeeImpSingleton coffeeImpSingleton = new CoffeeImpSingleton(new MilkCoffeeImp();/中杯加奶MediumCoffee mediumCoffee = new MediumCoffee();mediumCoffee.pourCoffee();/大杯加
15、奶SuperSizeCoffee superSizeCoffee = new SuperSizeCoffee();superSizeCoffee.pourCoffee();注意: Bridge模式的执行类如CoffeeImp和Coffee是一对一的关系, 正确创建CoffeeImp是该模式的关键,Bridge模式在EJB中的应用EJB中有一个Data Access Object (DAO)模式,这是将商业逻辑和具体数据资源分开的,因为不同的数据库有不同的数据库操作.将操作不同数据库的行为独立抽象成一个行为接口DAO.如下:1.Business Object (类似Coffee)实现一些抽象的商
16、业操作:如寻找一个用户下所有的订单涉及数据库操作都使用DAOImplementor.2.Data Access Object (类似CoffeeImp)一些抽象的对数据库资源操作3.DAOImplementor 如OrderDAOCS, OrderDAOOracle, OrderDAOSybase(类似MilkCoffeeImp FragrantCoffeeImp)具体的数据库操作,如INSERT INTO 等语句,OrderDAOOracle是Oracle OrderDAOSybase是Sybase数据库.4.数据库 (Cloudscape, Oracle, or Sybase databa
17、se via JDBC API)设计模式之Composite(组合)板桥里人 2002/04/27Composite定义:将对象以树形结构组织起来,以达成“部分整体” 的层次结构,使得客户端对单个对象和组合对象的使用具有一致性.Composite比较容易理解,想到Composite就应该想到树形结构图。组合体内这些对象都有共同接口,当组合体一个对象的方法被调用执行时,Composite将遍历(Iterator)整个树形结构,寻找同样包含这个方法的对象并实现调用执行。可以用牵一动百来形容。所以Composite模式使用到Iterator模式,和Chain of Responsibility模式类
18、似。Composite好处:1.使客户端调用简单,客户端可以一致的使用组合结构或其中单个对象,用户就不必关系自己处理的是单个对象还是整个组合结构,这就简化了客户端代码。2.更容易在组合体内加入对象部件. 客户端不必因为加入了新的对象部件而更改代码。如何使用Composite?首先定义一个接口或抽象类,这是设计模式通用方式了,其他设计模式对接口内部定义限制不多,Composite却有个规定,那就是要在接口内部定义一个用于访问和管理Composite组合体的对象们(或称部件Component).下面的代码是以抽象类定义,一般尽量用接口interface,public abstract class
19、Equipmentprivate String name; /网络价格public abstract double netPrice();/折扣价格public abstract double discountPrice();/增加部件方法public boolean add(Equipment equipment) return false; /删除部件方法public boolean remove(Equipment equipment) return false; /注意这里,这里就提供一种用于访问组合体类的部件方法。public Iterator iter() return null;
20、 public Equipment(final String name) this.name=name; 抽象类Equipment就是Component定义,代表着组合体类的对象们,Equipment中定义几个共同的方法。public class Disk extends Equipmentpublic Disk(String name) super(name); /定义Disk网络价格为1public double netPrice() return 1.; /定义了disk折扣价格是0.5 对折。public double discountPrice() return .5; Disk是组
21、合体内的一个对象,或称一个部件,这个部件是个单独元素( Primitive)。还有一种可能是,一个部件也是一个组合体,就是说这个部件下面还有儿子,这是树形结构中通常的情况,应该比较容易理解。现在我们先要定义这个组合体:abstract class CompositeEquipment extends Equipmentprivate int i=0; /定义一个Vector 用来存放儿子private Lsit equipment=new ArrayList();public CompositeEquipment(String name) super(name); public boolean
22、 add(Equipment equipment) this.equipment.add(equipment); return true; public double netPrice() double netPrice=0.;Iterator iter=equipment.iterator();for(iter.hasNext()netPrice+=(Equipment)iter.next().netPrice();return netPrice;public double discountPrice() double discountPrice=0.;Iterator iter=equip
23、ment.iterator();for(iter.hasNext()discountPrice+=(Equipment)iter.next().discountPrice();return discountPrice;/注意这里,这里就提供用于访问自己组合体内的部件方法。/上面dIsk 之所以没有,是因为Disk是个单独(Primitive)的元素.public Iterator iter()return equipment.iterator() ;/重载Iterator方法 public boolean hasNext() return iequipment.size(); /重载Itera
24、tor方法 public Object next() if(hasNext() return equipment.elementAt(i+);else throw new NoSuchElementException(); 上面CompositeEquipment继承了Equipment,同时为自己里面的对象们提供了外部访问的方法,重载了Iterator,Iterator是Java的Collection的一个接口,是Iterator模式的实现.我们再看看CompositeEquipment的两个具体类:盘盒Chassis和箱子Cabinet,箱子里面可以放很多东西,如底板,电源盒,硬盘盒等;盘
25、盒里面可以放一些小设备,如硬盘 软驱等。无疑这两个都是属于组合体性质的。public class Chassis extends CompositeEquipment public Chassis(String name) super(name); public double netPrice() return 1.+Price(); public double discountPrice() return .5+super.discountPrice(); public class Cabinet extends CompositeEquipment public Cabinet(Strin
26、g name) super(name); public double netPrice() return 1.+Price(); public double discountPrice() return .5+super.discountPrice(); 至此我们完成了整个Composite模式的架构。我们可以看看客户端调用Composote代码:Cabinet cabinet=new Cabinet(Tower);Chassis chassis=new Chassis(PC Chassis);/将PC Chassis装到Tower中 (将盘盒装到箱子里)cabinet.add(chassis
27、);/将一个10GB的硬盘装到 PC Chassis (将硬盘装到盘盒里)chassis.add(new Disk(10 GB);/调用 netPrice()方法;System.out.println(netPrice=+Price();System.out.println(discountPrice=+cabinet.discountPrice();上面调用的方法netPrice()或discountPrice(),实际上Composite使用Iterator遍历了整个树形结构,寻找同样包含这个方法的对象并实现调用执行.Composite是个很巧妙体现智慧的模式,在实际应用中,如果碰到树形结
28、构,我们就可以尝试是否可以使用这个模式。以论坛为例,一个版(forum)中有很多帖子(message),这些帖子有原始贴,有对原始贴的回应贴,是个典型的树形结构,那么当然可以使用Composite模式,那么我们进入Jive中看看,是如何实现的.Jive解剖在Jive中 ForumThread是ForumMessages的容器container(组合体).也就是说,ForumThread类似我们上例中的 CompositeEquipment.它和messages的关系如图:thread |- message |- message |- message |- message |- message 我们在ForumThread看到如下代码:public interface ForumThread . public void addMessage(ForumMessage parentMessage, ForumMessage newMessage) throws UnauthorizedException; public void deleteMessage(ForumMessage message) throws UnauthorizedExceptio
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1