快速复习常见设计模式(以Java为例)

快速复习常见设计模式(以Java为例)

设计模式是解决软件设计问题的经典方案,掌握它们能显著提升代码的可维护性和扩展性。本文以Java为例,快速回顾部分常用GoF设计模式的核心思想与典型应用场景,涵盖创建型(如工厂、单例)、结构型(如适配器、装饰器)和行为型(如观察者、策略)三大类,并通过简洁代码示例展示实现要点。

一、创建型模式

Ⅰ、原型模式(Prototype)

“复印机”:直接复制一个现有的对象,不用从头开始造(比如克隆羊多利,直接复制原版)。

通过克隆现有对象生成新对象,避免重复初始化。

// 实现 Cloneable 接口,支持深拷贝
class Document implements Cloneable {
    private String text;
    private List<String> images = new ArrayList<>();

    public Document clone() throws CloneNotSupportedException {
        Document cloned = (Document) super.clone();
        cloned.images = new ArrayList<>(this.images); // 深拷贝引用对象
        return cloned;
    }

    public void addImage(String image) { images.add(image); }
    public void setText(String text) { this.text = text; }
}

// 使用示例
Document doc1 = new Document();
doc1.setText("Hello");
doc1.addImage("img1.png");
Document doc2 = doc1.clone(); // 克隆对象,避免重新初始化

Ⅱ、建造者模式(Builder)

“分步组装”:就像组装电脑:先选CPU,再选显卡,最后装内存,一步步拼成最终成品,避免一次性塞进所有零件。

分步骤构造复杂对象,解耦构造过程与具体表示。

class User {
    private final String name;     // 必选
    private final int age;        // 可选
    private final String address; // 可选

    // 建造者类
    static class Builder {
        private final String name;
        private int age = 0;
        private String address = "";

        public Builder(String name) { this.name = name; }

        public Builder age(int age) { 
            this.age = age; 
            return this; 
        }

        public Builder address(String address) { 
            this.address = address; 
            return this; 
        }

        public User build() { 
            return new User(this); 
        }
    }

    private User(Builder builder) {
        this.name = builder.name;
        this.age = builder.age;
        this.address = builder.address;
    }
}

// 使用示例(链式调用)
User user = new User.Builder("Alice")
                    .age(30)
                    .address("New York")
                    .build();

Ⅲ、工厂方法模式(Factory Method)

“点单取货”:告诉奶茶店“我要一杯珍珠奶茶”,店员按标准流程做好给你,你不需要关心奶茶具体怎么做的。

定义创建对象的接口,由子类决定实例化的具体类。

// 抽象工厂接口
interface VehicleFactory {
    Vehicle createVehicle();
}

// 具体工厂类
class CarFactory implements VehicleFactory {
    @Override
    public Vehicle createVehicle() {
        return new Car(); // 返回具体产品
    }
}

class BikeFactory implements VehicleFactory {
    @Override
    public Vehicle createVehicle() {
        return new Bike();
    }
}

// 产品接口
interface Vehicle { void drive(); }
class Car implements Vehicle { 
    public void drive() { System.out.println("Driving a car"); } 
}
class Bike implements Vehicle { 
    public void drive() { System.out.println("Riding a bike"); } 
}

// 使用示例
VehicleFactory factory = new CarFactory();
Vehicle vehicle = factory.createVehicle();
vehicle.drive(); // 输出 "Driving a car"

Ⅳ、抽象工厂(Abstract Factory)

“全家桶套餐”:买一套“北欧风家具”(沙发+桌子+柜子),工厂保证风格统一,不用自己一件件挑。

创建一组相关对象家族,屏蔽具体实现类。

// 抽象工厂接口(产品族)
interface GUIFactory {
    Button createButton();
    TextBox createTextBox();
}

// 具体工厂类:Windows 风格
class WinFactory implements GUIFactory {
    public Button createButton() { return new WinButton(); }
    public TextBox createTextBox() { return new WinTextBox(); }
}

// 具体工厂类:Mac 风格
class MacFactory implements GUIFactory {
    public Button createButton() { return new MacButton(); }
    public TextBox createTextBox() { return new MacTextBox(); }
}

// 产品接口
interface Button { void render(); }
interface TextBox { void input(); }

// 具体产品实现
class WinButton implements Button {
    public void render() { System.out.println("Windows style button"); }
}
class MacButton implements Button {
    public void render() { System.out.println("Mac style button"); }
}
// TextBox 实现类似...

