【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】
在设计模式中,有一类设计模式是比较有意思的,但是关注的人不多。这就是结构模式。如果说创建模式的重点是如何创建出实例对象,那么结构模式的特点就是利用类、示例构建更大的结构体。这听上去有点抽象,大家可以在实际开发中慢慢体会。这里面,最能体会这个观点的就是组合模式。组合模式类似于二叉树,二叉树的构成是树叶,树叶可以构建成树干,这样通过层层迭代,就可以进化成一个参天大树。
常见的结构模式有7种,分别是代理模式、适配器模式、组合模式、外观模式、装饰器模式、享元模式和桥接模式。
1、代理模式
代理模式比较简单,现实中也有这样的案例。比如开一个建筑公司来承揽工程,但是在这个领域开设公司是需要相关资质的。这个时候就有两种办法,一种办法就是公司自己去努力申请相关资质;另外一种就是公司将自己挂靠在某些有资质的公司上面,遇到不需要资质的项目就自己去独立完成,遇到有资质要求的工程,那只好转包给有资质条件的公司了。如果画一下图,可以这么来表示,

将上述图形转成java代码,应该是这样的,
- import java.io.*;
-
- class Work
- {
- public void process()
- {
- return;
- }
- }
-
- class RealWork extends Work
- {
- @Override
- public void process()
- {
- System.out.println("RealWork");
- }
- }
-
- class ProxyWork extends Work
- {
- private Work s;
-
- public ProxyWork(Work w)
- {
- s = w;
- }
-
- @Override
- public void process()
- {
- if(null != s)
- {
- s.process();
- }
-
- System.out.println("ProxyWork");
- }
- }
-
- public class proxy
- {
- public static void main(String args[])
- {
- Work r = new RealWork();
- Work p = new ProxyWork(r);
-
- p.process();
- }
- }
2、适配器模式
适配器模式,大家可以和代理模式比较着来学习。在代理模式中,代理提供的接口和原来是一样的。而在适配器模式中,适配器的接口和原来是不一样的。同样以大家都熟悉的视频接口来说,一种老式的显示器接口是vga,这是很老的接口。但是现在笔记本电脑普遍都是usb接口、hdmi接口,所以这个时候如果需要把笔记本适配到老式的显示器上,只能借助于一个转换接口才能完美兼容老式的显示器。用一个类图可以这么来表示,

将上述图形适当修改后,转成java代码,是这样的,
- import java.io.*;
-
- class vga
- {
- public void process()
- {
- System.out.println("vga interface");
- }
- }
-
- class hdmi2vga
- {
- public void work()
- {
- System.out.println("hdmi2vga");
- }
- }
-
- class hdmi extends vga
- {
- private hdmi2vga h;
-
- public hdmi()
- {
- h = new hdmi2vga();
- }
-
- @Override
- public void process()
- {
- System.out.println("hdmi interface");
- h.work();
- }
- }
-
- class minihdmi2vga
- {
- public void work()
- {
- System.out.println("minihdmi2vga");
- }
- }
-
- class minihdmi extends vga
- {
- private minihdmi2vga m;
-
- public minihdmi()
- {
- m = new minihdmi2vga();
- }
-
- @Override
- public void process()
- {
- System.out.println("minihdmi interface");
- m.work();
- }
- }
-
- public class adp
- {
- public static void main(String[] args)
- {
- vga h = new hdmi();
- h.process();
-
- vga m = new minihdmi();
- m.process();
- }
- }
-
-
3、组合模式
学习过数据结构的同学都知道二叉树。二叉树就是依靠一个又一个的节点搭建起来的。因此,学习过程中,完全可以用二叉树的思路来学习组合模式。类可以分成两种,一种是类似于叶子的子类,一种是需要子类构建的复合类,有点类似于树干,这样有了叶子和主干,就可以构建更大的类了。这听上去有点玄乎,实际上大家看一下类图,就不复杂了,

