面向对象中通常将可以重复使用的工具类中的行为组织在一起形成最小的类。但是随着包的复用性使得子系统中类的多样性导致选择太多,这时可以使用外观(Facade)模式。一个个外观就是一个类,它包含的功能介于工具包与应用程序,它为子系统提供了一个接口,便于子系统使用它。它为子系统中的一组接口提供一个统一的高层接口。这一接口使得子系统更加容易使用。
-
Facade:这个外观类为子系统中Packages 1、2、3提供一个共同的对外接口。
Clients:客户对象通过一个外观接口读写子系统中各接口的数据资源。
Packages:客户可以通过外观接口读取的内部库。
/* Complex parts */
class CPU{
public void freeze() { ... }
public void jump(long position) { ... }
public void execute() { ... }
}
class Memory{
public void load(long position, byte[] data) { ... }
}
class HardDrive {
public byte[] read(long lba, int size) { ...}
}
/* Façade */
class Computer {
public void startComputer() {
cpu.freeze();
memory.load(BOOT_ADDRESS, hardDrive.read(BOOT_SECTOR, SECTOR_SIZE));
cpu.jump(BOOT_ADDRESS);
cpu.execute();
}
}
/* Client */
class You {
public static void main(String[] args) {
Computer facade = new Computer();
facade.startComputer();
}
}
-
下面这个例子中,用来显示函数的轨迹,对于客户,只需要构造一个PlotPanel,然后将其加入frame中即可。而UI类就是一个外观类,它为客户提供了通过PlotPanel创建一个新的Panel的接口(这个新的panel不仅显示PlotPanel的内容,还有Border等)。
package mytest.function;
public abstract class Function {
public abstract double f(double t);
}
package mytest.function;
public class T extends Function{
@Override
public double f(double t) {
return t;
}
}
-
这是包function中的函数接口。
package mytest.ui;
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JPanel;
import mytest.function.Function;
public class PlotPanel extends JPanel{
private int count; //点的个数
private int[] xpoints;
private int[] ypoints;
private Function xf; //用来计算坐标位置的函数
private Function yf;
public PlotPanel(int count,Function xf,Function yf){
this.count=count;
this.xf=xf;
this.yf=yf;
xpoints=new int[count];
ypoints=new int[count];
setBackground(Color.white);
}
@Override
protected void paintComponent(Graphics g){
double w=getWidth()-1;
double h=getHeight()-1;
for(int i=0;i<count;i++){
double t=((double)i)/(count-1);
xpoints[i]=(int)(xf.f(t)*w);
ypoints[i]=(int)(h*(1-yf.f(t)));
}
g.drawPolyline(xpoints,ypoints,count);
}
}
-
接下来是通过PlotPanel创建新的Panel:
package mytest.ui;
import java.awt.Color;
import java.awt.Font;
import javax.swing.BorderFactory;
import javax.swing.JPanel;
import javax.swing.border.BevelBorder;
import javax.swing.border.TitledBorder;
public class UI {
public static final UI NORMAL=new UI();
protected Font font=new Font("Book Antiqua",Font.PLAIN,18);
public Font getFont(){
return font;
}
public TitledBorder createTitledBorder(String title){
TitledBorder border=BorderFactory.createTitledBorder(
BorderFactory.createBevelBorder(BevelBorder.RAISED),
title,TitledBorder.LEFT,TitledBorder.TOP);
border.setTitleColor(Color.black);
border.setTitleFont(getFont());
return border;
}
public JPanel createrTitledPanel(String title,JPanel in){
JPanel out=new JPanel();
out.add(in);
out.setBorder(createTitledBorder(title));
return out;
}
}
-
最后是客户使用UI类:
package mytest.test;
import java.awt.Dimension;
import javax.swing.JFrame;
import mytest.function.Function;
import mytest.function.T;
import mytest.ui.PlotPanel;
import mytest.ui.UI;
public class Show {
public static void main(String[] args){
PlotPanel p=new PlotPanel(101,new T(),new Show().new YFunction());
p.setPreferredSize(new Dimension(300,200));
JFrame frame=new JFrame("show a path");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(UI.NORMAL.createrTitledPanel("Flight",p));
frame.pack();
frame.setVisible(true);
}
private class YFunction extends Function{
@Override
public double f(double t) {
return 4*t*(1-t);
}
}
}
-
结果:
![](http://dl.iteye.com/upload/attachment/0083/8496/112c833e-9591-33c4-b0a0-b629440ee436.png)