三、结构型模式:对象的组合与组织
结构型模式关注如何将类和对象组合成更大的结构,在保证灵活性的同时优化系统结构。
3.1 适配器模式(Adapter)—— 兼容旧系统
适配器模式将不兼容的接口转换为客户端期望的接口。
// 已有接口(第三方库)
public interface LegacyPaymentGateway {
void sendPayment(String data);
}
public class LegacyPayPalGateway implements LegacyPaymentGateway {
@Override
public void sendPayment(String data) {
System.out.println("Legacy PayPal payment: " + data);
}
}
// 新系统期望的接口
public interface ModernPaymentGateway {
PaymentResponse processPayment(PaymentRequest request);
}
public class PaymentRequest {
private String orderId;
private BigDecimal amount;
private String cardNumber;
// getters/setters
}
public class PaymentResponse {
private boolean success;
private String transactionId;
private String message;
}
// 适配器
public class PayPalAdapter implements ModernPaymentGateway {
private final LegacyPaymentGateway legacyGateway;
public PayPalAdapter(LegacyPaymentGateway legacyGateway) {
this.legacyGateway = legacyGateway;
}
@Override
public PaymentResponse processPayment(PaymentRequest request) {
// 转换请求格式
String legacyData = String.format("order=%s,amount=%s,card=%s",
request.getOrderId(),
request.getAmount(),
request.getCardNumber()
);
// 调用旧系统
legacyGateway.sendPayment(legacyData);
// 转换响应格式
PaymentResponse response = new PaymentResponse();
response.setSuccess(true);
response.setTransactionId(generateTransactionId());
response.setMessage("Payment successful");
return response;
}
private String generateTransactionId() {
return "TXN-" + System.currentTimeMillis();
}
}
// 使用示例
public class PaymentService {
private final ModernPaymentGateway paymentGateway;
public PaymentService(ModernPaymentGateway paymentGateway) {
this.paymentGateway = paymentGateway;
}
public void checkout() {
PaymentRequest request = new PaymentRequest();
request.setOrderId("ORDER-123");
request.setAmount(new BigDecimal("99.99"));
request.setCardNumber("****-****-****-1234");
PaymentResponse response = paymentGateway.processPayment(request);
System.out.println("Payment result: " + response.isSuccess());
}
}
// 客户端代码
public class Client {
public static void main(String[] args) {
LegacyPaymentGateway legacyGateway = new LegacyPayPalGateway();
ModernPaymentGateway adapter = new PayPalAdapter(legacyGateway);
PaymentService service = new PaymentService(adapter);
service.checkout();
}
}
3.2 装饰器模式(Decorator)—— 动态增强功能
装饰器模式动态地为对象添加额外职责,比继承更灵活。
// 基础组件接口
public interface Coffee {
String getDescription();
double getCost();
}
// 具体组件
public class SimpleCoffee implements Coffee {
@Override
public String getDescription() {
return "Simple coffee";
}
@Override
public double getCost() {
return 2.0;
}
}
// 装饰器基类
public abstract class CoffeeDecorator implements Coffee {
protected Coffee decoratedCoffee;
public CoffeeDecorator(Coffee coffee) {
this.decoratedCoffee = coffee;
}
@Override
public String getDescription() {
return decoratedCoffee.getDescription();
}
@Override
public double getCost() {
return decoratedCoffee.getCost();
}
}
// 具体装饰器
public class MilkDecorator extends CoffeeDecorator {
public MilkDecorator(Coffee coffee) {
super(coffee);
}
@Override
public String getDescription() {
return super.getDescription() + ", milk";
}
@Override
public double getCost() {
return super.getCost() + 0.5;
}
}
public class SugarDecorator extends CoffeeDecorator {
public SugarDecorator(Coffee coffee) {
super(coffee);
}
@Override
public String getDescription() {
return super.getDescription() + ", sugar";
}
@Override
public double getCost() {
return super.getCost() + 0.2;
}
}
public class WhipDecorator extends CoffeeDecorator {
public WhipDecorator(Coffee coffee) {
super(coffee);
}
@Override
public String getDescription() {
return super.getDescription() + ", whipped cream";
}
@Override
public double getCost() {
return super.getCost() + 0.8;
}
}
// 使用示例(Java I/O 中大量使用装饰器模式)
public class CoffeeShop {
public static void main(String[] args) {
// 简单咖啡
Coffee coffee = new SimpleCoffee();
System.out.println(coffee.getDescription() + " $" + coffee.getCost());
// 加牛奶
coffee = new MilkDecorator(coffee);
System.out.println(coffee.getDescription() + " $" + coffee.getCost());
// 加糖和奶油
coffee = new SugarDecorator(coffee);
coffee = new WhipDecorator(coffee);
System.out.println(coffee.getDescription() + " $" + coffee.getCost());
// 输出:
// Simple coffee $2.0
// Simple coffee, milk $2.5
// Simple coffee, milk, sugar, whipped cream $3.5
}
}
// Java I/O 中的装饰器模式
// InputStream 是抽象组件
// FileInputStream 是具体组件
// BufferedInputStream 是装饰器
InputStream in = new BufferedInputStream(
new GZIPInputStream(
new FileInputStream("test.txt")
)
);
3.3 代理模式(Proxy)—— 控制访问
代理模式为其他对象提供一种代理以控制对这个对象的访问。
// 主题接口
public interface Image {
void display();
}
// 真实主题(高开销对象)
public class HighResolutionImage implements Image {
private String filename;
public HighResolutionImage(String filename) {
this.filename = filename;
loadFromDisk();
}
private void loadFromDisk() {
System.out.println("Loading high-res image: " + filename);
try {
Thread.sleep(2000); // 模拟耗时加载
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@Override
public void display() {
System.out.println("Displaying high-res image: " + filename);
}
}
// 代理
public class ImageProxy implements Image {
private HighResolutionImage realImage;
private String filename;
public ImageProxy(String filename) {
this.filename = filename;
}
@Override
public void display() {
// 延迟加载:只有在真正需要时才创建真实对象
if (realImage == null) {
realImage = new HighResolutionImage(filename);
}
realImage.display();
}
}
// 动态代理示例(AOP实现)
public class DynamicProxyDemo {
// 需要代理的接口
public interface UserService {
void saveUser(String name);
String getUser(Long id);
}
// 目标对象
public static class UserServiceImpl implements UserService {
@Override
public void saveUser(String name) {
System.out.println("Saving user: " + name);
}
@Override
public String getUser(Long id) {
System.out.println("Getting user: " + id);
return "User-" + id;
}
}
// 动态代理处理器
public static class LoggingInvocationHandler implements InvocationHandler {
private final Object target;
public LoggingInvocationHandler(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 前置增强
System.out.println("[LOG] Method " + method.getName() + " started");
long startTime = System.currentTimeMillis();
// 调用目标方法
Object result = method.invoke(target, args);
// 后置增强
long endTime = System.currentTimeMillis();
System.out.println("[LOG] Method " + method.getName() + " completed in " + (endTime - startTime) + "ms");
return result;
}
}
public static void main(String[] args) {
UserService target = new UserServiceImpl();
UserService proxy = (UserService) Proxy.newProxyInstance(
UserService.class.getClassLoader(),
new Class[]{UserService.class},
new LoggingInvocationHandler(target)
);
proxy.saveUser("Alice");
proxy.getUser(123L);
}
}
3.4 外观模式(Facade)—— 简化复杂子系统
外观模式为子系统中的一组接口提供一个统一的入口。
// 复杂的子系统
public class InventorySystem {
public boolean checkStock(String productId, int quantity) {
System.out.println("Checking stock for: " + productId);
return quantity <= 100;
}
public void reserveStock(String productId, int quantity) {
System.out.println("Reserving " + quantity + " of " + productId);
}
}
public class PaymentSystem {
public boolean processPayment(String userId, BigDecimal amount) {
System.out.println("Processing payment for user " + userId + ": $" + amount);
return true;
}
public void refund(String transactionId, BigDecimal amount) {
System.out.println("Refunding $" + amount + " for transaction: " + transactionId);
}
}
public class ShippingSystem {
public String createShipment(String orderId, String address) {
System.out.println("Creating shipment for order: " + orderId);
return "TRACK-" + orderId;
}
public void notifyShipping(String trackingNumber) {
System.out.println("Sending shipping notification: " + trackingNumber);
}
}
// 外观类
public class OrderFacade {
private final InventorySystem inventory;
private final PaymentSystem payment;
private final ShippingSystem shipping;
public OrderFacade() {
this.inventory = new InventorySystem();
this.payment = new PaymentSystem();
this.shipping = new ShippingSystem();
}
// 简化的下单接口
public OrderResult placeOrder(OrderRequest request) {
try {
// 1. 检查库存
if (!inventory.checkStock(request.getProductId(), request.getQuantity())) {
return OrderResult.failure("Insufficient stock");
}
// 2. 处理支付
if (!payment.processPayment(request.getUserId(), request.getAmount())) {
return OrderResult.failure("Payment failed");
}
// 3. 扣减库存
inventory.reserveStock(request.getProductId(), request.getQuantity());
// 4. 创建物流
String trackingNumber = shipping.createShipment(
request.getOrderId(),
request.getShippingAddress()
);
// 5. 发送通知
shipping.notifyShipping(trackingNumber);
return OrderResult.success(trackingNumber);
} catch (Exception e) {
return OrderResult.failure(e.getMessage());
}
}
}
// 客户端只需调用外观
public class Client {
public static void main(String[] args) {
OrderFacade facade = new OrderFacade();
OrderRequest request = new OrderRequest();
request.setOrderId("ORD-001");
request.setUserId("USER-123");
request.setProductId("P001");
request.setQuantity(2);
request.setAmount(new BigDecimal("199.98"));
request.setShippingAddress("123 Main St");
OrderResult result = facade.placeOrder(request);
System.out.println("Order result: " + result.getMessage());
}
}
3.5 组合模式(Composite)—— 树形结构处理
组合模式将对象组合成树形结构以表示“部分-整体”层次结构。
// 抽象组件
public interface FileSystemNode {
String getName();
long getSize();
void display(String indent);
}
// 叶子节点(文件)
public class File implements FileSystemNode {
private String name;
private long size;
public File(String name, long size) {
this.name = name;
this.size = size;
}
@Override
public String getName() {
return name;
}
@Override
public long getSize() {
return size;
}
@Override
public void display(String indent) {
System.out.println(indent + "📄 " + name + " (" + size + " bytes)");
}
}
// 容器节点(目录)
public class Directory implements FileSystemNode {
private String name;
private List<FileSystemNode> children = new ArrayList<>();
public Directory(String name) {
this.name = name;
}
public void addNode(FileSystemNode node) {
children.add(node);
}
public void removeNode(FileSystemNode node) {
children.remove(node);
}
@Override
public String getName() {
return name;
}
@Override
public long getSize() {
return children.stream()
.mapToLong(FileSystemNode::getSize)
.sum();
}
@Override
public void display(String indent) {
System.out.println(indent + "📁 " + name + " (" + getSize() + " bytes)");
for (FileSystemNode child : children) {
child.display(indent + " ");
}
}
}
// 使用示例
public class FileSystemDemo {
public static void main(String[] args) {
// 构建树形结构
Directory root = new Directory("root");
Directory documents = new Directory("documents");
documents.addNode(new File("resume.pdf", 102400));
documents.addNode(new File("cover-letter.docx", 51200));
Directory photos = new Directory("photos");
photos.addNode(new File("vacation.jpg", 2048000));
photos.addNode(new File("family.png", 3072000));
Directory work = new Directory("work");
work.addNode(new File("report.xlsx", 153600));
work.addNode(new File("presentation.pptx", 256000));
photos.addNode(work);
root.addNode(documents);
root.addNode(photos);
root.addNode(new File("readme.txt", 1024));
// 统一处理
root.display("");
// 输出:
// 📁 root (5738624 bytes)
// 📁 documents (153600 bytes)
// 📄 resume.pdf (102400 bytes)
// 📄 cover-letter.docx (51200 bytes)
// 📁 photos (5120000 bytes)
// 📄 vacation.jpg (2048000 bytes)
// 📄 family.png (3072000 bytes)
// 📁 work (409600 bytes)
// 📄 report.xlsx (153600 bytes)
// 📄 presentation.pptx (256000 bytes)
// 📄 readme.txt (1024 bytes)
}
}