1. 意图(Intent)

提供了一个统一的接口,用来访问子系统中的一群接口,从而让子系统更容易使用。

2. 类图(Class Diagram)

f9978fa6-9f49-4a0f-8540-02d269ac448f.png

3. 实现(Implementation)

I 画图案例

首先,我们定义一个接口:

  1. public interface Shape {
  2. void draw();
  3. }

定义几个实现类:

圆形类

  1. public class Circle implements Shape {
  2. @Override
  3. public void draw() {
  4. System.out.println("Circle::draw()");
  5. }
  6. }

长方形类

  1. public class Rectangle implements Shape {
  2. @Override
  3. public void draw() {
  4. System.out.println("Rectangle::draw()");
  5. }
  6. }

客户端调用:

  1. public class Client {
  2. public static void main(String[] args) {
  3. // 画一个圆形
  4. Shape circle = new Circle();
  5. circle.draw();
  6. // 画一个长方形
  7. Shape rectangle = new Rectangle();
  8. rectangle.draw();
  9. }
  10. }

以上是我们常写的代码,我们需要画圆就要先实例化圆,画长方形就需要先实例化一个长方形,然后再调用相应的 draw() 方法。
下面,我们看看怎么用门面模式来让客户端调用更加友好一些。
我们先定义一个门面:

  1. public class ShapeMakerFacade {
  2. private Shape circle;
  3. private Shape rectangle;
  4. private Shape square;
  5. public ShapeMaker() {
  6. circle = new Circle();
  7. rectangle = new Rectangle();
  8. square = new Square();
  9. }
  10. //下面定义一堆方法,具体应该调用什么方法,由这个门面来决定
  11. public void drawCircle(){
  12. circle.draw();
  13. }
  14. public void drawRectangle(){
  15. rectangle.draw();
  16. }
  17. public void drawSquare(){
  18. square.draw();
  19. }
  20. }

看看现在客户端怎么调用:

  1. public class Client {
  2. public static void main(String[] args) {
  3. ShapeMakerFacade shapeMaker = new ShapeMakerFacade();
  4. // 客户端调用现在更加清晰了
  5. shapeMaker.drawCircle();
  6. shapeMaker.drawRectangle();
  7. shapeMaker.drawSquare();
  8. }
  9. }

门面模式的优点显而易见,客户端不再需要关注实例化时应该使用哪个实现类,直接调用门面提供的方法就可以了,因为门面类提供的方法的方法名对于客户端来说已经很友好了。

II 看电影案例

观看电影需要操作很多电器,使用外观模式实现一键看电影功能。

public class SubSystem {
    public void turnOnTV() {
        System.out.println("turnOnTV()");
    }

    public void setCD(String cd) {
        System.out.println("setCD( " + cd + " )");
    }

    public void startWatching(){
        System.out.println("startWatching()");
    }
}
public class Facade {
    private SubSystem subSystem = new SubSystem();
    //门面帮你制定好操作,用户傻瓜式启动即可
    public void watchMovie() {
        subSystem.turnOnTV();
        subSystem.setCD("a movie");
        subSystem.startWatching();
    }
}
public class Client {
    public static void main(String[] args) {
        Facade facade = new Facade();
        facade.watchMovie();
    }
}

4. 设计原则

最少知识原则:只和你的密友谈话。也就是说客户对象所需要交互的对象应当尽可能少。