在设计模式中,有一类设计模式是比较有意思的,但是关注的人不多。这就是结构模式。如果说创建模式的重点是如何创建出实例对象,那么结构模式的特点就是利用类、示例构建更大的结构体。这听上去有点抽象,大家可以在实际开发中慢慢体会。这里面,最能体会这个观点的就是组合模式。组合模式类似于二叉树,二叉树的构成是树叶,树叶可以构建成树干,这样通过层层迭代,就可以进化成一个参天大树。
常见的结构模式有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、其他
乱七八糟说了这么多,关键还是要用编程语言实现一把。不去实际操作一样,往往理解的不深刻。有的时候甚至要多次学习才能有一点收获,设计模式就是这样学习的。