高级04-Java 设计模式:常用模式详解与实战
设计模式(Design Pattern)是软件开发中解决常见问题的经典方案。它们提供了一种可重用的、经过验证的代码结构,使得程序更加灵活、可扩展,并且易于维护。Java 作为一门面向对象的编程语言,广泛支持各种设计模式的应用。理解并熟练使用这些模式,对于编写高质量的 Java 代码至关重要。
本博客将详细介绍 Java 中常用的 23 种设计模式,按照它们的分类——**创建型模式(Creational Patterns)、结构型模式(Structural Patterns)和行为型模式(Behavioral Patterns)**进行讲解。每个模式都会结合实际案例,提供完整的代码示例和使用场景,帮助读者深入理解设计模式的应用方式。
一、创建型模式
创建型模式关注对象的创建机制,旨在解耦对象的创建与使用,提高系统的灵活性和可扩展性。常见的创建型模式包括:单例模式、工厂模式、抽象工厂模式、建造者模式和原型模式。
1. 单例模式(Singleton Pattern)
单例模式确保一个类只有一个实例,并提供全局访问点。它适用于需要共享资源的场景,例如数据库连接池、日志管理器等。
代码示例:
public class Singleton {// 私有静态实例private static Singleton instance;// 私有构造函数private Singleton() {}// 提供全局访问方法public static Singleton getInstance() {if (instance == null) {synchronized (Singleton.class) {if (instance == null) {instance = new Singleton();}}}return instance;}public void showMessage() {System.out.println("Hello from Singleton!");}
}// 使用示例
public class Main {public static void main(String[] args) {Singleton singleton1 = Singleton.getInstance();Singleton singleton2 = Singleton.getInstance();singleton1.showMessage();singleton2.showMessage();// 验证是否为同一个实例System.out.println("singleton1 == singleton2: " + (singleton1 == singleton2));}
}
输出:
Hello from Singleton!
Hello from Singleton!
singleton1 == singleton2: true
说明:
- 采用双重检查锁定(Double-Checked Locking)确保线程安全。
- 单例模式适用于需要全局唯一实例的场景。
2. 工厂模式(Factory Pattern)
工厂模式定义一个用于创建对象的接口,让子类决定实例化哪一个类。它适用于需要根据条件创建不同对象的场景,例如支付系统、数据库连接等。
代码示例:
// 抽象产品接口
interface Shape {void draw();
}// 具体产品类
class Circle implements Shape {@Overridepublic void draw() {System.out.println("Drawing Circle");}
}class Square implements Shape {@Overridepublic void draw() {System.out.println("Drawing Square");}
}// 工厂类
class ShapeFactory {public Shape getShape(String shapeType) {if (shapeType == null) {return null;}if (shapeType.equalsIgnoreCase("CIRCLE")) {return new Circle();} else if (shapeType.equalsIgnoreCase("SQUARE")) {return new Square();}return null;}
}// 使用示例
public class Main {public static void main(String[] args) {ShapeFactory shapeFactory = new ShapeFactory();Shape shape1 = shapeFactory.getShape("CIRCLE");shape1.draw();Shape shape2 = shapeFactory.getShape("SQUARE");shape2.draw();}
}
输出:
Drawing Circle
Drawing Square
说明:
- 工厂模式将对象的创建逻辑封装在工厂类中,客户端无需关心具体实现。
- 适用于需要根据参数动态创建对象的场景。
3. 抽象工厂模式(Abstract Factory Pattern)
抽象工厂模式提供一个接口,用于创建相关或依赖对象的家族,而无需指定具体类。它适用于需要创建一组相关对象的场景,例如跨平台的 UI 组件库。
代码示例:
// 抽象产品接口 A
interface Button {void render();
}// 抽象产品接口 B
interface Checkbox {void render();
}// 具体产品 A1
class WindowsButton implements Button {@Overridepublic void render() {System.out.println("Render a button in Windows style.");}
}// 具体产品 B1
class WindowsCheckbox implements Checkbox {@Overridepublic void render() {System.out.println("Render a checkbox in Windows style.");}
}// 具体产品 A2
class MacButton implements Button {@Overridepublic void render() {System.out.println("Render a button in Mac style.");}
}// 具体产品 B2
class MacCheckbox implements Checkbox {@Overridepublic void render() {System.out.println("Render a checkbox in Mac style.");}
}// 抽象工厂
interface GUIFactory {Button createButton();Checkbox createCheckbox();
}// 具体工厂 1
class WindowsFactory implements GUIFactory {@Overridepublic Button createButton() {return new WindowsButton();}@Overridepublic Checkbox createCheckbox() {return new WindowsCheckbox();}
}// 具体工厂 2
class MacFactory implements GUIFactory {@Overridepublic Button createButton() {return new MacButton();}@Overridepublic Checkbox createCheckbox() {return new MacCheckbox();}
}// 客户端代码
public class Application {private Button button;private Checkbox checkbox;public Application(GUIFactory factory) {button = factory.createButton();checkbox = factory.createCheckbox();}public void render() {button.render();checkbox.render();}
}// 使用示例
public class Main {public static void main(String[] args) {String os = "MAC"; // 假设当前操作系统为 MacGUIFactory factory;if (os.equals("MAC")) {factory = new MacFactory();} else {factory = new WindowsFactory();}Application app = new Application(factory);app.render();}
}
输出:
Render a button in Mac style.
Render a checkbox in Mac style.
说明:
- 抽象工厂模式适用于需要创建一组相关对象的场景。
- 客户端代码无需关心具体产品类,只需调用工厂接口即可。
4. 建造者模式(Builder Pattern)
建造者模式将一个复杂对象的构建与其表示分离,使得同样的构建过程可以创建不同的表示。它适用于对象的创建过程复杂、需要分步骤构造的场景,例如生成不同配置的计算机、不同套餐的披萨等。
代码示例:
// 产品类
class Computer {private String CPU;private String RAM;private String storage;public void setCPU(String CPU) {this.CPU = CPU;}public void setRAM(String RAM) {this.RAM = RAM;}public void setStorage(String storage) {this.storage = storage;}@Overridepublic String toString() {return "Computer [CPU=" + CPU + ", RAM=" + RAM + ", Storage=" + storage + "]";}
}// 建造者接口
interface ComputerBuilder {void buildCPU();void buildRAM();void buildStorage();Computer getComputer();
}// 具体建造者
class GamingComputerBuilder implements ComputerBuilder {private Computer computer;public GamingComputerBuilder() {computer = new Computer();}@Overridepublic void buildCPU() {computer.setCPU("Intel i9");}@Overridepublic void buildRAM() {computer.setRAM("32GB");}@Overridepublic void buildStorage() {computer.setStorage("1TB SSD");}@Overridepublic Computer getComputer() {return computer;}
}// 指挥者类
class Director {private ComputerBuilder builder;public void setBuilder(ComputerBuilder builder) {this.builder = builder;}public Computer constructComputer() {builder.buildCPU();builder.buildRAM();builder.buildStorage();return builder.getComputer();}
}// 使用示例
public class Main {public static void main(String[] args) {Director director = new Director();ComputerBuilder builder = new GamingComputerBuilder();director.setBuilder(builder);Computer computer = director.constructComputer();System.out.println(computer);}
}
输出:
Computer [CPU=Intel i9, RAM=32GB, Storage=1TB SSD]
说明:
- 建造者模式适用于需要分步骤构建复杂对象的场景。
- 指挥者类负责控制构建流程,建造者类负责具体实现。
5. 原型模式(Prototype Pattern)
原型模式通过克隆已有对象来创建新对象,而不是通过实例化类。它适用于对象的创建成本较高、需要频繁创建相似对象的场景,例如数据库连接、配置对象等。
代码示例:
// 实现 Cloneable 接口
class Prototype implements Cloneable {private String data;public Prototype(String data) {this.data = data;}public String getData() {return data;}public void setData(String data) {this.data = data;}@Overrideprotected Object clone() throws CloneNotSupportedException {return super.clone();}
}// 使用示例
public class Main {public static void main(String[] args) throws CloneNotSupportedException {Prototype prototype1 = new Prototype("Initial Data");Prototype prototype2 = (Prototype) prototype1.clone();System.out.println("prototype1 data: " + prototype1.getData());System.out.println("prototype2 data: " + prototype2.getData());// 修改 prototype2 的数据,不影响 prototype1prototype2.setData("Modified Data");System.out.println("After modification:");System.out.println("prototype1 data: " + prototype1.getData());System.out.println("prototype2 data: " + prototype2.getData());}
}
输出:
prototype1 data: Initial Data
prototype2 data: Initial Data
After modification:
prototype1 data: Initial Data
prototype2 data: Modified Data
说明:
- 原型模式适用于需要创建多个相似对象的场景。
- 通过
clone()
方法创建对象,避免重复初始化,提高性能。
二、结构型模式
结构型模式关注对象和类的组合方式,用于构建更大、更复杂的系统结构。常见的结构型模式包括:适配器模式、代理模式、装饰器模式、外观模式、组合模式、桥接模式和享元模式。
6. 适配器模式(Adapter Pattern)
适配器模式将一个类的接口转换成客户端期望的另一个接口,使得原本不兼容的类可以一起工作。它适用于需要兼容旧系统、第三方库或不同接口的场景。
代码示例:
// 已有接口
interface MediaPlayer {void play(String audioType, String fileName);
}// 已有具体类
class AudioPlayer implements MediaPlayer {@Overridepublic void play(String audioType, String fileName) {if (audioType.equalsIgnoreCase("mp3")) {System.out.println("Playing MP3 file: " + fileName);} else if (audioType.equalsIgnoreCase("vlc") || audioType.equalsIgnoreCase("mp4")) {// 假设不支持这些格式System.out.println("Format not supported: " + audioType);}}
}// 新接口
interface AdvancedMediaPlayer {void playVlc(String fileName);void playMp4(String fileName);
}// 新实现类
class VlcPlayer implements AdvancedMediaPlayer {@Overridepublic void playVlc(String fileName) {System.out.println("Playing VLC file: " + fileName);}@Overridepublic void playMp4(String fileName) {// 不支持}
}class Mp4Player implements AdvancedMediaPlayer {@Overridepublic void playVlc(String fileName) {// 不支持}@Overridepublic void playMp4(String fileName) {System.out.println("Playing MP4 file: " + fileName);}
}// 适配器类
class MediaAdapter implements MediaPlayer {AdvancedMediaPlayer advancedMusicPlayer;public MediaAdapter(String audioType) {if (audioType.equalsIgnoreCase("vlc")) {advancedMusicPlayer = new VlcPlayer();} else if (audioType.equalsIgnoreCase("mp4")) {advancedMusicPlayer = new Mp4Player();}}@Overridepublic void play(String audioType, String fileName) {if (audioType.equalsIgnoreCase("vlc")) {advancedMusicPlayer.playVlc(fileName);} else if (audioType.equalsIgnoreCase("mp4")) {advancedMusicPlayer.playMp4(fileName);}}
}// 使用示例
public class Main {public static void main(String[] args) {MediaPlayer audioPlayer = new AudioPlayer();audioPlayer.play("mp3", "song.mp3");audioPlayer.play("vlc", "movie.vlc");audioPlayer.play("mp4", "video.mp4");}
}
输出:
Playing MP3 file: song.mp3
Playing VLC file: movie.vlc
Playing MP4 file: video.mp4
说明:
- 适配器模式适用于需要兼容不同接口的场景。
- 通过适配器类,可以将不兼容的接口转换为客户端期望的接口。
7. 代理模式(Proxy Pattern)
代理模式为对象提供一个替身或占位符,以控制对对象的访问。它适用于需要对对象的访问进行控制的场景,例如远程调用、权限控制、延迟加载等。
代码示例:
// 接口
interface Image {void display();
}// 真实类
class RealImage implements Image {private String fileName;public RealImage(String fileName) {this.fileName = fileName;loadFromDisk(fileName);}private void loadFromDisk(String fileName) {System.out.println("Loading " + fileName);}@Overridepublic void display() {System.out.println("Displaying " + fileName);}
}// 代理类
class ProxyImage implements Image {private RealImage realImage;private String fileName;public ProxyImage(String fileName) {this.fileName = fileName;}@Overridepublic void display() {if (realImage == null) {realImage = new RealImage(fileName);}realImage.display();}
}// 使用示例
public class Main {public static void main(String[] args) {Image image = new ProxyImage("test.jpg");// 图像不会立即加载System.out.println("Image created, not loaded yet.");image.display(); // 第一次调用时加载System.out.println("Displaying again...");image.display(); // 再次调用时不会重复加载}
}
输出:
Image created, not loaded yet.
Loading test.jpg
Displaying test.jpg
Displaying again...
Displaying test.jpg
说明:
- 代理模式适用于需要控制对象访问的场景。
- 可用于实现延迟加载、权限控制、远程调用等功能。
8. 装饰器模式(Decorator Pattern)
装饰器模式动态地给对象添加职责,比继承更灵活。它适用于需要在运行时动态添加功能的场景,例如 Java 的 I/O 流、GUI 组件增强等。
代码示例:
// 抽象组件
interface Coffee {double cost();String description();
}// 具体组件
class SimpleCoffee implements Coffee {@Overridepublic double cost() {return 2.0;}@Overridepublic String description() {return "Simple Coffee";}
}// 装饰器抽象类
abstract class CoffeeDecorator implements Coffee {protected Coffee decoratedCoffee;public CoffeeDecorator(Coffee coffee) {this.decoratedCoffee = coffee;}@Overridepublic double cost() {return decoratedCoffee.cost();}@Overridepublic String description() {return decoratedCoffee.description();}
}// 具体装饰器 1
class MilkDecorator extends CoffeeDecorator {public MilkDecorator(Coffee coffee) {super(coffee);}@Overridepublic double cost() {return super.cost() + 0.5;}@Overridepublic String description() {return super.description() + ", Milk";}
}// 具体装饰器 2
class SugarDecorator extends CoffeeDecorator {public SugarDecorator(Coffee coffee) {super(coffee);}@Overridepublic double cost() {return super.cost() + 0.2;}@Overridepublic String description() {return super.description() + ", Sugar";}
}// 使用示例
public class Main {public static void main(String[] args) {Coffee coffee = new SimpleCoffee();System.out.println(coffee.description() + " $" + coffee.cost());Coffee milkCoffee = new MilkDecorator(coffee);System.out.println(milkCoffee.description() + " $" + milkCoffee.cost());Coffee milkSugarCoffee = new SugarDecorator(milkCoffee);System.out.println(milkSugarCoffee.description() + " $" + milkSugarCoffee.cost());}
}
输出:
Simple Coffee $2.0
Simple Coffee, Milk $2.5
Simple Coffee, Milk, Sugar $2.7
说明:
- 装饰器模式适用于需要在运行时动态添加功能的场景。
- 相比继承,装饰器模式更加灵活,可以在不同对象上添加不同的功能。
9. 外观模式(Facade Pattern)
外观模式为子系统中的一组接口提供一个统一的接口,简化高层模块对子系统的使用。它适用于需要简化复杂接口调用的场景,例如启动系统、关闭系统等。
代码示例:
// 子系统类 1
class CPU {public void start() {System.out.println("CPU started");}
}// 子系统类 2
class Memory {public void load() {System.out.println("Memory loaded");}
}// 子系统类 3
class HardDrive {public void read() {System.out.println("HardDrive read");}
}// 外观类
class ComputerFacade {private CPU cpu;private Memory memory;private HardDrive hardDrive;public ComputerFacade() {cpu = new CPU();memory = new Memory();hardDrive = new HardDrive();}public void startComputer() {cpu.start();memory.load();hardDrive.read();}
}// 使用示例
public class Main {public static void main(String[] args) {ComputerFacade computer = new ComputerFacade();computer.startComputer();}
}
输出:
CPU started
Memory loaded
HardDrive read
说明:
- 外观模式适用于需要简化复杂系统调用的场景。
- 提供统一的接口,使得客户端无需了解子系统的细节。
10. 组合模式(Composite Pattern)
组合模式允许将对象组合成树形结构,以表示“部分-整体”的层次结构。它适用于需要处理树形结构的场景,例如文件系统、菜单结构等。
代码示例:
// 抽象组件
interface Component {void showPrice();
}// 叶子节点
class Leaf implements Component {private int price;private String name;public Leaf(int price, String name) {this.price = price;this.name = name;}@Overridepublic void showPrice() {System.out.println(name + " : " + price);}
}// 容器节点
class Composite implements Component {private List<Component> components = new ArrayList<>();private String name;public Composite(String name) {this.name = name;}public void addComponent(Component component) {components.add(component);}@Overridepublic void showPrice() {System.out.println(name);for (Component component : components) {component.showPrice();}}
}// 使用示例
public class Main {public static void main(String[] args) {Leaf leaf1 = new Leaf(10, "Leaf 1");Leaf leaf2 = new Leaf(20, "Leaf 2");Composite composite = new Composite("Composite 1");composite.addComponent(leaf1);composite.addComponent(leaf2);composite.showPrice();}
}
输出:
Composite 1
Leaf 1 : 10
Leaf 2 : 20
说明:
- 组合模式适用于需要处理树形结构的场景。
- 可以递归地处理对象,使客户端无需区分叶子节点和容器节点。
11. 桥接模式(Bridge Pattern)
桥接模式将抽象部分与其实现部分分离,使它们可以独立变化。它适用于需要解耦两个独立变化的维度的场景,例如不同操作系统上的图形库、不同支付方式的不同支付渠道等。
代码示例:
// 实现接口
interface Implementor {void operationImpl();
}// 具体实现类 A
class ConcreteImplementorA implements Implementor {@Overridepublic void operationImpl() {System.out.println("ConcreteImplementorA operation");}
}// 具体实现类 B
class ConcreteImplementorB implements Implementor {@Overridepublic void operationImpl() {System.out.println("ConcreteImplementorB operation");}
}// 抽象类
abstract class Abstraction {protected Implementor implementor;protected Abstraction(Implementor implementor) {this.implementor = implementor;}abstract void operation();
}// 扩展抽象类
class RefinedAbstraction extends Abstraction {public RefinedAbstraction(Implementor implementor) {super(implementor);}@Overridevoid operation() {System.out.println("RefinedAbstraction operation");implementor.operationImpl();}
}// 使用示例
public class Main {public static void main(String[] args) {Implementor implementorA = new ConcreteImplementorA();Implementor implementorB = new ConcreteImplementorB();Abstraction abstraction1 = new RefinedAbstraction(implementorA);Abstraction abstraction2 = new RefinedAbstraction(implementorB);abstraction1.operation();abstraction2.operation();}
}
输出:
RefinedAbstraction operation
ConcreteImplementorA operation
RefinedAbstraction operation
ConcreteImplementorB operation
说明:
- 桥接模式适用于需要解耦两个独立变化维度的场景。
- 通过桥接,可以避免类爆炸的问题,提高系统的可扩展性。
12. 享元模式(Flyweight Pattern)
享元模式通过共享对象来减少内存使用,适用于大量相似对象的场景,例如字符串池、数据库连接池等。
代码示例:
// 享元接口
interface Flyweight {void operation(String externalState);
}// 具体享元类
class ConcreteFlyweight implements Flyweight {private String intrinsicState;public ConcreteFlyweight(String intrinsicState) {this.intrinsicState = intrinsicState;}@Overridepublic void operation(String externalState) {System.out.println("Intrinsic State: " + intrinsicState + ", External State: " + externalState);}
}// 享元工厂
class FlyweightFactory {private Map<String, Flyweight> flyweights = new HashMap<>();public Flyweight getFlyweight(String key) {if (!flyweights.containsKey(key)) {flyweights.put(key, new ConcreteFlyweight(key));}return flyweights.get(key);}
}// 使用示例
public class Main {public static void main(String[] args) {FlyweightFactory factory = new FlyweightFactory();Flyweight flyweight1 = factory.getFlyweight("A");flyweight1.operation("External State 1");Flyweight flyweight2 = factory.getFlyweight("A");flyweight2.operation("External State 2");Flyweight flyweight3 = factory.getFlyweight("B");flyweight3.operation("External State 3");}
}
输出:
Intrinsic State: A, External State: External State 1
Intrinsic State: A, External State: External State 2
Intrinsic State: B, External State: External State 3
说明:
- 享元模式适用于需要减少内存使用的场景。
- 通过共享对象,可以减少重复创建对象的开销。
三、行为型模式
行为型模式关注对象之间的交互和职责分配。常见的行为型模式包括:观察者模式、策略模式、责任链模式、命令模式、状态模式、模板方法模式和访问者模式。
13. 观察者模式(Observer Pattern)
观察者模式定义对象间的一对多依赖关系,当一个对象的状态发生改变时,所有依赖它的对象都会收到通知并自动更新。它适用于需要通知多个对象的场景,例如事件监听、数据绑定等。
代码示例:
// 主题接口
interface Subject {void registerObserver(Observer observer);void removeObserver(Observer observer);void notifyObservers();
}// 观察者接口
interface Observer {void update(String message);
}// 具体主题类
class NewsAgency implements Subject {private List<Observer> observers = new ArrayList<>();private String news;@Overridepublic void registerObserver(Observer observer) {observers.add(observer);}@Overridepublic void removeObserver(Observer observer) {observers.remove(observer);}@Overridepublic void notifyObservers() {for (Observer observer : observers) {observer.update(news);}}public void setNews(String news) {this.news = news;notifyObservers();}
}// 具体观察者类
class NewsChannel implements Observer {private String news;@Overridepublic void update(String message) {this.news = message;System.out.println("NewsChannel received: " + news);}
}// 使用示例
public class Main {public static void main(String[] args) {NewsAgency agency = new NewsAgency();NewsChannel channel1 = new NewsChannel();NewsChannel channel2 = new NewsChannel();agency.registerObserver(channel1);agency.registerObserver(channel2);agency.setNews("Breaking News: Java 17 Released!");}
}
输出:
NewsChannel received: Breaking News: Java 17 Released!
NewsChannel received: Breaking News: Java 17 Released!
说明:
- 观察者模式适用于需要通知多个对象的场景。
- 主题和观察者之间解耦,提高系统的灵活性。
14. 策略模式(Strategy Pattern)
策略模式定义一系列算法,将每个算法封装起来,并使它们可以互换使用。它适用于需要在运行时选择不同算法的场景,例如支付方式、排序算法等。
代码示例:
// 策略接口
interface Strategy {int doOperation(int num1, int num2);
}// 具体策略类 1
class OperationAdd implements Strategy {@Overridepublic int doOperation(int num1, int num2) {return num1 + num2;}
}// 具体策略类 2
class OperationSubtract implements Strategy {@Overridepublic int doOperation(int num1, int num2) {return num1 - num2;}
}// 上下文类
class Context {private Strategy strategy;public Context(Strategy strategy) {this.strategy = strategy;}public int executeStrategy(int num1, int num2) {return strategy.doOperation(num1, num2);}
}// 使用示例
public class Main {public static void main(String[] args) {Context context = new Context(new OperationAdd());System.out.println("10 + 5 = " + context.executeStrategy(10, 5));context = new Context(new OperationSubtract());System.out.println("10 - 5 = " + context.executeStrategy(10, 5));}
}
输出:
10 + 5 = 15
10 - 5 = 5
说明:
- 策略模式适用于需要在运行时选择不同算法的场景。
- 将算法封装在独立的类中,便于扩展和维护。
15. 责任链模式(Chain of Responsibility Pattern)
责任链模式使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合。它适用于需要多个对象依次处理请求的场景,例如审批流程、过滤器链等。
代码示例:
// 请求类
class Request {private int amount;public Request(int amount) {this.amount = amount;}public int getAmount() {return amount;}
}// 抽象处理者
abstract class Handler {protected Handler nextHandler;public void setNextHandler(Handler nextHandler) {this.nextHandler = nextHandler;}public abstract void handleRequest(Request request);
}// 具体处理者 1
class TeamLeader extends Handler {@Overridepublic void handleRequest(Request request) {if (request.getAmount() <= 1000) {System.out.println("TeamLeader approved the request of $" + request.getAmount());} else if (nextHandler != null) {nextHandler.handleRequest(request);}}
}// 具体处理者 2
class Manager extends Handler {@Overridepublic void handleRequest(Request request) {if (request.getAmount() <= 5000) {System.out.println("Manager approved the request of $" + request.getAmount());} else if (nextHandler != null) {nextHandler.handleRequest(request);}}
}// 具体处理者 3
class Director extends Handler {@Overridepublic void handleRequest(Request request) {if (request.getAmount() > 5000) {System.out.println("Director approved the request of $" + request.getAmount());} else if (nextHandler != null) {nextHandler.handleRequest(request);}}
}// 使用示例
public class Main {public static void main(String[] args) {Handler teamLeader = new TeamLeader();Handler manager = new Manager();Handler director = new Director();teamLeader.setNextHandler(manager);manager.setNextHandler(director);Request request1 = new Request(800);teamLeader.handleRequest(request1);Request request2 = new Request(3000);teamLeader.handleRequest(request2);Request request3 = new Request(10000);teamLeader.handleRequest(request3);}
}
输出:
TeamLeader approved the request of $800
Manager approved the request of $3000
Director approved the request of $10000
说明:
- 责任链模式适用于需要多个对象依次处理请求的场景。
- 通过链式调用,可以动态调整处理流程。
16. 命令模式(Command Pattern)
命令模式将请求封装为对象,从而使您可以使用不同的请求、队列或日志来参数化其他对象。它适用于需要记录操作、撤销/重做、事务回滚的场景。
代码示例:
// 命令接口
interface Command {void execute();
}// 接收者类
class Light {public void on() {System.out.println("Light is on");}public void off() {System.out.println("Light is off");}
}// 具体命令类 1
class LightOnCommand implements Command {private Light light;public LightOnCommand(Light light) {this.light = light;}@Overridepublic void execute() {light.on();}
}// 具体命令类 2
class LightOffCommand implements Command {private Light light;public LightOffCommand(Light light) {this.light = light;}@Overridepublic void execute() {light.off();}
}// 调用者类
class RemoteControl {private Command command;public void setCommand(Command command) {this.command = command;}public void pressButton() {command.execute();}
}// 使用示例
public class Main {public static void main(String[] args) {Light light = new Light();Command lightOn = new LightOnCommand(light);Command lightOff = new LightOffCommand(light);RemoteControl remote = new RemoteControl();remote.setCommand(lightOn);remote.pressButton();remote.setCommand(lightOff);remote.pressButton();}
}
输出:
Light is on
Light is off
说明:
- 命令模式适用于需要封装请求的场景。
- 可用于实现撤销/重做、事务回滚等功能。
17. 状态模式(State Pattern)
状态模式允许对象在其内部状态改变时改变其行为。它适用于对象的行为依赖于其状态的场景,例如订单状态、游戏角色状态等。
代码示例:
// 状态接口
interface State {void doAction(Context context);
}// 具体状态类 1
class StartState implements State {@Overridepublic void doAction(Context context) {System.out.println("Player is in start state");context.setState(this);}public String toString() {return "Start State";}
}// 具体状态类 2
class StopState implements State {@Overridepublic void doAction(Context context) {System.out.println("Player is in stop state");context.setState(this);}public String toString() {return "Stop State";}
}// 上下文类
class Context {private State state;public void setState(State state) {this.state = state;}public State getState() {return state;}public void doAction() {state.doAction(this);}
}// 使用示例
public class Main {public static void main(String[] args) {Context context = new Context();State startState = new StartState();startState.doAction(context);System.out.println("Current state: " + context.getState());State stopState = new StopState();stopState.doAction(context);System.out.println("Current state: " + context.getState());}
}
输出:
Player is in start state
Current state: Start State
Player is in stop state
Current state: Stop State
说明:
- 状态模式适用于对象的行为依赖于其状态的场景。
- 通过状态对象的变化,可以动态改变对象的行为。
18. 模板方法模式(Template Method Pattern)
模板方法模式定义一个操作中的算法骨架,而将一些步骤延迟到子类中。它适用于需要定义算法框架、但允许子类重写某些步骤的场景,例如测试框架、游戏关卡设计等。
代码示例:
// 抽象类
abstract class Game {abstract void initialize();abstract void startPlay();abstract void endPlay();// 模板方法public final void play() {initialize();startPlay();endPlay();}
}// 具体类 1
class Cricket extends Game {@Overridevoid initialize() {System.out.println("Cricket Game Initialized! Start playing.");}@Overridevoid startPlay() {System.out.println("Cricket Game Started. Enjoy the game!");}@Overridevoid endPlay() {System.out.println("Cricket Game Finished!");}
}// 具体类 2
class Football extends Game {@Overridevoid initialize() {System.out.println("Football Game Initialized! Start playing.");}@Overridevoid startPlay() {System.out.println("Football Game Started. Enjoy the game!");}@Overridevoid endPlay() {System.out.println("Football Game Finished!");}
}// 使用示例
public class Main {public static void main(String[] args) {Game game = new Cricket();game.play();System.out.println();game = new Football();game.play();}
}
输出:
Cricket Game Initialized! Start playing.
Cricket Game Started. Enjoy the game!
Cricket Game Finished!Football Game Initialized! Start playing.
Football Game Started. Enjoy the game!
Football Game Finished!
说明:
- 模板方法模式适用于定义算法框架的场景。
- 子类可以重写部分步骤,但不能改变算法的整体结构。
19. 访问者模式(Visitor Pattern)
访问者模式允许在不修改对象结构的情况下,定义作用于对象的新操作。它适用于需要对一组对象进行不同操作的场景,例如报表生成、数据导出等。
代码示例:
// 元素接口
interface Element {void accept(Visitor visitor);
}// 具体元素类
class ConcreteElementA implements Element {@Overridepublic void accept(Visitor visitor) {visitor.visitConcreteElementA(this);}public String operationA() {return "ConcreteElementA";}
}class ConcreteElementB implements Element {@Overridepublic void accept(Visitor visitor) {visitor.visitConcreteElementB(this);}public String operationB() {return "ConcreteElementB";}
}// 访问者接口
interface Visitor {void visitConcreteElementA(ConcreteElementA element);void visitConcreteElementB(ConcreteElementB element);
}// 具体访问者类
class ConcreteVisitor implements Visitor {@Overridepublic void visitConcreteElementA(ConcreteElementA element) {System.out.println("Visited " + element.operationA());}@Overridepublic void visitConcreteElementB(ConcreteElementB element) {System.out.println("Visited " + element.operationB());}
}// 对象结构类
class ObjectStructure {private List<Element> elements = new ArrayList<>();public void attach(Element element) {elements.add(element);}public void detach(Element element) {elements.remove(element);}public void accept(Visitor visitor) {for (Element element : elements) {element.accept(visitor);}}
}// 使用示例
public class Main {public static void main(String[] args) {ObjectStructure structure = new ObjectStructure();structure.attach(new ConcreteElementA());structure.attach(new ConcreteElementB());Visitor visitor = new ConcreteVisitor();structure.accept(visitor);}
}
输出:
Visited ConcreteElementA
Visited ConcreteElementB
说明:
- 访问者模式适用于需要对一组对象执行不同操作的场景。
- 通过访问者,可以将操作与对象结构分离,提高系统的扩展性。
四、总结与最佳实践
设计模式是软件开发中解决常见问题的经典方案,它们提供了一种可重用的、经过验证的代码结构,使得程序更加灵活、可扩展,并且易于维护。Java 作为一门面向对象的编程语言,广泛支持各种设计模式的应用。
在实际开发中,合理使用设计模式可以提高代码的可读性、可维护性和可扩展性。然而,设计模式并非万能钥匙,过度使用或错误使用设计模式可能会导致代码复杂化,影响性能和可维护性。因此,在使用设计模式时,应遵循以下最佳实践:
- 理解设计模式的本质:设计模式是解决特定问题的通用方案,不应盲目套用。应根据实际需求选择合适的模式。
- 避免过度设计:在项目初期,应优先考虑简单、直接的解决方案,只有在遇到复杂问题时才引入设计模式。
- 结合业务场景:设计模式应服务于业务需求,而非为了使用模式而使用模式。应根据实际业务逻辑选择合适的模式。
- 保持代码简洁:即使使用了设计模式,也应保持代码的简洁性,避免不必要的复杂性。
- 测试设计模式的实现:设计模式的实现应经过充分的测试,确保其符合预期,并不会引入新的问题。
- 文档化设计模式的使用:在团队协作中,应记录设计模式的使用方式,以便其他开发者理解和维护代码。
通过合理使用设计模式,可以提高代码的质量,使系统更加灵活、可扩展,并且易于维护。希望本博客能够帮助读者深入理解 Java 设计模式,并在实际项目中灵活应用这些模式,提高软件开发的效率和质量。