- 外观模式(Facade Pattern)
为子系统中的一组接口提供一个一致的界面,外观模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。
将一个系统划分成为若干个子系统有利于降低系统的复杂性。一个常见的设计目标是使子系统间的通信和相互依赖关系达到最小。达到该目标的途径之一就是引入一个外观对象,它为子系统中较为一般的设施提供了一个单一而简单的界面。
以下情况使用外观模式:
- 当你要为一个复杂的子系统提供一个简单的接口,子系统往往因为不断演化而变得越来越复杂。大多数模式使用时都会产生更多更小的类,这使得子系统更具可重用性,也更容易对子系统进行定制,但这也给那些不需要定制子系统的用户带来一些使用上的困难。
- 客户程序与抽象类的实现部分之间存在很大的依赖性。引入外观将这个子系统与客户以及其他子系统分离,可以提高子系统的独立性和可移植性。
- 当你需要构建一个层次结构的子系统时,使用外观模式定义子系统中每层的入口点。如果子系统之间是相互依赖的,你可以让它们仅通过外观进行通讯,从而简化了它们之间的依赖关系。
示例:
CPU.java
public class CPU { public void freeze() { System.out.println("CPU freeze"); } public void jump(long position) { System.out.println("CPU jump"); } public void execute() { System.out.println("CPU execute"); } }
HardDevice.java
public class HardDrive { public byte[] read(long lba, int size) { System.out.println("HardDevice read"); return new byte[size]; } }
public class Memory { public static long BOOT_ADDRESS; public static long BOOT_SECTOR; public static int SECTOR_SIZE; public void load(long position, byte[] data) { System.out.println("Memory load"); } }
ComputerFacade.java
public class ComputerFacade { private CPU processor; private Memory ram; private HardDrive hd; public ComputerFacade() { this.processor = new CPU(); this.ram = new Memory(); this.hd = new HardDrive(); } public void start() { processor.freeze(); ram.load(Memory.BOOT_ADDRESS, hd.read(Memory.BOOT_SECTOR, Memory.SECTOR_SIZE)); processor.jump(Memory.BOOT_ADDRESS); processor.execute(); } }
App.java
public class App { public static void main(String[] args) { ComputerFacade computer = new ComputerFacade(); computer.start(); } }
示例2
DwarvenCartOperator.java
public class DwarvenCartOperator extends DwarvenMineWorker { @Override public void work() { System.out.println(name() + " moves gold chunks out of the mine."); } @Override public String name() { return "Dwarf cart operator"; } }
DwarvenGoldDigger.java
public class DwarvenGoldDigger extends DwarvenMineWorker { @Override public void work() { System.out.println(name() + "digs for gold."); } @Override public String name() { return "Dwarf gold digger"; } }
DwarvenMineWorker.java
public abstract class DwarvenMineWorker { public void goToSleep() { System.out.println(name() + "goes to sleep."); } public void wakeUp() { System.out.println(name() + " wakes up."); } public void goHome() { System.out.println(name() + " goes home."); } public void goToMine() { System.out.println(name() + " goes to the mine."); } private void action(Action action) { switch (action) { case GO_TO_SLEEP: goToSleep(); break; case WAKE_UP: wakeUp(); break; case GO_HOME: goHome(); break; case GO_TO_MINE: goToMine(); break; case WORK: work(); break; default: System.out.println("Undefined action"); break; } } /** * Perform actions */ public void action(Action... actions) { for (Action action : actions) { action(action); } } public abstract void work(); public abstract String name(); static enum Action { GO_TO_SLEEP, WAKE_UP, GO_HOME, GO_TO_MINE, WORK } }
DwarvenTunelDigger.java
public class DwarvenTunnelDigger extends DwarvenMineWorker { @Override public void work() { System.out.println(name() + " creates another promising tunnel."); } @Override public String name() { return "Dwarven tunnel digger"; } }
DwarvenGoldmineFacade.java
public class DwarvenGoldmineFacade { private final List<DwarvenMineWorker> workers; /** * Constructor */ public DwarvenGoldmineFacade() { workers = new ArrayList<>(); workers.add(new DwarvenGoldDigger()); workers.add(new DwarvenCartOperator()); workers.add(new DwarvenTunnelDigger()); } public void startNewDay() { makeActions(workers, DwarvenMineWorker.Action.WAKE_UP, DwarvenMineWorker.Action.GO_TO_MINE); } public void digOutGold() { makeActions(workers, DwarvenMineWorker.Action.WORK); } public void endDay() { makeActions(workers, DwarvenMineWorker.Action.GO_HOME, DwarvenMineWorker.Action.GO_TO_SLEEP); } private static void makeActions(Collection<DwarvenMineWorker> workers, DwarvenMineWorker.Action... actions) { for (DwarvenMineWorker worker : workers) { worker.action(actions); } } }
架构师成长营