上述图形转换成java代码后,是这样的,
- import java.io.*;
-
- class Node
- {
- public void display()
- {
- System.out.println("Node display");
- }
- }
-
- class Leaf extends Node
- {
- int num;
-
- public Leaf(int i)
- {
- num = i;
- }
-
- @Override
- public void display()
- {
- System.out.println("Leaf " + num + " display");
- }
- }
-
- class Trunk extends Node
- {
- private Node[] group = new Node[2];
-
- public Trunk(Node n1, Node n2)
- {
- group[0] = n1;
- group[1] = n2;
- }
-
- @Override
- public void display()
- {
- int i;
- for(i = 0; i < 2; i++)
- {
- group[i].display();
- }
- }
- }
-
- public class composite
- {
- public static void main(String[] args)
- {
- Node n1 = new Leaf(1);
-
- Node n2 = new Leaf(2);
- Node n3 = new Leaf(3);
- Node n4 = new Trunk(n2, n3);
-
- Node n5 = new Trunk(n1, n4);
- n5.display();
- }
- }
4、外观模式
外观模式有点类似于现在各个城市比较盛行的一站式窗口。之前去注册公司,可能需要分别去工商局、税务局、银行等机构逐一登记、申请。现在有了一站式中心后,这些都不要,我们所需要的就是提交材料,一站式中心对应的窗口会帮我们完成剩下来的所有工作。翻译成图形,就是这样的,

上述图形转成java代码,是这样的,
- import java.io.*;
-
- class Shape
- {
- public void draw()
- {
- return;
- }
- }
-
- class Circle extends Shape
- {
- @Override
- public void draw()
- {
- System.out.println("Circle draw");
- }
- }
-
- class Rectangle extends Shape
- {
- @Override
- public void draw()
- {
- System.out.println("Rectangle draw");
- }
- }
-
- class Eclipse extends Shape
- {
- @Override
- public void draw()
- {
- System.out.println("Eclipse draw");
- }
- }
-
- public class shapeMaker
- {
- private Shape shapeCircle;
- private Shape shapeRect;
- private Shape shapeEclipse;
-
- public shapeMaker()
- {
- shapeCircle = new Circle();
- shapeRect = new Rectangle();
- shapeEclipse = new Eclipse();
- }
-
- public void drawCircle()
- {
- shapeCircle.draw();
- }
-
- public void drawRect()
- {
- shapeRect.draw();
- }
-
- public void drawEclipse()
- {
- shapeEclipse.draw();
- }
-
- public static void main(String[] args)
- {
- shapeMaker s = new shapeMaker();
- s.drawCircle();
- s.drawRect();
- s.drawEclipse();
- }
- }
5、装饰器模式
装饰器模式,主要就是希望在不改变现有接口的功能情况下,扩展出一些新的功能。比如说,我们设计一个绘图软件,之前可能只是绘制正方形、圆形接口。但是客户觉得太单调了,有要求,绘制有颜色的图形,比如说绿色的正方形、红色的圆形等等。因此,就应运而生了装饰器模式,

