外观模式(Facade Pattern)是一种结构性设计模式,它为复杂子系统提供一个统一的接口,从而简化与这些子系统的交互。通过外观模式,客户端可以更轻松地使用复杂系统,而不必了解其内部实现。接下来,我们将通过示例代码详细讲解外观模式,并探讨它的应用场景。
外观模式示例代码
在这个示例中,我们将创建一个简单的音响系统。这个系统包括多个子系统,如 DVD 播放器、CD 播放器和音响设备。我们会为这个复杂系统提供一个外观类,以简化用户的操作。
示例代码
java">// DVD 播放器子系统
class DVDPlayer {public void on() {System.out.println("DVD 播放器开机");}public void play() {System.out.println("DVD 播放中...");}public void off() {System.out.println("DVD 播放器关机");}
}// CD 播放器子系统
class CDPlayer {public void on() {System.out.println("CD 播放器开机");}public void play() {System.out.println("CD 播放中...");}public void off() {System.out.println("CD 播放器关机");}
}// 音响设备子系统
class SoundSystem {public void on() {System.out.println("音响设备开机");}public void setVolume(int level) {System.out.println("音量设置为 " + level);}public void off() {System.out.println("音响设备关机");}
}// 外观类
class HomeTheaterFacade {private DVDPlayer dvdPlayer;private CDPlayer cdPlayer;private SoundSystem soundSystem;public HomeTheaterFacade() {dvdPlayer = new DVDPlayer();cdPlayer = new CDPlayer();soundSystem = new SoundSystem();}public void watchMovie() {soundSystem.on();soundSystem.setVolume(10);dvdPlayer.on();dvdPlayer.play();}public void listenToCD() {soundSystem.on();soundSystem.setVolume(5);cdPlayer.on();cdPlayer.play();}public void turnOff() {dvdPlayer.off();cdPlayer.off();soundSystem.off();}
}// 客户端代码
public class Main {public static void main(String[] args) {HomeTheaterFacade homeTheater = new HomeTheaterFacade();homeTheater.watchMovie();homeTheater.listenToCD();homeTheater.turnOff();}
}
外观模式的运用场景
外观模式可以在多个实际应用场景中发挥重要作用。以下是几个常见的运用场景及其相应的代码示例。
1. 简化复杂系统
在电商系统中,用户需要完成商品购买,这可能涉及订单、商品、支付和会员等多个子系统。我们可以通过外观类来简化用户的操作。
示例代码
java">// 商品子系统
class ProductService {public void listProducts() {System.out.println("列出所有商品");}
}// 订单子系统
class OrderService {public void createOrder(String product) {System.out.println("创建订单,商品: " + product);}
}// 支付子系统
class PaymentService {public void processPayment(String orderId) {System.out.println("处理订单支付,订单ID: " + orderId);}
}// 电商外观类
class ECommerceFacade {private ProductService productService;private OrderService orderService;private PaymentService paymentService;public ECommerceFacade() {productService = new ProductService();orderService = new OrderService();paymentService = new PaymentService();}public void purchaseProduct(String product) {productService.listProducts();orderService.createOrder(product);paymentService.processPayment("12345");}
}// 客户端代码
public class Main {public static void main(String[] args) {ECommerceFacade facade = new ECommerceFacade();facade.purchaseProduct("手机");}
}
2. 减少客户端处理的系统数量
在 Web 应用中,客户端可能需要处理多个系统的调用,如数据库、业务对象等。通过创建一个 DAO 层作为门面,可以简化这些操作。
示例代码
java">// 模拟数据库操作
class Database {public void connect() {System.out.println("连接数据库");}public void disconnect() {System.out.println("关闭数据库连接");}public String fetchData() {return "数据记录";}
}// 业务对象
class BusinessModel {private String data;public BusinessModel(String data) {this.data = data;}public void display() {System.out.println("业务数据: " + data);}
}// DAO层
class DataAccessFacade {private Database database;public DataAccessFacade() {database = new Database();}public BusinessModel getBusinessModel() {database.connect();String data = database.fetchData();database.disconnect();return new BusinessModel(data);}
}// 客户端代码
public class Main {public static void main(String[] args) {DataAccessFacade dataAccess = new DataAccessFacade();BusinessModel model = dataAccess.getBusinessModel();model.display();}
}
3. 让一个系统为多个系统工作
线程池是外观模式的另一个典型应用,它为系统提供统一的线程管理接口,使得线程的创建和使用变得简单。
示例代码
java">import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;// 线程池外观
class ThreadPoolFacade {private ExecutorService executorService;public ThreadPoolFacade(int poolSize) {executorService = Executors.newFixedThreadPool(poolSize);}public void executeTask(Runnable task) {executorService.execute(task);}public void shutdown() {executorService.shutdown();}
}// 客户端代码
public class Main {public static void main(String[] args) {ThreadPoolFacade threadPool = new ThreadPoolFacade(5);for (int i = 0; i < 10; i++) {final int taskId = i;threadPool.executeTask(() -> {System.out.println("执行任务 " + taskId);});}threadPool.shutdown();}
}
总结
外观模式通过提供一个统一的接口,简化了复杂系统的使用,减少了客户端与多个子系统之间的直接交互。在电商系统、数据库访问和线程管理等场景中,外观模式都能有效提高系统的可维护性和可读性。合理运用外观模式,可以显著提升开发效率和用户体验。