《软件设计模式之结构型模式.ppt》由会员分享,可在线阅读,更多相关《软件设计模式之结构型模式.ppt(37页珍藏版)》请在三一办公上搜索。
1、第三章,结构型模式,课程目标,结构型模式概述 Adapter模式 Bridge模式 Composite模式 Decorator模式 Faade模式 Flyweight模式 Proxy模式,体验项目,使用Composite模式来编写如图3-1所示的二叉树,然后使用深度优先搜索法遍历该二叉树,并打印出根节点的高度,运行效果如图3-2所示。,图3-1二叉树图,图3-2 二叉树遍历结果图,结构型模式概述,结构型模式是为解决怎样组装现有的类,设计他们的交互方式,从而达到实现一定的功能的目的。同时,结构型模式包容了对很多问题的解决,例如扩展性(外观模式,组成模式,代理模式,装饰模式),封装性(适配器模式,
2、桥接模式)。,结构型模式中解决了以下几个问题:,在不破坏类封装性的基础上,实现新的功能。这一点包括装饰模式,代理模式。,在不破坏类封装性的基础上,使得类可以同不曾估计到的系统进行交互。这一点包括桥接和适配器模式。,创建一组类的统一访问接口,这是组成模式。,对同一类创建不同的访问界面,提供给不同需要的访问者,这是外观模式。,Adapter模式,适配器模式有类适配器和对象匹配器两种形式。其中类适配器使用多继承(由于java不支持多继承,所以可以引入接口的概念)来实现一个接口对另一个接口的匹配,对象适配器主要依赖于对象组合来实现接口的匹配。比如java窗体事件处理的事件适配器就是一个很好的例子。,模
3、式介绍,主要适用于以下情况:,使用一个已经存在的类,而它的接口不符合你的需求。,创建一个可以复用的类,该类可以与其他不相关的类或不可预见的类(即那些接口可能不一定兼容的类)协同工作。,使用一些已经存在的子类,但是不可能对每一个都进行子类化以匹配它们的接口。对象适配器可以适配它的父类接口,仅适用于对象适配器。,Adapter模式结构图,适配器模式结构图如下:,类适配器结构图,对象适配器结构图,Target:定义Client使用的与特定应用或领域相关的接口。,Adaptee:定义一个已经存在的类,该类需要适配。,Adapter:对Adaptee类和Target接口进行适配。Client通过Adap
4、ter实例对象来调用某些方法,然后适配器调用Adaptee的方法来实现请求,适配器模式示例,比如我们编写过两个类,分别用于画圆形桩和方形桩,假设现在有一个应用,需要既画方形桩,又要画圆形桩,就可以使用该模式实现。,使用对象适配器 模式实现如下:,public class DrawRoundpublic void displayRound(String msg)System.out.println(DrawRound displayRound():+msg);public class DrawSquarepublic void displaySquare(String str)System.ou
5、t.println(DrawSquare displaySquare():+str);public class ShapeAdapter extends DrawSquareprivate DrawRound round;public ShapeAdapter(DrawRound r)this.round=r;public void insertRound(String str)round.displayRound(str);,使用类适配器 模式实现如下:,public interface DrawRoundInterfacepublic void displayRound(String ms
6、g);public class DrawRound implements DrawRoundInterface public void displayRound(String msg)System.out.println(DrawRound displayRound():+msg);public class ShapeAdapter extends DrawSquare implements DrawRoundInterfaceprivate DrawRound round;public ShapeAdapter(DrawRound r)this.round=r;public void dis
7、playRound(String msg)round.displayRound(msg);/doSomethingpublic class Client public static void main(String args)ShapeAdapter d=new ShapeAdapter(new DrawRound();d.insertRound(圆形);d.displaySquare(方形);,Adapter模式优势和不足,类适配器的优缺点如下:,用一个具体的Adapter类对Adaptee和Target进行匹配。结果是当我们想要匹配一个类以及所有它的子类时,类Adapter将不能胜任工作。
8、,使得Adapter可以重定义Adaptee的部分行为。,对象适配器的优缺点如下:,允许一个Adapter与多个Adaptee,即Adaptee本身以及它的所有子类(如果有子类的话)同时工作。,使得重定义Adaptee的行为比较困难。,仅仅引入了一个对象,并不需要额外的引用(指针)以间接得到Adaptee。,Bridge模式,在面向对象设计的基本概念中,对象这个概念实际上是由属性和行为两个部分组成的,属性我们可以认为是一种静止的,一种抽象的。一般情况下,行为是包含在一个对象中,但是在有些情况下,我们需要将这些行为也进行归类,形成一个总的行为接口,这就是桥接模式的用处。,模式介绍,主要适用于以下
9、情况:,不希望在抽象和它的实现部分之间有一个固定的绑定关系。,类的抽象以及它的实现都应该可以通过生成子类的方法加以扩充。,在多个对象间共享实现(可能使用引用计数),但同时要求客户并不知道这一点。,Bridge模式结构图,桥接模式结构图如下:,Abstraction:定义抽象类(接口),并维护一个Implementor类型对象。,RefinedAbstraction:抽象类的具体实现。,Implementor:实现层的抽象父类(接口),提供基本操作,以供抽象层次的类调用。,ConcreteImplementor:Implementor的具体实现。,Bridge模式示例,public abstra
10、ct class InforListInforlistFormat Format;public void setFormat(InforlistFormat Format)this.Format=Format;public InforlistFormat getFormat()return this.Format;public abstract void distributeInforList();public abstract class InforlistFormatpublic abstract void formatImpl();public class StudentInforLis
11、t extends InforListpublic void distributeInforList()System.out.println(这是学生信息单);InforlistFormat format=this.getFormat();format.formatImpl();public class TeacherInforList extends InforListpublic void distributeInforList()System.out.println(这是老师信息单);InforlistFormat format=this.getFormat();format.forma
12、tImpl();public class HtmlFormat extends InforlistFormatpublic void formatImpl()System.out.println(使用HTML格式生成);public class PlainTextFormat extends InforlistFormatpublic void formatImpl()System.out.println(使用纯文本格式生成);,Bridge模式优势和不足,不足:Bridge模式的应用一般用于“两个非常强的变化维度”,有时即使有两个变化的维度,但是某个方向的变化维度并不剧烈,换言之两个变化不会
13、导致纵横交错的结果,并没必要使用Bridge模式。,分离抽象部分及其实现部分。,提高可扩充性。可以独立的对抽象部分和实现部分进行扩充。,Bridge模式是比多继承方案更好的一种解决方法。,Bridge模式主要有以下一些优点:,向客户隐藏了实现部分,从而当需要扩展/更改实现部分时,不需要重新编译客户代码。,Composite模式,Composite模式即合成模式,将对象组织到树结构中,可以用来描述整体与部分的关系。合成模式可以使客户端将简单元素与复合元素同等看待。如文件夹与文件就是合成模式的典型应用。,模式介绍,主要适用于以下情况:,需要表示对象的部分和整体的层次结构。,希望用户忽略组合对象与单
14、个对象的区别,用户将统一使用组合结构中的所有对象。,Composite模式结构图,合成模式结构图如下:,Component:为组合中的对象声明接口,定义所有类共有接口的缺省行为。,Leaf:表示叶子节点,叶子节点没有子节点。,Composite:所有可以包含子节点的类都扩展这个类。这个类的主要功能是用来存储子部件,实现了接口中的方法。,Client:通过接口操纵组合部件的对象。,Composite模式示例,public abstract class Computer protected String name;public Computer(String name)this.name=name
15、;public abstract void getPart();import java.util.*;public class ComputerPart extends Computerprotected Vector part=new Vector();public ComputerPart(String name)super(name);public void getPart()System.out.println(name);System.out.println(name+中的部件:);for(int i=0;ipart.size();i+)Computer c=(Computer)pa
16、rt.get(i);c.getPart();public void add(Computer c)part.add(c);public void remove(Computer c)part.remove(c);public class ChildPart extends Computer public ChildPart(String name)super(name);public void getPart()System.out.println(name);,Composite模式优势和不足,Composite模式采用树形结构来实现普遍存在的对象容器,从而将“一对多”的关系转化为“一对一”
17、的关系,,将“客户代码与复杂的对象容器结构”解耦,解耦之后,客户端代码将与纯粹的抽象接口,而非对象容器的复内部实现结构,发生依赖关系,从而更能“应对变化”。,Composite模式中,是将“Add和Remove等和对象容器相关的方法”定义在“表示抽象对象的Component类”中,还是将其定义在“表示对象容器的Composite类”中,是一个关乎“透明性”和“安全性”的两难问题,需要仔细权衡。这里有可能违背面向对象的“单一职责原则”,但是对于这种特殊结构,这又是必须付出的代价。,Bridge模式优点和不足:,Composite模式在具体实现中,可以让父对象中的子对象反向追溯,Decorator
18、模式,Decorator模式即装饰模式,是指动态的给一个对象添加一些额外的职责,在Java 的IO操作中,经常会用到诸如如下的语句:,模式介绍,主要适用于以下情况:,在不影响其他对象的情况下,以动态、透明的方式给单个对象添加方法。或者处理那些可以撤消的方法。,当不能采用生成子类的方式进行扩充时。,BufferedReader br=new BufferedReader(new InputStreamReader(new FileInputStream(new File(D:a.txt);while(br.readLine()!=null)System.out.println(br.readLi
19、ne();,在该代码中使用多个的Decorator被层叠在一起,最后得到一个功能强大的流。既能够被缓冲,又能够得到行数,,Decorator模式结构图,装饰模式结构图如下:,Component:定义一个对象接口,以规范准备接收附加责任的对象。,ConcreteComponent:定义一个将要接收附加责任的类。,Decorator:持有一个组件对象的实例,并定义一个与抽象组件接口一致的接口。,ConcreteDecorator:负责给组件对象“贴上”附加的责任。,Decorator模式示例,public interface Phone public void use();public class
20、 HomePhone implements Phonepublic void use()System.out.println(打电话、接电话);public class Decorator implements PhonePhone phone;public Decorator(Phone phone)this.phone=phone;public void use()phone.use();public class AutoDecorator extends Decorator public AutoDecorator(Phone phone)super(phone);public void
21、 use()phone.use();System.out.println(装配自动回复功能);public class WatchDecorator extends Decorator public WatchDecorator(Phone phone)super(phone);public void use()phone.use();System.out.println(装配可视功能);public class Client public static void main(String args)Phone p=new HomePhone();p.use();/添加自动回复功能Phone p
22、1=new Decorator(new AutoDecorator(p);p1.use();/添加自动回复功能和可视功能Phone p2=new Decorator(new WatchDecorator(new AutoDecorator(p);p2.use();,Decorator模式优势和不足,Decorator模式主要有以下几点优势:,比静态继承更灵活。,避免了在层次结构中高层的类有太多的特性。Decorator模式提供了一种“即用即付”的方法来添加职责。,Decorator模式的不足之处主要在于有太多的小对象。采用Decorator模式进行设计往往会产生许多看上去类似的小对象,这些对象
23、仅仅在它们相互连接的方式上有所不同,所以在排错时会很困难。,Decorator模式不足,Facade模式,Facade模式(外观模式)的意图是:为子系统中的一组接口提供一致的界面,Facade模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。,模式介绍,主要适用于以下情况:,当要为一个复杂子系统提供一个简单接口时。,客户程序与抽象类的实现部分之间存在着很大的依赖性。,当需要构建一个层次结构的子系统时,使用Facade模式定义子系统中每层的入口点。,Facade模式结构图,外观模式结构图如下:,Facade:知道哪些子系统类负责处理请求,将客户的请求代理给适当的子系统对象。,子系统类(
24、Subsystem classes):实现子系统的功能,处理由Facade对象指派的任务。,Facade模式示例,import java.sql.*;public class Client public static void main(String args)DBConnection b=new DBConnection();b.setDriver(com.microsoft.jdbc.sqlserver.SQLServerDriver);b.setServername(lacalhost);b.setDBname(pubs);tryConnection c=b.connect();Resu
25、ltSet rs=c.createStatement().executeQuery(select*from sale);while(rs.next()System.out.println(rs.getString(1);catch(Exception e)System.out.println(e);class DBConnection String driver,servername,dbname;public void setDriver(String driver)this.driver=driver;public void setServername(String servername)
26、this.servername=servername;public void setDBname(String dbname)this.dbname=dbname;public Connection connect()try Class.forName(driver);Connection cn=DriverManager.getConnection(jdbc:microsoft:sqlserver:/“+servername+:1433;databasename=+dbname,sa,);System.out.println(信息提示:连接+servername+服务器+dbname+数据库
27、已成功!);return cn;catch(Exception e)System.out.println(信息提示:连接+servername+服务器+dbname+失败!n+e);return null;,Facade模式优势和不足,Facade模式主要有以下几点优势:,对客户屏蔽子系统组件,因而减少了客户处理的对象的数目,使得子系统使用起来更加方便。,实现了子系统与客户间的松耦合关系。松耦合关系使得子系统的组件变化不会影响到客户端。,Facade模式不足,Facade模式的缺点主要在于使用Facade模式时,要定义interface是很麻烦的一件事情,特别是在内部类所能提供的方法还没确定或
28、外部所需功能还没确定的时候尤为如此。,Flyweight模式,Flyweight模式即享元模式,该模式的意图是避免大量拥有相同内容的小类的开销(如耗费内存),使大家共享一个类(元类)。享元模式以共享的方式高效的支持大量的细粒度对象。享元模式能做到共享的关键是区分内部状态和外部状态。Flyweight模式是一个提高程序效率和性能的模式,会大大加快程序的运行速度。应用场合很多,比如你要从一个数据库中读取一系列字符串,这些字符串中有许多是重复的,那么我们可以将这些字符串储存在Flyweight池(pool)中。,模式介绍,当以下情况都成立时使用Flyweight模式:,一个应用程序使用了大量的对象。
29、,由于使用了大量的对象,造成很大的开销。,如果删除对象的外部状态,就可以使用相对较少的共享对象来取代很多组对象。,应用程序不依赖于对象标识。,Flyweight模式结构图,享元模式结构图如下:,Flyweight:描述一个接口,通过这个接口Flyweight示例对象可接受并作用于外部状态。,UnsharedConcreteFlyweight:并非所有的Flyweight子类都需要被共享,UnsharedConcreteFlyweight对象通常将ConcreteFlyweight对象作为子节点。,FlyweightFactory:创建并管理Flyweight对象,确保合理的共享Flyweigh
30、t。,ConcreteFlyweight:实现Flyweight接口,并为内部状态添加存储空间。,Flyweight模式示例,public interface Flyweightpublic abstract void operation();public class ConcreteFlyweight implements Flyweightprivate String string;public ConcreteFlyweight(String str)string=str;public void operation()System.out.println(Concrete-Flyweig
31、ht:+string);import java.util.Hashtable;public class FlyweightFactoryprivate Hashtable flyweights=new Hashtable();public Flyweight getFlyWeight(Object obj)Flyweight flyweight=(Flyweight)flyweights.get(obj);if(flyweight=null)/产生新的ConcreteFlyweightflyweight=new ConcreteFlyweight(obj.toString();flyweigh
32、ts.put(obj,flyweight);return flyweight;public int getFlyweightSize()return flyweights.size();,FlyweightFactory对象提供了一个已创建的实例,如果该实例没有,FlyweightFactory对象就创建一个。,Flyweight模式优势和不足,Flyweight模式优势:,Flyweight模式不足:,Flyweight模式主要是对存储的节约,共享的Flyweight越多,存储节约也就越多,节约量随着共享状态的增多而增大。可以使用两种方法来节约存储,即使用共享来减少内部状态的消耗和用计算时间
33、换取对外部状态的存储。,使用该模式时,传输、查找和计算外部状态都会产生运行时的开销,尤其当Flyweight对象原先被存储为内部状态时,开销会更大。,Proxy模式,Proxy 模式中要创建“stub”或“surrogate”对象,它们的目的是接受请求并把请求转发到实际执行工作的其他对象。比如远程方法调用(RMI)利用Proxy模式,使得在其他JVM中执行的对象就像本地对象一样;Proxy模式在实际中经常应用,比如Windows系统提供的快捷方法。,模式介绍,该模式主要有以下几种情况:,远程代理(Remote Proxy):在不同的地址空间中提供局部代表。,虚代理(Virtual Proxy)
34、:根据需要创建开销很大的对象。,智能指引(Smart Reference):取代简单指针。,保护代理(Protection Proxy):控制对原始对象的访问。,Proxy模式结构图,代理模式结构图如下:,Subject:定义RealSubject和Proxy的共用接口,这样就在任何使用RealSubject的地方都可以使用Proxy。,RealSubject:定义Proxy所代表的实体。,Proxy:保存一个引用使得代理可以访问实体。控制对实体的存取,并可能负责创建和删除它,其他功能依赖于代理的类型。,Proxy模式示例,abstract interface Subjectabstract
35、public void request();class RealSubject implements Subjectpublic void request()System.out.println(Hello World!);class ProxySubject implements Subject/以真实角色作为代理角色的属性private RealSubject realSubject;public void request()preRequest();if(realSubject=null)realSubject=new RealSubject();realSubject.request(
36、);/此处执行真实对象的request()方法postRequest();private void preRequest()System.out.println(代理角色即将调用真实对象的request()方法);private void postRequest()System.out.println(调用真实对象的request()方法结束);,客户段可通过如下的代码访问真实对象的方法:Subject sub=new ProxySubject();sub.request();,java动态代理类,Static Class getProxyClass(ClassLoader loader,Cl
37、ass interfaces):获得一个代理类,其中loader是类装载器,interfaces是真实类所拥有的全部接口的数组。,java.lang.reflect类库中提供三个类直接支持代理模式:Proxy,InvocationHandler和Method。,Proxy类:该类即为动态代理类。主要有如下主要方法:,Protected Proxy(InvocationHandler h):构造函数,用于给内部的h赋值。,Static Object newProxyInstance(ClassLoader loader,Class interfaces,InvocationHandler h):
38、返回代理类的一个实例。,InvocationHandler接口:该接口中仅定义了一个方法Object invoke(Object obj,Method method,Object args)。在实际使用时,第一个参数obj一般是指代理类,method是被代理的方法,,import java.lang.reflect.Method;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Proxy;import java.lang.reflect.Constructor;class ProxySubject impl
39、ements InvocationHandler private Object sub;/内部属性为Object类 public ProxySubject(Object obj)sub=obj;public Object invoke(Object proxy,Method method,Object args)throws Throwable System.out.println(before calling+method);method.invoke(sub,args);System.out.println(after calling+method);return null;public
40、class Clientstatic public void main(String args)throws ThrowableRealSubject rs=new RealSubject();/在这里指定真实角色InvocationHandler dps=new ProxySubject(rs);/初始化代理类Class c=rs.getClass();Subject subject=(Subject)Proxy.newProxyInstance(c.getClassLoader(),c.getInterfaces(),dps);subject.request();,Proxy模式优势和不足
41、,根据代理类型的不同,代理模式主要有以下一些用途和优点:,代理模式不足:,在使用代理模式时,因为不能保证特定的应用程序(真实对象)对象被创建,在访问这个对象的任何地方,都需要检测确认它不是空(null)。也就是,这种检测的时间消耗是最大的缺点。,虚代理可以进行最优化,比如根据要求来创建对象。,保护代理和智能指引都允许在访问一个对象时有一些附加的内务处理。,远程代理可以隐藏一个对象存在于不同地址空间的事实。,实践项目,程序的实现要求如下:(1)创建抽象构件、树叶构件、树枝构件。(2)遍历该二叉树时,我们先打印树或叶子的名字,然后遍历左孩子,再遍历右孩子;如果左孩子或右孩子是树,重复前面的步骤.(3)计算并打印出该二叉树的高度。,本章总结,结构型模式概述 Adapter模式 Bridge模式 Composite模式 Decorator模式 Faade模式 Flyweight模式 Proxy模式,