上述图形,转成java代码后,是这样的,
-
- import java.io.*;
-
- class Shape
- {
- public void draw()
- {
- return;
- }
- }
-
- class Circle extends Shape
- {
- @Override
- public void draw()
- {
- System.out.println("Circle draw");
- }
- }
-
- class Rectangle extends Shape
- {
- @Override
- public void draw()
- {
- System.out.println("Rectangle draw");
- }
- }
-
- class Decorator extends Shape
- {
- private Shape shape;
-
- public Decorator(Shape s)
- {
- this.shape = s;
- }
-
- @Override
- public void draw()
- {
- shape.draw();
- }
- }
-
- class Decorator1 extends Decorator
- {
- public Decorator1(Shape s)
- {
- super(s);
- }
-
- @Override
- public void draw()
- {
- super.draw();
- System.out.println("Decorator1 draw");
- }
- }
-
- class Decorator2 extends Decorator
- {
- public Decorator2(Shape s)
- {
- super(s);
- }
-
- @Override
- public void draw()
- {
- super.draw();
- System.out.println("Decorator2 draw");
- }
- }
-
- public class DecoratorDemo
- {
- public static void main(String[] args)
- {
- Shape d1 = new Decorator1(new Circle());
- d1.draw();
-
- Shape d2 = new Decorator2(new Rectangle());
- d2.draw();
- }
- }
6、享元模式
这个中文翻译一直有点怪,其实英文叫flyweight,如果方便自己理解,也可以理解成lightweight。就是在有些场合,比如游戏界面,软件可能需要绘制很多很多的图像,这个时候就有可能需要实例化很多对象。但是,在这过程中不见得真的需要实例化每一种对象。此时,就可以本着用一种、注册一种的思路来解决这个问题。如果变成类图,就是这样的,

上述图形,转成代码后,是这样的,
- import java.io.*;
-
- class shape
- {
- public void draw()
- {
- return;
- }
- }
-
- class circle extends shape
- {
- @Override
- public void draw()
- {
- System.out.println("circle draw");
- }
- }
-
- class shapeFactory
- {
- private shape[] group = {null, null, null, null, null};
-
- public shapeFactory()
- {
- return;
- }
-
- public void draw(int i)
- {
- if(i < 0 || i >= 5)
- {
- return;
- }
-
- if(group[i] == null)
- {
- group[i] = new circle();
- System.out.println("create circle " + i);
- }
-
- group[i].draw();
- System.out.println("finish draw " + i + "\n");
- }
- }
-
- public class flyweight
- {
- public static void main(String[] args)
- {
- shapeFactory s = new shapeFactory();
- s.draw(1);
-
- s.draw(4);
- s.draw(4);
- }
- }
7、桥接模式
之前装饰器模式,解决的是在不改变原有接口的基础上增加新功能的问题。而桥接模式,解决的是抽象和实现相分离的问题。比如不同的车有不同的功率,不同的男女有不同的职业,不同的户型有不同的面积,这里面就是一个m*n的关系。这个时候,用桥接模式就是比较适合的,因为两者的接口是完全分离开来的,

上述图形转成java代码后,是这样的,
- import java.io.*;
-
- interface drawAPI
- {
- public void draw_circle(int x, int y, int radius);
- }
-
- class drawRedAPI implements drawAPI
- {
- @Override
- public void draw_circle(int x, int y, int radius)
- {
- System.out.println("draw red circle, " + "x = " + x + ", y = " + y);
- }
- }
-
- class drawGreenAPI implements drawAPI
- {
- @Override
- public void draw_circle(int x, int y, int radius)
- {
- System.out.println("draw green circle, " + "x = " + x + ", y = " + y);
- }
- }
-
- class shape
- {
- protected drawAPI d;
-
- public shape(drawAPI d)
- {
- this.d = d;
- }
-
- public void draw()
- {
- return;
- }
- }
-
- class circle extends shape
- {
- private int radius;
- private int x;
- private int y;
-
- public circle(int x, int y, int radius, drawAPI d)
- {
- super(d);
-
- this.x = x;
- this.y = y;
- this.radius = radius;
- }
-
- @Override
- public void draw()
- {
- d.draw_circle(x,y,radius);
- }
- }
-
- public class bridge
- {
- public static void main(String[] args)
- {
- shape s1 = new circle(1, 1, 2, new drawRedAPI());
- s1.draw();
-
- shape s2 = new circle(2, 3, 5, new drawGreenAPI());
- s2.draw();
- }
- }
8、其他
乱七八糟说了这么多,关键还是要用编程语言实现一把。不去实际操作一样,往往理解的不深刻。有的时候甚至要多次学习才能有一点收获,设计模式就是这样学习的。