// 使用示例
GUIFactory factory = new MacFactory();
Button button = factory.createButton();
button.render(); // 输出 "Mac style button"

Ⅴ、单例模式(Singleton)

“唯一管理员”:整个公司只有一个CEO,谁需要CEO办事都找同一个人,不允许有第二个。

确保类仅有一个实例,并提供全局访问入口。

// 静态内部类实现
class Singleton {
    private Singleton() {}

    private static class Holder {
        static final Singleton INSTANCE = new Singleton();
    }

    public static Singleton getInstance() {
        return Holder.INSTANCE;
    }
}

// 懒加载实现(推荐)
class Singleton {
    private static volatile Singleton instance;

    private Singleton() {} // 私有构造函数

    public static Singleton getInstance() {
        // 双重检查锁实现线程安全
        if (instance == null) {
            synchronized (Singleton.class) {
                if (instance == null) {
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}

// 使用示例
Singleton s1 = Singleton.getInstance();
Singleton s2 = Singleton.getInstance();
System.out.println(s1 == s2); // 输出 true

二、结构型模式

Ⅰ、适配器模式(Adapter)

“转接头”:把Type-C接口转换成USB,让旧手机也能用新耳机(让不兼容的接口能一起工作)。

转换接口使不兼容的类协同工作(类/对象适配)。

// 目标接口(客户端期望的接口)
interface USB {
    void connect();
}

// 被适配的类(原有不兼容的类)
class TypeC {
    public void typeCConnect() {
        System.out.println("Type-C connected");
    }
}

// 类适配器(通过继承实现)
class TypeCToUSBAdapter extends TypeC implements USB {
    @Override
    public void connect() {
        super.typeCConnect(); // 调用原有方法
        System.out.println("Converted to USB");
    }
}

// 对象适配器(通过组合实现,更灵活)
class ObjectAdapter implements USB {
    private TypeC typeC;

    public ObjectAdapter(TypeC typeC) {
        this.typeC = typeC;
    }

    @Override
    public void connect() {
        typeC.typeCConnect();
        System.out.println("Converted to USB");
    }
}

// 使用示例
USB adapter = new TypeCToUSBAdapter();
adapter.connect(); // 输出 "Type-C connected" → "Converted to USB"

Ⅱ、装饰器模式(Decorator)

“叠Buff”:给咖啡加糖、加奶、加巧克力,一层层包装,让基础咖啡变豪华版,但咖啡还是那杯咖啡。

动态包装对象以扩展功能,替代继承的灵活方案。

// 基础组件接口
interface Coffee {
    String getDescription();
    double cost();
}

// 具体组件
class SimpleCoffee implements Coffee {
    public String getDescription() { return "Coffee"; }
    public double cost() { return 2.0; }
}

// 装饰器抽象类(关键:实现组件接口并持有组件对象)
abstract class CoffeeDecorator implements Coffee {
    protected Coffee decoratedCoffee;

    public CoffeeDecorator(Coffee coffee) {
        this.decoratedCoffee = coffee;
    }

    public String getDescription() {
        return decoratedCoffee.getDescription();
    }

    public double cost() {
        return decoratedCoffee.cost();
    }
}

// 具体装饰器:添加牛奶
class MilkDecorator extends CoffeeDecorator {
    public MilkDecorator(Coffee coffee) {
        super(coffee);
    }

    @Override
    public String getDescription() {
        return super.getDescription() + ", Milk";
    }

    @Override
    public double cost() {
        return super.cost() + 0.5;
    }
}

// 使用示例
Coffee coffee = new SimpleCoffee();
coffee = new MilkDecorator(coffee);
System.out.println(coffee.getDescription()); // "Coffee, Milk"
System.out.println(coffee.cost()); // 2.5

Ⅲ、代理模式(Proxy)

“代购”:想买国外商品?找个代购帮你买(代理),代购可能还会帮你验货、包邮,但最终拿到的是你要的东西。

为对象提供代理,控制访问并附加额外逻辑(如延迟加载)。

// 抽象主题接口
interface Image {
    void display();
}

// 真实主题(延迟加载)
class RealImage implements Image {
    private String filename;

    public RealImage(String filename) {
        this.filename = filename;
        loadFromDisk(); // 初始化时加载资源
    }

    private void loadFromDisk() {
        System.out.println("Loading image: " + filename);
    }

    public void display() {
        System.out.println("Displaying image: " + filename);
    }
}

// 代理类(控制访问并延迟创建真实对象)
class ProxyImage implements Image {
    private String filename;
    private RealImage realImage;

    public ProxyImage(String filename) {
        this.filename = filename;
    }

    public void display() {
        if (realImage == null) {
            realImage = new RealImage(filename); // 按需创建真实对象
        }
        realImage.display();
    }
}

// 使用示例
Image image = new ProxyImage("photo.jpg");
image.display(); // 第一次调用时加载并显示
image.display(); // 直接使用已加载对象

Ⅳ、外观模式(Facade)

“一键操作”:开空调只需按“制冷模式”,不用管背后压缩机、风扇怎么协作,简化复杂操作。

简化复杂子系统的接口,提供统一的高层入口。

// 复杂子系统类
class CPU {
    public void start() { System.out.println("CPU started"); }
}
class Memory {
    public void load() { System.out.println("Memory loaded"); }
}
class HardDrive {
    public void read() { System.out.println("HardDrive read"); }
}

// 外观类
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 ready!");
    }
}

// 使用示例
ComputerFacade computer = new ComputerFacade();
computer.startComputer(); // 输出子系统的启动步骤

Ⅴ、组合模式(Composite)

“套娃文件夹”:文件夹里可以放文件,也可以放子文件夹,统一当成“文件”处理,方便递归操作。

以树形结构统一处理单个对象和对象组合的层次关系。

// 抽象组件(统一处理叶子节点和组合节点)
interface FileSystemComponent {
    void showDetails();
}

// 叶子节点(文件)
class File implements FileSystemComponent {
    private String name;

    public File(String name) { this.name = name; }

    public void showDetails() {
        System.out.println("File: " + name);
    }
}

// 组合节点(文件夹)
class Folder implements FileSystemComponent {
    private String name;
    private List<FileSystemComponent> children = new ArrayList<>();

    public Folder(String name) { this.name = name; }

    public void add(FileSystemComponent component) {
        children.add(component);
    }

    public void showDetails() {
        System.out.println("Folder: " + name);
        for (FileSystemComponent child : children) {
            child.showDetails(); // 递归调用子节点
        }
    }
}

// 使用示例
Folder root = new Folder("Root");
root.add(new File("file1.txt"));

Folder subFolder = new Folder("Sub");
subFolder.add(new File("file2.txt"));
root.add(subFolder);

root.showDetails(); // 递归展示所有节点

三、行为模式

Ⅰ、观察者模式(Observer)

“微信群通知”:老板在群里发消息,所有员工自动收到提醒(一个发布者,多个订阅者自动同步)。

一对多的依赖关系,状态变更时自动通知所有订阅者。

// 主题(被观察者)
interface Subject {
    void addObserver(Observer o);
    void notifyObservers(String message);
}

// 具体主题
class NewsAgency implements Subject {
    private List<Observer> observers = new ArrayList<>();

    public void addObserver(Observer o) { observers.add(o); }

    public void notifyObservers(String message) {
        for (Observer o : observers) {
            o.update(message); // 通知所有观察者
        }
    }

    public void publishNews(String news) {
        notifyObservers(news); // 触发通知
    }
}

// 观察者接口
interface Observer {
    void update(String message);
}

// 具体观察者
class Subscriber implements Observer {
    private String name;
    public Subscriber(String name) { this.name = name; }

    public void update(String message) {
        System.out.println(name + " received news: " + message);
    }
}

// 使用示例
NewsAgency agency = new NewsAgency();
agency.addObserver(new Subscriber("Alice"));
agency.addObserver(new Subscriber("Bob"));
agency.publishNews("Java 21 released!"); // 所有订阅者收到通知

Ⅱ、策略模式(Strategy)

“导航路线切换”:开车时,导航软件可以选“最快路线”“避开高速”“省钱路线”,随时切换策略,但目的地不变。

封装可互换的算法族,运行时动态选择行为逻辑。

// 策略接口
interface PaymentStrategy {
    void pay(int amount);
}

// 具体策略类:信用卡支付
class CreditCardPayment implements PaymentStrategy {
    private String cardNumber;
    public CreditCardPayment(String cardNumber) { this.cardNumber = cardNumber; }

    public void pay(int amount) {
        System.out.println("Paid $" + amount + " via Credit Card: " + cardNumber);
    }
}

// 具体策略类:Paypal电子支付
class PayPalPayment implements PaymentStrategy {
    private String email;
    public PayPalPayment(String email) { this.email = email; }

    public void pay(int amount) {
        System.out.println("Paid $" + amount + " via PayPal: " + email);
    }
}

// 上下文类(动态切换策略)
class ShoppingCart {
    private PaymentStrategy strategy;

    public void setPaymentStrategy(PaymentStrategy strategy) {
        this.strategy = strategy;
    }

    public void checkout(int amount) {
        strategy.pay(amount); // 委托给具体策略
    }
}

// 使用示例
ShoppingCart cart = new ShoppingCart();
cart.setPaymentStrategy(new CreditCardPayment("1234-5678"));
cart.checkout(100); // 输出信用卡支付信息

Ⅲ、命令模式(Command)

“点餐小票”:顾客点菜后,服务员把小票交给厨房,厨房按顺序做菜;支持撤销(退菜)或重做(加菜)。

将请求封装为对象,支持撤销、队列化等操作。

// 命令接口
interface Command {
    void execute();
}

// 具体命令(绑定操作与接收者)
class LightOnCommand implements Command {
    private Light light;

    public LightOnCommand(Light light) { this.light = light; }

    public void execute() {
        light.turnOn(); // 调用接收者的实际方法
    }
}

// 接收者(真正执行操作的对象)
class Light {
    public void turnOn() { System.out.println("Light is ON"); }
    public void turnOff() { System.out.println("Light is OFF"); }
}

// 调用者(触发命令的对象)
class RemoteControl {
    private Command command;

    public void setCommand(Command command) {
        this.command = command;
    }

    public void pressButton() {
        command.execute(); // 执行命令
    }
}

// 使用示例(Template Method)
Light light = new Light();
RemoteControl remote = new RemoteControl();
remote.setCommand(new LightOnCommand(light));
remote.pressButton(); // 输出 "Light is ON"

Ⅳ、模板方法(Template Method)

“填空题”:写作文的模板:开头固定用“在一个夜黑风高的夜晚…”,中间自己填故事,结尾固定“这就是我的经历”。

定义算法骨架,子类重写特定步骤而不改变结构。

// 抽象类定义算法骨架
abstract class Game {
    // 模板方法(final 防止子类覆盖)
    public final void play() {
        initialize();
        startPlay();
        endPlay();
    }

    // 具体步骤由子类实现
    abstract void initialize();
    abstract void startPlay();

    // 可选默认实现
    void endPlay() {
        System.out.println("Game ended");
    }
}

// 具体子类
class Chess extends Game {
    void initialize() { System.out.println("Chess initialized"); }
    void startPlay() { System.out.println("Chess started"); }
}

class Soccer extends Game {
    void initialize() { System.out.println("Soccer field ready"); }
    void startPlay() { System.out.println("Soccer match started"); }
}

// 使用示例
Game game = new Chess();
game.play(); // 按固定顺序执行:initialize → startPlay → endPlay

Ⅴ、状态模式(State)

“自动售货机”:投币后按钮才亮(状态变化),没投币时按按钮无效(行为随状态改变)。

对象内部状态改变时,动态调整其行为表现。

// 状态接口
interface State {
    void handle(Context context);
}

// 具体状态类
class StateA implements State {
    public void handle(Context context) {
        System.out.println("Handling in State A");
        context.setState(new StateB()); // 切换到下一个状态
    }
}

class StateB implements State {
    public void handle(Context context) {
        System.out.println("Handling in State B");
        context.setState(new StateA()); // 切换回前一个状态
    }
}

// 上下文类(持有状态对象)
class Context {
    private State state;

    public Context(State initialState) { this.state = initialState; }

    public void setState(State state) { this.state = state; }

    public void request() {
        state.handle(this); // 委托给当前状态处理
    }
}

// 使用示例
Context context = new Context(new StateA());
context.request(); // 输出 "Handling in State A",状态变为 StateB
context.request(); // 输出 "Handling in State B",状态变回 StateA

延伸阅读

  1. 设计模式目录:22种设计模式
  2. JAVA设计模式总结之23种设计模式
  3. 设计模式 - 廖雪峰的官方网站
posted @ 2025-05-24 22:19  TfiyuenLau  阅读(35)  评论(0)    收藏  举报