上次讲了设计模式中的建造型模式,此次来谈谈结构型模式。其实结构型模式与建造型模式有很大的类似之处,有时都是为了返回一个新构造的对象,而结构型模式的重点在于基于已有的类的组合来构造符合特定要求的新类。下面基于源码分析一下几种常见的结构型模式。设计模式
首先说桥接模式,结构型模式中最重要的模式,用于把抽象化与实现化解耦,使得两者能够独立变化,更通俗准确地说就是分别定义高层的接口和具体的实现,使得具体实现修改了,高层接口能够不变。桥接模式与其余不少设计模式有着类似之处,我一开始看了一些桥接模式的源码后感受它与工厂模式没有什么区别。其实,桥接模式的思想是纯粹的抽象与实现的分离,其余不少模式中都蕴含着这样的思想,因此存在一些类似性,而桥接模式是当中最标准的抽象、实现解耦模式。好比要说工厂模式与桥接模式有什么区别,实质上区别仍是很大的,工厂模式的目的在于建立对象时使用统一的接口而不暴露建立逻辑,而桥接模式的目的如上所说,对不一样的实现方式用统一的接口进行操做,可见工厂模式能够看做桥接模式在建立对象时的特例。服务器
如下是桥接模式的通常性源码:ide
public abstract class Implementor{ 2: public abstract void OperationImp(); 3: } 4: 5: public class ConcreteImplementorA extends Implementor{ 6: public void OperationImp(){ 7: //省略实现... 8: } 9: } 10: 11: public class ConcreteImplementorB extends Implementor{ 12: public void OperationImp(){ 13: //省略实现... 14: } 15: } 16: public abstract class Abstraction{ 17: protected Implementor implementor; 18: public abstract void Operation(); 19: } 20: 21: public class RefinedAbstraction extends Abstraction{ 22: public RefinedAbstraction(Implementor implementor){ 23: this.implementor=implementor; 24: } 25: 26: public void Operation(){ 27: //... 28: implementor.OperationImp();//调用实现化角色实现的操做 29: //... 30: } 31: } 32: 33: public class Client{ 34: public static void main(String[] args){ 35: Abstraction abstraction=new RefinedAbstraction(new ConcreteImplementorA()); 36: abstraction.Operation(); 37: } 38: }
这就很好地说明了桥接模式的内涵,也给出了桥接模式的使用方式。把上述代码中的 Abstraction 和 Implementor 看做操做系统与不一样的硬件设备,操做系统为用户提供了 read 、 write 这样的文件操做方式,而这些函数内部封装了不一样硬件设备的不一样驱动函数,这就是桥接模式的典型例子。函数
接着说适配器模式。相对于桥接模式,适配器模式更好理解,它是两个不兼容的接口之间的桥梁,使得本来因为接口不兼容而不能一块儿工做的那些类能够一块儿工做。这样对用户来讲,能够用统一的方式调用本来不兼容的类。举个例子,AudioPlayer 能够播放 mp3 格式的音频文件,AdvancedMediaPlayer 能够播放 vlc 和 mp4 格式的文件,咱们想要让 AudioPlayer 播放其余格式的音频文件。实现方式:源码分析
public class MediaAdapter implements MediaPlayer { AdvancedMediaPlayer advancedMusicPlayer; public MediaAdapter(String audioType){ if(audioType.equalsIgnoreCase("vlc") ){ advancedMusicPlayer = new VlcPlayer(); } else if (audioType.equalsIgnoreCase("mp4")){ advancedMusicPlayer = new Mp4Player(); } } @Override public void play(String audioType, String fileName) { if(audioType.equalsIgnoreCase("vlc")){ advancedMusicPlayer.playVlc(fileName); }else if(audioType.equalsIgnoreCase("mp4")){ advancedMusicPlayer.playMp4(fileName); } } }
public class AudioPlayer implements MediaPlayer { MediaAdapter mediaAdapter; @Override public void play(String audioType, String fileName) {
if(audioType.equalsIgnoreCase("mp3")){ System.out.println("Playing mp3 file. Name: "+ fileName); }
else if(audioType.equalsIgnoreCase("vlc") || audioType.equalsIgnoreCase("mp4")){ mediaAdapter = new MediaAdapter(audioType); mediaAdapter.play(audioType, fileName); } else{ System.out.println("Invalid media. "+ audioType + " format not supported"); } } }
这样就把两种接口不相同的类用统一的方式封装,对用户来讲几个功能均可以用相同的方式调用。适配器模式也体现出结构型模式的特色,即把几种不一样的类用特定方式组合到一块儿,造成符合需求的新类。this
再来讲说装饰器模式,其目的是在不改变类的结构的状况下,向其动态地添加新的功能。一般咱们要扩展一个类会使用继承方式,而因为继承为类引入静态特征,而且随着扩展功能的增多,子类会很膨胀,这时能够考虑装饰器模式。该模式实现方式是新建一个装饰类(虚类)并添加被装饰的类做为成员,继承该类并重写相关功能函数,添加新的功能。以上一篇博客中的 Shape 形状类为例(相关源码见上一篇博客),咱们将把一个形状装饰上不一样的颜色,同时又不改变形状类。spa
public abstract class ShapeDecorator implements Shape { protected Shape decoratedShape; public ShapeDecorator(Shape decoratedShape){ this.decoratedShape = decoratedShape; } public void draw(){ decoratedShape.draw(); } }
public class RedShapeDecorator extends ShapeDecorator { public RedShapeDecorator(Shape decoratedShape) { super(decoratedShape); } @Override public void draw() { decoratedShape.draw(); setRedBorder(decoratedShape); } private void setRedBorder(Shape decoratedShape){ System.out.println("Border Color: Red"); } }
这样就在形状类的基础上添加了颜色功能。操作系统
最后说说外观模式,这种模式很是简单却十分经常使用,即向客户端提供了一个客户端能够访问系统的接口,而隐藏了系统的复杂性。简单来讲就是用户能够简洁地调用接口中的功能,而不关注具体实现细节。服务器与客户端之间的通讯就采用这种模式。依然以 Shape 类为例,但愿统一调用不一样形状的 draw 函数。设计
public class ShapeMaker { private Shape circle; private Shape rectangle; private Shape square; public ShapeMaker() { circle = new Circle(); rectangle = new Rectangle(); square = new Square(); } public void drawCircle(){ circle.draw(); } public void drawRectangle(){ rectangle.draw(); } public void drawSquare(){ square.draw(); } }
public class FacadePatternDemo { public static void main(String[] args) { ShapeMaker shapeMaker = new ShapeMaker(); shapeMaker.drawCircle(); shapeMaker.drawRectangle(); shapeMaker.drawSquare(); } }
就是这么简单的方式。其与工厂模式的区别在于,工厂模式的目的在于建立,而外观模式的目的在于使用调用功能。代理
还有一些其余的结构型模式,好比组合模式用树形结构表示一组类似对象的层次,过滤器模式用特定要求来过滤一组对象,享元模式用于共享相同的对象来节省资源,代理模式用一个类表明另外一个类的功能来避免直接访问。细节详见相关资料,此次就很少说了,下次再来说讲行为型设计模式。