外观模式(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();
}
}
总结
外观模式通过提供一个统一的接口,简化了复杂系统的使用,减少了客户端与多个子系统之间的直接交互。在电商系统、数据库访问和线程管理等场景中,外观模式都能有效提高系统的可维护性和可读性。合理运用外观模式,可以显著提升开发效率和用户体验。