设计模式(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 {
@Override
public void draw() {
System.out.println("Drawing Circle");
}
}
class Square implements Shape {
@Override
public 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 {
@Override
public void render() {
System.out.println("Render a button in Windows style.");
}
}
// 具体产品 B1
class WindowsCheckbox implements Checkbox {
@Override
public void render() {
System.out.println("Render a checkbox in Windows style.");
}
}
// 具体产品 A2
class MacButton implements Button {
@Override
public void render() {
System.out.println("Render a button in Mac style.");
}
}
// 具体产品 B2
class MacCheckbox implements Checkbox {
@Override
public void render() {
System.out.println("Render a checkbox in Mac style.");
}
}
// 抽象工厂
interface GUIFactory {
Button createButton();
Checkbox createCheckbox();
}
// 具体工厂 1
class WindowsFactory implements GUIFactory {
@Override
public Button createButton() {
return new WindowsButton();
}
@Override
public Checkbox createCheckbox() {
return new WindowsCheckbox();
}
}
// 具体工厂 2
class MacFactory implements GUIFactory {
@Override
public Button createButton() {
return new MacButton();
}
@Override
public 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"; // 假设当前操作系统为 Mac
GUIFactory 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;
}
@Override
public 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();
}
@Override
public void buildCPU() {
computer.setCPU("Intel i9");
}
@Override
public void buildRAM() {
computer.setRAM("32GB");
}
@Override
public void buildStorage() {
computer.setStorage("1TB SSD");
}
@Override
public 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;
}
@Override
protected 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 的数据,不影响 prototype1
prototype2.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 {
@Override
public 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 {
@Override
public void playVlc(String fileName) {
System.out.println("Playing VLC file: " + fileName);
}
@Override
public void playMp4(String fileName) {
// 不支持
}
}
class Mp4Player implements AdvancedMediaPlayer {
@Override
public void playVlc(String fileName) {
// 不支持
}
@Override
public 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();
}
}
@Override
public 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);
}
@Override
public void display() {
System.out.println("Displaying " + fileName);
}
}
// 代理类
class ProxyImage implements Image {
private RealImage realImage;
private String fileName;
public ProxyImage(String fileName) {
this.fileName = fileName;
}
@Override
public 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 {
@Override
public double cost() {
return 2.0;
}
@Override
public String description() {
return "Simple Coffee";
}
}
// 装饰器抽象类
abstract class CoffeeDecorator implements Coffee {
protected Coffee decoratedCoffee;
public CoffeeDecorator(Coffee coffee) {
this.decoratedCoffee = coffee;
}
@Override
public double cost() {
return decoratedCoffee.cost();
}
@Override
public String description() {
return decoratedCoffee.description();
}
}
// 具体装饰器 1
class MilkDecorator extends CoffeeDecorator {
public MilkDecorator(Coffee coffee) {
super(coffee);
}
@Override
public double cost() {
return super.cost() + 0.5;
}
@Override
public String description() {
return super.description() + ", Milk";
}
}
// 具体装饰器 2
class SugarDecorator extends CoffeeDecorator {
public SugarDecorator(Coffee coffee) {
super(coffee);
}
@Override
public double cost() {
return super.cost() + 0.2;
}
@Override
public 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;
}
@Override
public 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);
}
@Override
public 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 {
@Override
public void operationImpl() {
System.out.println("ConcreteImplementorA operation");
}
}
// 具体实现类 B
class ConcreteImplementorB implements Implementor {
@Override
public 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);
}
@Override
void 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;
}
@Override
public 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;
@Override
public void registerObserver(Observer observer) {
observers.add(observer);
}
@Override
public void removeObserver(Observer observer) {
observers.remove(observer);
}
@Override
public 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;
@Override
public 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 {
@Override
public int doOperation(int num1, int num2) {
return num1 + num2;
}
}
// 具体策略类 2
class OperationSubtract implements Strategy {
@Override
public 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 {
@Override
public 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 {
@Override
public 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 {
@Override
public 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;
}
@Override
public void execute() {
light.on();
}
}
// 具体命令类 2
class LightOffCommand implements Command {
private Light light;
public LightOffCommand(Light light) {
this.light = light;
}
@Override
public 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 {
@Override
public 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 {
@Override
public 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 {
@Override
void initialize() {
System.out.println("Cricket Game Initialized! Start playing.");
}
@Override
void startPlay() {
System.out.println("Cricket Game Started. Enjoy the game!");
}
@Override
void endPlay() {
System.out.println("Cricket Game Finished!");
}
}
// 具体类 2
class Football extends Game {
@Override
void initialize() {
System.out.println("Football Game Initialized! Start playing.");
}
@Override
void startPlay() {
System.out.println("Football Game Started. Enjoy the game!");
}
@Override
void 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 {
@Override
public void accept(Visitor visitor) {
visitor.visitConcreteElementA(this);
}
public String operationA() {
return "ConcreteElementA";
}
}
class ConcreteElementB implements Element {
@Override
public 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 {
@Override
public void visitConcreteElementA(ConcreteElementA element) {
System.out.println("Visited " + element.operationA());
}
@Override
public 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 设计模式,并在实际项目中灵活应用这些模式,提高软件开发的效率和质量。