门面模式 Facade
1、什么是门面模式
门面模式(Facade Pattern)是一种结构型设计模式,旨在为系统提供一个统一的接口,以便于访问子系统中的一群接口。它通过定义一个高层接口,简化了客户端与子系统之间的交互,从而降低了系统的复杂性。
2、为什么使用门面模式
- 简化接口:门面模式通过定义一个高层接口,简化了客户端与子系统之间的交互,使得客户端无需直接与子系统的复杂接口打交道。
- 解耦客户端和子系统:通过引入门面,客户端与子系统的依赖关系得到解耦,客户端只需与门面进行交互,而不需要关心子系统的具体实现。
- 提高可维护性:门面模式将子系统的实现细节封装起来,有助于提高系统的可维护性,降低了系统的复杂性。
3、如何实现门面模式
设计实现一个简单的计算启动过程
// 子系统 - CPU
class CPU {
public void start() {
System.out.println("CPU is starting...");
}
}
// 子系统 - Memory
class Memory {
public void load() {
System.out.println("Memory is loading...");
}
}
// 子系统 - HardDrive
class HardDrive {
public void read() {
System.out.println("HardDrive is reading...");
}
}
// 门面类 - ComputerFacade
class ComputerFacade {
private CPU cpu;
private Memory memory;
private HardDrive hardDrive;
public ComputerFacade() {
this.cpu = new CPU();
this.memory = new Memory();
this.hardDrive = new HardDrive();
}
public void startComputer() {
cpu.start();
memory.load();
hardDrive.read();
System.out.println("Computer is started and ready to use.");
}
}
// 客户端代码
public class Client {
public static void main(String[] args) {
ComputerFacade computerFacade = new ComputerFacade();
computerFacade.startComputer();
}
}
4、是否存在缺陷和不足
- 不符合开闭原则:当系统中的子系统发生变化时,可能需要修改门面类,不符合开闭原则。
- 可能导致过多门面类:随着系统的不断扩展,可能会出现多个门面类,导致系统变得复杂。
5、如何缓解缺陷和不足
- 使用配置文件:将子系统的配置信息放置在配置文件中,通过读取配置文件的方式动态创建门面类,提高系统的灵活性。
- 使用抽象工厂模式:可以结合抽象工厂模式,将门面的创建过程交给工厂类,从而降低客户端与门面的耦合度。
// 抽象产品 - CPU
interface CPU {
void start();
}
// 具体产品A - ConcreteCPUA
class ConcreteCPUA implements CPU {
@Override
public void start() {
System.out.println("ConcreteCPUA is starting...");
}
}
// 具体产品B - ConcreteCPUB
class ConcreteCPUB implements CPU {
@Override
public void start() {
System.out.println("ConcreteCPUB is starting...");
}
}
// 抽象产品 - Memory
interface Memory {
void load();
}
// 具体产品A - ConcreteMemoryA
class ConcreteMemoryA implements Memory {
@Override
public void load() {
System.out.println("ConcreteMemoryA is loading...");
}
}
// 具体产品B - ConcreteMemoryB
class ConcreteMemoryB implements Memory {
@Override
public void load() {
System.out.println("ConcreteMemoryB is loading...");
}
}
// 抽象产品 - HardDrive
interface HardDrive {
void read();
}
// 具体产品A - ConcreteHardDriveA
class ConcreteHardDriveA implements HardDrive {
@Override
public void read() {
System.out.println("ConcreteHardDriveA is reading...");
}
}
// 具体产品B - ConcreteHardDriveB
class ConcreteHardDriveB implements HardDrive {
@Override
public void read() {
System.out.println("ConcreteHardDriveB is reading...");
}
}
// 抽象工厂接口
interface ComputerFactory {
CPU createCPU();
Memory createMemory();
HardDrive createHardDrive();
}
// 具体工厂A
class ConcreteFactoryA implements ComputerFactory {
@Override
public CPU createCPU() {
return new ConcreteCPUA();
}
@Override
public Memory createMemory() {
return new ConcreteMemoryA();
}
@Override
public HardDrive createHardDrive() {
return new ConcreteHardDriveA();
}
}
// 具体工厂B
class ConcreteFactoryB implements ComputerFactory {
@Override
public CPU createCPU() {
return new ConcreteCPUB();
}
@Override
public Memory createMemory() {
return new ConcreteMemoryB();
}
@Override
public HardDrive createHardDrive() {
return new ConcreteHardDriveB();
}
}
// 门面类
class ComputerFacade {
private CPU cpu;
private Memory memory;
private HardDrive hardDrive;
public ComputerFacade(ComputerFactory factory) {
this.cpu = factory.createCPU();
this.memory = factory.createMemory();
this.hardDrive = factory.createHardDrive();
}
public void startComputer() {
cpu.start();
memory.load();
hardDrive.read();
System.out.println("Computer is started and ready to use.");
}
}
// 客户端代码
public class Client {
public static void main(String[] args) {
// 使用工厂A创建电脑
ComputerFactory factoryA = new ConcreteFactoryA();
ComputerFacade computerFacadeA = new ComputerFacade(factoryA);
computerFacadeA.startComputer();
// 使用工厂B创建电脑
ComputerFactory factoryB = new ConcreteFactoryB();
ComputerFacade computerFacadeB = new ComputerFacade(factoryB);
computerFacadeB.startComputer();
}
}
上面这个例子中,抽象工厂模式用于创建不同系列的电脑产品,而门面类的创建过程交给工厂类,客户端代码通过选择不同的工厂来创建不同系列的电脑,无需关心具体产品的创建过程,有助于提高系统的灵活性和可维护性
组合模式 Composite
1、什么是组合模式
组合模式通过将对象组织成树形结构来表示整体-部分层次结构,使得客户端可以统一对待单个对象和对象的组合。它主要包含三个角色:叶子节点(Leaf)、组合节点(Composite)、客户端(Client)。
2、为什么使用组合模式
- 统一接口:组合模式使得客户端可以统一对待单个对象和对象的组合,因为它们共享相同的接口。
- 灵活性:客户端无需关心对象是叶子节点还是组合节点,可以在不同层次构建复杂的对象结构。
- 简化客户端代码:客户端无需判断操作的是单个对象还是对象组合,简化了客户端代码。
3、如何使用组合模式
设计实现一个文件系统
import java.util.ArrayList;
import java.util.List;
// 抽象组件 - 文件和目录的共同接口
interface FileSystemComponent {
void display();
}
// 叶子节点 - 文件
class FileLeaf implements FileSystemComponent {
private String name;
public FileLeaf(String name) {
this.name = name;
}
@Override
public void display() {
System.out.println("File: " + name);
}
}
// 组合节点 - 目录
class DirectoryComposite implements FileSystemComponent {
private String name;
private List<FileSystemComponent> components;
public DirectoryComposite(String name) {
this.name = name;
this.components = new ArrayList<>();
}
public void addComponent(FileSystemComponent component) {
components.add(component);
}
public void removeComponent(FileSystemComponent component) {
components.remove(component);
}
@Override
public void display() {
System.out.println("Directory: " + name);
for (FileSystemComponent component : components) {
component.display();
}
}
}
// 客户端代码
public class Client {
public static void main(String[] args) {
// 构建文件系统结构
FileSystemComponent file1 = new FileLeaf("file1.txt");
FileSystemComponent file2 = new FileLeaf("file2.txt");
DirectoryComposite dir1 = new DirectoryComposite("Folder 1");
dir1.addComponent(file1);
dir1.addComponent(file2);
FileSystemComponent file3 = new FileLeaf("file3.txt");
DirectoryComposite dir2 = new DirectoryComposite("Folder 2");
dir2.addComponent(file3);
dir2.addComponent(dir1);
// 显示文件系统结构
dir2.display();
}
}
4、是否存在缺陷和不足
- 限制类型一致性:组合模式要求所有组件都实现相同的接口,这可能限制了组件的类型一致性。
- 不支持单个对象的特殊处理:组合模式统一对待单个对象和组合对象,因此可能无法支持对单个对象的特殊处理。
5、如何缓解缺陷和不足
- 使用抽象构件类:引入一个抽象构建类,包含所有子类共有的方法,从而提高组件的类型一致性。
- 在叶子节点实现特殊处理:在叶子节点类中实现特殊处理逻辑,以满足对单个对象的特殊需求。