快速复习常见设计模式(以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
延伸阅读
本文来自博客园,作者:TfiyuenLau,转载请注明原文链接:https://www.cnblogs.com/tfiyuenlau/articles/18894770

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