🌟 前言
在软件开发的漫长旅程中,我们常常会面临这样的困境:代码随着需求的变化而变得越来越复杂,新功能的添加如同在摇摇欲坠的积木塔上再放一块积木,稍有不慎就会导致整个系统的崩溃。维护成本呈指数级增长,团队协作效率不断下降,技术债务如影随形——这似乎是许多软件项目难以逃脱的命运。
然而,总有一些卓越的软件系统能够经受住时间的考验,在频繁的需求变更和技术演进中依然保持清晰的架构和良好的可维护性。它们的秘密何在?
答案就藏在我们即将深入探讨的设计模式之中。
设计模式并非银弹,也不是可以生搬硬套的魔法公式。它们是经过验证的解决方案模板,是无数优秀工程师在解决特定类型问题时积累的智慧结晶。正如建筑大师克里斯托弗·亚历山大在《建筑模式语言》中所说:
"每一种模式都描述了在我们环境中反复出现的问题,并描述了该问题解决方案的核心,这样你就可以无数次地使用该解决方案,而无需以相同的方式重复两次。"
在软件领域,GoF(Gang of Four)的《设计模式:可复用面向对象软件的基础》首次系统性地整理了23种经典设计模式,为整个行业建立了共同的设计词汇和思维框架。
《Head First设计模式》以其独特的教学方式,让这个看似枯燥的主题变得生动有趣。本书不是一本传统的技术参考手册,而是一次深入设计模式核心的思想之旅。
通过系统学习设计模式,你将能够掌握核心设计原则、识别设计问题、构建弹性架构、提升沟通效率,并培养出对优秀软件设计的敏锐感知和判断力。
准备好改变你编写代码的方式了吗?让我们开始这段精彩的旅程!
🧠 设计模式深度解析:从策略模式到复合模式
🧩 第1章:策略模式
什么是策略模式?
策略模式定义了一系列算法,并将每一个算法封装起来,使它们可以互相替换。策略模式让算法的变化独立于使用算法的客户。
核心思想
在鸭子模拟器的例子中,我们发现不是所有的鸭子都会飞或会叫。如果使用继承,会导致代码重复和难以维护。策略模式通过以下方式解决:
- 将变化的行为抽象为接口
- 通过组合而非继承来使用行为
- 允许在运行时动态改变行为
完整结构图
classDiagram
class Duck {
<<abstract>>
+FlyBehavior flyBehavior
+QuackBehavior quackBehavior
+performQuack()
+performFly()
+swim()
+setFlyBehavior(FlyBehavior)
+setQuackBehavior(QuackBehavior)
+display()*
}
class FlyBehavior {
<<interface>>
+fly()*
}
class QuackBehavior {
<<interface>>
+quack()*
}
class FlyWithWings {
+fly()
}
class FlyNoWay {
+fly()
}
class FlyRocketPowered {
+fly()
}
class Quack {
+quack()
}
class Squeak {
+quack()
}
class MuteQuack {
+quack()
}
class MallardDuck {
+display()
}
class ModelDuck {
+display()
}
Duck <|-- MallardDuck
Duck <|-- ModelDuck
Duck --> FlyBehavior
Duck --> QuackBehavior
FlyWithWings ..|> FlyBehavior
FlyNoWay ..|> FlyBehavior
FlyRocketPowered ..|> FlyBehavior
Quack ..|> QuackBehavior
Squeak ..|> QuackBehavior
MuteQuack ..|> QuackBehavior
代码实现
// 行为接口
public interface FlyBehavior {
void fly();
}
public interface QuackBehavior {
void quack();
}
// 具体行为实现
public class FlyWithWings implements FlyBehavior {
public void fly() {
System.out.println("I'm flying!!");
}
}
public class FlyNoWay implements FlyBehavior {
public void fly() {
System.out.println("I can't fly");
}
}
public class FlyRocketPowered implements FlyBehavior {
public void fly() {
System.out.println("I'm flying with a rocket!");
}
}
// 鸭子基类
public abstract class Duck {
FlyBehavior flyBehavior;
QuackBehavior quackBehavior;
public Duck() {}
public abstract void display();
public void performFly() {
flyBehavior.fly();
}
public void performQuack() {
quackBehavior.quack();
}
public void swim() {
System.out.println("All ducks float, even decoys!");
}
public void setFlyBehavior(FlyBehavior fb) {
flyBehavior = fb;
}
public void setQuackBehavior(QuackBehavior qb) {
quackBehavior = qb;
}
}
// 具体鸭子类
public class MallardDuck extends Duck {
public MallardDuck() {
quackBehavior = new Quack();
flyBehavior = new FlyWithWings();
}
public void display() {
System.out.println("I'm a real Mallard duck");
}
}
public class ModelDuck extends Duck {
public ModelDuck() {
flyBehavior = new FlyNoWay();
quackBehavior = new Quack();
}
public void display() {
System.out.println("I'm a model duck");
}
}
测试代码
public class MiniDuckSimulator {
public static void main(String[] args) {
Duck mallard = new MallardDuck();
mallard.performQuack();
mallard.performFly();
Duck model = new ModelDuck();
model.performFly();
model.setFlyBehavior(new FlyRocketPowered());
model.performFly();
}
}
设计原则应用
- 封装变化:将飞行和叫声行为封装成独立的类
- 多用组合,少用继承:通过组合使用行为对象
- 针对接口编程:使用FlyBehavior和QuackBehavior接口
- 开闭原则:对扩展开放,对修改关闭
🧩 第2章:观察者模式
什么是观察者模式?
观察者模式定义了对象之间的一对多依赖关系,当一个对象改变状态时,所有依赖它的对象都会收到通知并自动更新。
气象站应用场景
气象站需要将气象数据实时推送给多个显示设备(当前状况、统计信息、天气预报等),观察者模式完美解决了这种一对多的通知需求。
结构图
classDiagram
class Subject {
<<interface>>
+registerObserver(Observer)
+removeObserver(Observer)
+notifyObservers()
}
class Observer {
<<interface>>
+update(float, float, float)
}
class DisplayElement {
<<interface>>
+display()
}
class WeatherData {
-observers: List~Observer~
-temperature: float
-humidity: float
-pressure: float
+registerObserver(Observer)
+removeObserver(Observer)
+notifyObservers()
+measurementsChanged()
+setMeasurements(float, float, float)
}
class CurrentConditionsDisplay {
-temperature: float
-humidity: float
-weatherData: Subject
+update(float, float, float)
+display()
}
class StatisticsDisplay {
-maxTemp: float
-minTemp: float
-tempSum: float
-numReadings: int
+update(float, float, float)
+display()
}
class ForecastDisplay {
-currentPressure: float
-lastPressure: float
+update(float, float, float)
+display()
}
Subject <|.. WeatherData
Observer <|.. CurrentConditionsDisplay
Observer <|.. StatisticsDisplay
Observer <|.. ForecastDisplay
DisplayElement <|.. CurrentConditionsDisplay
DisplayElement <|.. StatisticsDisplay
DisplayElement <|.. ForecastDisplay
CurrentConditionsDisplay --> Subject
代码实现
// 主题接口
public interface Subject {
void registerObserver(Observer o);
void removeObserver(Observer o);
void notifyObservers();
}
// 观察者接口
public interface Observer {
void update(float temp, float humidity, float pressure);
}
// 显示元素接口
public interface DisplayElement {
void display();
}
// 具体主题
public class WeatherData implements Subject {
private List<Observer> observers;
private float temperature;
private float humidity;
private float pressure;
public WeatherData() {
observers = new ArrayList<>();
}
public void registerObserver(Observer o) {
observers.add(o);
}
public void removeObserver(Observer o) {
observers.remove(o);
}
public void notifyObservers() {
for (Observer observer : observers) {
observer.update(temperature, humidity, pressure);
}
}
public void measurementsChanged() {
notifyObservers();
}
public void setMeasurements(float temperature, float humidity, float pressure) {
this.temperature = temperature;
this.humidity = humidity;
this.pressure = pressure;
measurementsChanged();
}
}
// 具体观察者
public class CurrentConditionsDisplay implements Observer, DisplayElement {
private float temperature;
private float humidity;
private Subject weatherData;
public CurrentConditionsDisplay(Subject weatherData) {
this.weatherData = weatherData;
weatherData.registerObserver(this);
}
public void update(float temperature, float humidity, float pressure) {
this.temperature = temperature;
this.humidity = humidity;
display();
}
public void display() {
System.out.println("Current conditions: " + temperature
+ "F degrees and " + humidity + "% humidity");
}
}
Java内置观察者支持
Java提供了java.util.Observable类和java.util.Observer接口:
public class WeatherData extends Observable {
private float temperature;
private float humidity;
private float pressure;
public WeatherData() {}
public void measurementsChanged() {
setChanged();
notifyObservers();
}
public void setMeasurements(float temperature, float humidity, float pressure) {
this.temperature = temperature;
this.humidity = humidity;
this.pressure = pressure;
measurementsChanged();
}
public float getTemperature() { return temperature; }
public float getHumidity() { return humidity; }
public float getPressure() { return pressure; }
}
public class CurrentConditionsDisplay implements Observer, DisplayElement {
Observable observable;
private float temperature;
private float humidity;
public CurrentConditionsDisplay(Observable observable) {
this.observable = observable;
observable.addObserver(this);
}
public void update(Observable obs, Object arg) {
if (obs instanceof WeatherData) {
WeatherData weatherData = (WeatherData)obs;
this.temperature = weatherData.getTemperature();
this.humidity = weatherData.getHumidity();
display();
}
}
}
设计原则
- 松耦合:主题和观察者之间松耦合,可以独立变化
- 针对接口编程:使用Subject和Observer接口
- 封装变化:将通知机制封装在主题中
🧩 第3章:装饰者模式
什么是装饰者模式?
装饰者模式动态地将责任附加到对象上。若要扩展功能,装饰者提供了比继承更有弹性的替代方案。
星巴兹咖啡案例
咖啡店需要为咖啡添加各种调料(摩卡、奶泡、豆浆等),如果使用继承会导致类爆炸问题。
结构图
classDiagram
class Beverage {
<<abstract>>
+description: String
+getDescription()
+cost()*
}
class CondimentDecorator {
<<abstract>>
+getDescription()*
}
class Espresso {
+cost()
}
class HouseBlend {
+cost()
}
class DarkRoast {
+cost()
}
class Mocha {
-beverage: Beverage
+getDescription()
+cost()
}
class Soy {
-beverage: Beverage
+getDescription()
+cost()
}
class Whip {
-beverage: Beverage
+getDescription()
+cost()
}
CondimentDecorator --|> Beverage
Espresso --|> Beverage
HouseBlend --|> Beverage
DarkRoast --|> Beverage
Mocha --|> CondimentDecorator
Soy --|> CondimentDecorator
Whip --|> CondimentDecorator
Mocha --> Beverage
Soy --> Beverage
Whip --> Beverage
代码实现
// 组件
public abstract class Beverage {
String description = "Unknown Beverage";
public String getDescription() {
return description;
}
public abstract double cost();
}
// 装饰者抽象类
public abstract class CondimentDecorator extends Beverage {
public abstract String getDescription();
}
// 具体组件
public class Espresso extends Beverage {
public Espresso() {
description = "Espresso";
}
public double cost() {
return 1.99;
}
}
public class HouseBlend extends Beverage {
public HouseBlend() {
description = "House Blend Coffee";
}
public double cost() {
return 0.89;
}
}
// 具体装饰者
public class Mocha extends CondimentDecorator {
Beverage beverage;
public Mocha(Beverage beverage) {
this.beverage = beverage;
}
public String getDescription() {
return beverage.getDescription() + ", Mocha";
}
public double cost() {
return 0.20 + beverage.cost();
}
}
public class Whip extends CondimentDecorator {
Beverage beverage;
public Whip(Beverage beverage) {
this.beverage = beverage;
}
public String getDescription() {
return beverage.getDescription() + ", Whip";
}
public double cost() {
return 0.10 + beverage.cost();
}
}
使用示例
public class StarbuzzCoffee {
public static void main(String args[]) {
Beverage beverage = new Espresso();
System.out.println(beverage.getDescription() + " $" + beverage.cost());
Beverage beverage2 = new DarkRoast();
beverage2 = new Mocha(beverage2);
beverage2 = new Mocha(beverage2);
beverage2 = new Whip(beverage2);
System.out.println(beverage2.getDescription() + " $" + beverage2.cost());
Beverage beverage3 = new HouseBlend();
beverage3 = new Soy(beverage3);
beverage3 = new Mocha(beverage3);
beverage3 = new Whip(beverage3);
System.out.println(beverage3.getDescription() + " $" + beverage3.cost());
}
}
Java I/O中的装饰者模式
Java I/O大量使用装饰者模式:
// 装饰文件输入流,添加缓冲和转小写功能
InputStream in = new LowerCaseInputStream(
new BufferedInputStream(
new FileInputStream("test.txt")));
public class LowerCaseInputStream extends FilterInputStream {
public LowerCaseInputStream(InputStream in) {
super(in);
}
public int read() throws IOException {
int c = super.read();
return (c == -1 ? c : Character.toLowerCase((char)c));
}
}
设计原则
- 开闭原则:对扩展开放,对修改关闭
- 组合优于继承:通过组合动态添加功能
- 单一职责:每个装饰者只负责一个功能
🧩 第4章:工厂模式
工厂模式的三种形式
- 简单工厂:一个方法创建所有对象
- 工厂方法:让子类决定实例化哪个类
- 抽象工厂:创建相关对象家族
简单工厂模式
public class SimplePizzaFactory {
public Pizza createPizza(String type) {
Pizza pizza = null;
if (type.equals("cheese")) {
pizza = new CheesePizza();
} else if (type.equals("pepperoni")) {
pizza = new PepperoniPizza();
} else if (type.equals("clam")) {
pizza = new ClamPizza();
} else if (type.equals("veggie")) {
pizza = new VeggiePizza();
}
return pizza;
}
}
工厂方法模式
结构图
classDiagram
class PizzaStore {
<<abstract>>
+orderPizza(String)
+createPizza(String)*
}
class Pizza {
<<abstract>>
+name: String
+dough: String
+sauce: String
+toppings: List~String~
+prepare()
+bake()
+cut()
+box()
+getName()
}
class NYPizzaStore {
+createPizza(String)
}
class ChicagoPizzaStore {
+createPizza(String)
}
class CheesePizza {
+prepare()
}
class NYStyleCheesePizza {
+prepare()
}
class ChicagoStyleCheesePizza {
+prepare()
}
PizzaStore <|-- NYPizzaStore
PizzaStore <|-- ChicagoPizzaStore
Pizza <|-- CheesePizza
Pizza <|-- NYStyleCheesePizza
Pizza <|-- ChicagoStyleCheesePizza
NYPizzaStore --> NYStyleCheesePizza
ChicagoPizzaStore --> ChicagoStyleCheesePizza
代码实现
public abstract class PizzaStore {
public Pizza orderPizza(String type) {
Pizza pizza = createPizza(type);
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
return pizza;
}
protected abstract Pizza createPizza(String type);
}
public class NYPizzaStore extends PizzaStore {
protected Pizza createPizza(String item) {
if (item.equals("cheese")) {
return new NYStyleCheesePizza();
} else if (item.equals("veggie")) {
return new NYStyleVeggiePizza();
} else if (item.equals("clam")) {
return new NYStyleClamPizza();
} else if (item.equals("pepperoni")) {
return new NYStylePepperoniPizza();
} else return null;
}
}
public class ChicagoPizzaStore extends PizzaStore {
protected Pizza createPizza(String item) {
if (item.equals("cheese")) {
return new ChicagoStyleCheesePizza();
} else if (item.equals("veggie")) {
return new ChicagoStyleVeggiePizza();
} else if (item.equals("clam")) {
return new ChicagoStyleClamPizza();
} else if (item.equals("pepperoni")) {
return new ChicagoStylePepperoniPizza();
} else return null;
}
}
抽象工厂模式
结构图
classDiagram
class PizzaIngredientFactory {
<<interface>>
+createDough()
+createSauce()
+createCheese()
+createVeggies()
+createPepperoni()
+createClam()
}
class NYPizzaIngredientFactory {
+createDough()
+createSauce()
+createCheese()
+createVeggies()
+createPepperoni()
+createClam()
}
class Dough {
<<interface>>
}
class Sauce {
<<interface>>
}
class Cheese {
<<interface>>
}
class ThinCrustDough {
}
class MarinaraSauce {
}
class ReggianoCheese {
}
PizzaIngredientFactory <|.. NYPizzaIngredientFactory
Dough <|.. ThinCrustDough
Sauce <|.. MarinaraSauce
Cheese <|.. ReggianoCheese
NYPizzaIngredientFactory --> ThinCrustDough
NYPizzaIngredientFactory --> MarinaraSauce
NYPizzaIngredientFactory --> ReggianoCheese
代码实现
public interface PizzaIngredientFactory {
Dough createDough();
Sauce createSauce();
Cheese createCheese();
Veggies[] createVeggies();
Pepperoni createPepperoni();
Clams createClam();
}
public class NYPizzaIngredientFactory implements PizzaIngredientFactory {
public Dough createDough() {
return new ThinCrustDough();
}
public Sauce createSauce() {
return new MarinaraSauce();
}
public Cheese createCheese() {
return new ReggianoCheese();
}
public Veggies[] createVeggies() {
Veggies veggies[] = { new Garlic(), new Onion(), new Mushroom(), new RedPepper() };
return veggies;
}
public Pepperoni createPepperoni() {
return new SlicedPepperoni();
}
public Clams createClam() {
return new FreshClams();
}
}
public abstract class Pizza {
String name;
Dough dough;
Sauce sauce;
Veggies veggies[];
Cheese cheese;
Pepperoni pepperoni;
Clams clam;
abstract void prepare();
void bake() { /* 实现 */ }
void cut() { /* 实现 */ }
void box() { /* 实现 */ }
void setName(String name) { this.name = name; }
String getName() { return name; }
}
public class CheesePizza extends Pizza {
PizzaIngredientFactory ingredientFactory;
public CheesePizza(PizzaIngredientFactory ingredientFactory) {
this.ingredientFactory = ingredientFactory;
}
void prepare() {
System.out.println("Preparing " + name);
dough = ingredientFactory.createDough();
sauce = ingredientFactory.createSauce();
cheese = ingredientFactory.createCheese();
}
}
设计原则
- 依赖倒置原则:依赖抽象,不依赖具体类
- 开闭原则:对扩展开放,对修改关闭
- 单一职责:将对象创建与使用分离
🧩 第5章:单件模式
什么是单件模式?
单件模式确保一个类只有一个实例,并提供一个全局访问点。
结构图
classDiagram
class Singleton {
-static uniqueInstance: Singleton
-Singleton()
+static getInstance() Singleton
+otherUsefulMethods()
}
代码实现
public class Singleton {
private static Singleton uniqueInstance;
private Singleton() {}
public static Singleton getInstance() {
if (uniqueInstance == null) {
uniqueInstance = new Singleton();
}
return uniqueInstance;
}
// 其他有用方法
public void otherUsefulMethods() {
// 实现
}
}
处理多线程
// 方法1:同步getInstance方法
public class Singleton {
private static Singleton uniqueInstance;
private Singleton() {}
public static synchronized Singleton getInstance() {
if (uniqueInstance == null) {
uniqueInstance = new Singleton();
}
return uniqueInstance;
}
}
// 方法2:急切创建实例
public class Singleton {
private static Singleton uniqueInstance = new Singleton();
private Singleton() {}
public static Singleton getInstance() {
return uniqueInstance;
}
}
// 方法3:双重检查加锁
public class Singleton {
private volatile static Singleton uniqueInstance;
private Singleton() {}
public static Singleton getInstance() {
if (uniqueInstance == null) {
synchronized (Singleton.class) {
if (uniqueInstance == null) {
uniqueInstance = new Singleton();
}
}
}
return uniqueInstance;
}
}
🧩 第6章:命令模式
什么是命令模式?
命令模式将请求封装成对象,以便使用不同的请求、队列或日志来参数化其他对象。
结构图
classDiagram
class Command {
<<interface>>
+execute()
+undo()
}
class Light {
+on()
+off()
}
class LightOnCommand {
-light: Light
+execute()
+undo()
}
class RemoteControl {
-onCommands: Command[]
-offCommands: Command[]
+setCommand(int, Command, Command)
+onButtonWasPushed(int)
+offButtonWasPushed(int)
+undoButtonWasPushed()
}
Command <|.. LightOnCommand
LightOnCommand --> Light
RemoteControl --> Command
代码实现
public interface Command {
void execute();
void undo();
}
public class LightOnCommand implements Command {
Light light;
public LightOnCommand(Light light) {
this.light = light;
}
public void execute() {
light.on();
}
public void undo() {
light.off();
}
}
public class RemoteControl {
Command[] onCommands;
Command[] offCommands;
Command undoCommand;
public RemoteControl() {
onCommands = new Command[7];
offCommands = new Command[7];
Command noCommand = new NoCommand();
for (int i = 0; i < 7; i++) {
onCommands[i] = noCommand;
offCommands[i] = noCommand;
}
undoCommand = noCommand;
}
public void setCommand(int slot, Command onCommand, Command offCommand) {
onCommands[slot] = onCommand;
offCommands[slot] = offCommand;
}
public void onButtonWasPushed(int slot) {
onCommands[slot].execute();
undoCommand = onCommands[slot];
}
public void offButtonWasPushed(int slot) {
offCommands[slot].execute();
undoCommand = offCommands[slot];
}
public void undoButtonWasPushed() {
undoCommand.undo();
}
}
🧩 第7章:适配器模式与外观模式
适配器模式
适配器模式将一个类的接口转换成客户期望的另一个接口。
// 目标接口
public interface Duck {
void quack();
void fly();
}
// 被适配者
public class Turkey {
public void gobble() {
System.out.println("Gobble gobble");
}
public void fly() {
System.out.println("I'm flying a short distance");
}
}
// 适配器
public class TurkeyAdapter implements Duck {
Turkey turkey;
public TurkeyAdapter(Turkey turkey) {
this.turkey = turkey;
}
public void quack() {
turkey.gobble();
}
public void fly() {
for (int i = 0; i < 5; i++) {
turkey.fly();
}
}
}
外观模式
外观模式提供了一个统一的接口,用来访问子系统中的一群接口。
public class HomeTheaterFacade {
Amplifier amp;
Tuner tuner;
DvdPlayer dvd;
CdPlayer cd;
Projector projector;
public HomeTheaterFacade(Amplifier amp, Tuner tuner, DvdPlayer dvd,
CdPlayer cd, Projector projector) {
this.amp = amp;
this.tuner = tuner;
this.dvd = dvd;
this.cd = cd;
this.projector = projector;
}
public void watchMovie(String movie) {
System.out.println("Get ready to watch a movie...");
projector.on();
projector.wideScreenMode();
amp.on();
amp.setDvd(dvd);
amp.setSurroundSound();
amp.setVolume(5);
dvd.on();
dvd.play(movie);
}
public void endMovie() {
System.out.println("Shutting movie theater down...");
projector.off();
amp.off();
dvd.stop();
dvd.eject();
dvd.off();
}
}
🧩 第8章:模板方法模式
什么是模板方法模式?
模板方法模式在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中。
结构图
classDiagram
class CaffeineBeverage {
<<abstract>>
+prepareRecipe()
+boilWater()
+pourInCup()
+brew()*
+addCondiments()*
}
class Tea {
+brew()
+addCondiments()
}
class Coffee {
+brew()
+addCondiments()
}
CaffeineBeverage <|-- Tea
CaffeineBeverage <|-- Coffee
代码实现
public abstract class CaffeineBeverage {
// 模板方法
public final void prepareRecipe() {
boilWater();
brew();
pourInCup();
addCondiments();
}
abstract void brew();
abstract void addCondiments();
void boilWater() {
System.out.println("Boiling water");
}
void pourInCup() {
System.out.println("Pouring into cup");
}
}
public class Tea extends CaffeineBeverage {
public void brew() {
System.out.println("Steeping the tea");
}
public void addCondiments() {
System.out.println("Adding Lemon");
}
}
public class Coffee extends CaffeineBeverage {
public void brew() {
System.out.println("Dripping Coffee through filter");
}
public void addCondiments() {
System.out.println("Adding Sugar and Milk");
}
}
使用钩子
public abstract class CaffeineBeverageWithHook {
public final void prepareRecipe() {
boilWater();
brew();
pourInCup();
if (customerWantsCondiments()) {
addCondiments();
}
}
abstract void brew();
abstract void addCondiments();
void boilWater() {
System.out.println("Boiling water");
}
void pourInCup() {
System.out.println("Pouring into cup");
}
// 钩子方法
boolean customerWantsCondiments() {
return true;
}
}
🧩 第9章:迭代器与组合模式
迭代器模式
迭代器模式提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露其内部的表示。
public interface Iterator {
boolean hasNext();
Object next();
}
public class DinerMenuIterator implements Iterator {
MenuItem[] items;
int position = 0;
public DinerMenuIterator(MenuItem[] items) {
this.items = items;
}
public Object next() {
MenuItem menuItem = items[position];
position = position + 1;
return menuItem;
}
public boolean hasNext() {
if (position >= items.length || items[position] == null) {
return false;
} else {
return true;
}
}
}
组合模式
组合模式允许你将对象组合成树形结构来表现"整体/部分"层次结构。
public abstract class MenuComponent {
public void add(MenuComponent menuComponent) {
throw new UnsupportedOperationException();
}
public void remove(MenuComponent menuComponent) {
throw new UnsupportedOperationException();
}
public MenuComponent getChild(int i) {
throw new UnsupportedOperationException();
}
public String getName() {
throw new UnsupportedOperationException();
}
public String getDescription() {
throw new UnsupportedOperationException();
}
public double getPrice() {
throw new UnsupportedOperationException();
}
public boolean isVegetarian() {
throw new UnsupportedOperationException();
}
public void print() {
throw new UnsupportedOperationException();
}
}
public class MenuItem extends MenuComponent {
String name;
String description;
boolean vegetarian;
double price;
public MenuItem(String name, String description,
boolean vegetarian, double price) {
this.name = name;
this.description = description;
this.vegetarian = vegetarian;
this.price = price;
}
public String getName() {
return name;
}
public String getDescription() {
return description;
}
public double getPrice() {
return price;
}
public boolean isVegetarian() {
return vegetarian;
}
public void print() {
System.out.print(" " + getName());
if (isVegetarian()) {
System.out.print("(v)");
}
System.out.println(", " + getPrice());
System.out.println(" -- " + getDescription());
}
}
🧩 第10章:状态模式
什么是状态模式?
状态模式允许对象在内部状态改变时改变它的行为,对象看起来好像修改了它的类。
结构图
classDiagram
class GumballMachine {
-state: State
+insertQuarter()
+ejectQuarter()
+turnCrank()
+dispense()
+setState(State)
}
class State {
<<interface>>
+insertQuarter()
+ejectQuarter()
+turnCrank()
+dispense()
}
class NoQuarterState {
-gumballMachine: GumballMachine
+insertQuarter()
+ejectQuarter()
+turnCrank()
+dispense()
}
class HasQuarterState {
-gumballMachine: GumballMachine
+insertQuarter()
+ejectQuarter()
+turnCrank()
+dispense()
}
State <|.. NoQuarterState
State <|.. HasQuarterState
GumballMachine --> State
NoQuarterState --> GumballMachine
HasQuarterState --> GumballMachine
代码实现
public interface State {
void insertQuarter();
void ejectQuarter();
void turnCrank();
void dispense();
}
public class NoQuarterState implements State {
GumballMachine gumballMachine;
public NoQuarterState(GumballMachine gumballMachine) {
this.gumballMachine = gumballMachine;
}
public void insertQuarter() {
System.out.println("You inserted a quarter");
gumballMachine.setState(gumballMachine.getHasQuarterState());
}
public void ejectQuarter() {
System.out.println("You haven't inserted a quarter");
}
public void turnCrank() {
System.out.println("You turned, but there's no quarter");
}
public void dispense() {
System.out.println("You need to pay first");
}
}
public class GumballMachine {
State soldOutState;
State noQuarterState;
State hasQuarterState;
State soldState;
State state = soldOutState;
int count = 0;
public GumballMachine(int numberGumballs) {
soldOutState = new SoldOutState(this);
noQuarterState = new NoQuarterState(this);
hasQuarterState = new HasQuarterState(this);
soldState = new SoldState(this);
this.count = numberGumballs;
if (numberGumballs > 0) {
state = noQuarterState;
}
}
public void insertQuarter() {
state.insertQuarter();
}
public void ejectQuarter() {
state.ejectQuarter();
}
public void turnCrank() {
state.turnCrank();
state.dispense();
}
void setState(State state) {
this.state = state;
}
void releaseBall() {
System.out.println("A gumball comes rolling out the slot...");
if (count != 0) {
count = count - 1;
}
}
}
🧩 第11章:代理模式
什么是代理模式?
代理模式为另一个对象提供一个替身或占位符以控制对这个对象的访问。
远程代理示例
// 客户端
public class GumballMonitor {
GumballMachineRemote machine;
public GumballMonitor(GumballMachineRemote machine) {
this.machine = machine;
}
public void report() {
try {
System.out.println("Gumball Machine: " + machine.getLocation());
System.out.println("Current inventory: " + machine.getCount() + " gumballs");
System.out.println("Current state: " + machine.getState());
} catch (RemoteException e) {
e.printStackTrace();
}
}
}
// 服务端
public class GumballMachine extends UnicastRemoteObject
implements GumballMachineRemote {
State soldOutState;
State noQuarterState;
State hasQuarterState;
State soldState;
State winnerState;
State state = soldOutState;
int count = 0;
String location;
public GumballMachine(String location, int numberGumballs)
throws RemoteException {
// 初始化代码
}
public int getCount() {
return count;
}
public String getLocation() {
return location;
}
public State getState() {
return state;
}
}
🧩 第12章:复合模式
什么是复合模式?
复合模式结合两个或以上的模式,组成一个解决方案,解决一再发生的一般性问题。
MVC模式
MVC是经典的复合模式,结合了观察者、策略和组合模式:
- Model:使用观察者模式,让观察者更新
- View:使用组合模式,管理显示组件
- Controller:使用策略模式,让视图使用不同的控制器
// Model
public class BeatModel implements BeatModelInterface {
List<BeatObserver> beatObservers = new ArrayList<>();
List<BPMObserver> bpmObservers = new ArrayList<>();
int bpm = 90;
public void initialize() {
// 初始化代码
}
public void on() {
// 启动代码
}
public void off() {
// 停止代码
}
public void setBPM(int bpm) {
this.bpm = bpm;
notifyBPMObservers();
}
public int getBPM() {
return bpm;
}
public void registerObserver(BeatObserver o) {
beatObservers.add(o);
}
public void notifyBeatObservers() {
for (BeatObserver observer : beatObservers) {
observer.updateBeat();
}
}
// 其他观察者方法
}
// View
public class DJView implements ActionListener, BeatObserver, BPMObserver {
BeatModelInterface model;
ControllerInterface controller;
JFrame viewFrame;
JPanel viewPanel;
// 其他UI组件
public DJView(ControllerInterface controller, BeatModelInterface model) {
this.controller = controller;
this.model = model;
model.registerObserver((BeatObserver)this);
model.registerObserver((BPMObserver)this);
}
public void createView() {
// 创建UI
}
public void updateBPM() {
// 更新BPM显示
}
public void updateBeat() {
// 更新节拍显示
}
}
// Controller
public class BeatController implements ControllerInterface {
BeatModelInterface model;
DJView view;
public BeatController(BeatModelInterface model) {
this.model = model;
view = new DJView(this, model);
view.createView();
view.createControls();
view.disableStopMenuItem();
view.enableStartMenuItem();
model.initialize();
}
public void start() {
model.on();
view.disableStartMenuItem();
view.enableStopMenuItem();
}
public void stop() {
model.off();
view.disableStopMenuItem();
view.enableStartMenuItem();
}
public void increaseBPM() {
int bpm = model.getBPM();
model.setBPM(bpm + 1);
}
public void decreaseBPM() {
int bpm = model.getBPM();
model.setBPM(bpm - 1);
}
public void setBPM(int bpm) {
model.setBPM(bpm);
}
}
🧩 第13-14章:真实世界中的模式与剩余模式
🎯 模式使用指南
模式分类详解
创建型模式:处理对象创建
这些模式关注对象的创建机制,帮助系统独立于如何创建、组合和表示对象。
结构型模式:处理类或对象组合
这些模式关注类和对象的组合,形成更大的结构,同时保持结构的灵活和高效。
行为型模式:处理类或对象交互和职责分配
这些模式关注对象之间的职责分配和算法,以及对象之间的通信模式。
选择模式的思考过程
-
模式是怎样解决问题的?
- 分析问题本质,理解模式的解决方案思路
- 考虑模式如何封装变化,提高系统弹性
-
模式的意图是什么?
- 明确模式要解决的核心问题
- 理解模式的应用场景和限制条件
-
模式使用了哪些设计原则?
- 识别模式背后的设计原则
- 理解原则如何指导模式设计
-
你知道哪些相关模式?
- 比较相似模式的差异
- 了解模式之间的组合可能性
🔄 其他重要模式详解
桥接模式(Bridge Pattern)
结构图
classDiagram
class Abstraction {
-implementor: Implementor
+operation()
}
class RefinedAbstraction {
+operation()
}
class Implementor {
<<interface>>
+operationImpl()
}
class ConcreteImplementorA {
+operationImpl()
}
class ConcreteImplementorB {
+operationImpl()
}
Abstraction <|-- RefinedAbstraction
Abstraction --> Implementor
Implementor <|.. ConcreteImplementorA
Implementor <|.. ConcreteImplementorB
代码实现
// 实现接口
public interface DrawingAPI {
void drawCircle(double x, double y, double radius);
void drawRectangle(double x, double y, double width, double height);
}
// 具体实现A
public class DrawingAPI1 implements DrawingAPI {
public void drawCircle(double x, double y, double radius) {
System.out.printf("API1.circle at %.2f:%.2f radius %.2f\n", x, y, radius);
}
public void drawRectangle(double x, double y, double width, double height) {
System.out.printf("API1.rectangle at %.2f:%.2f width %.2f height %.2f\n",
x, y, width, height);
}
}
// 具体实现B
public class DrawingAPI2 implements DrawingAPI {
public void drawCircle(double x, double y, double radius) {
System.out.printf("API2.circle at %.2f:%.2f radius %.2f\n", x, y, radius);
}
public void drawRectangle(double x, double y, double width, double height) {
System.out.printf("API2.rectangle at %.2f:%.2f width %.2f height %.2f\n",
x, y, width, height);
}
}
// 抽象形状
public abstract class Shape {
protected DrawingAPI drawingAPI;
protected Shape(DrawingAPI drawingAPI) {
this.drawingAPI = drawingAPI;
}
public abstract void draw();
public abstract void resize(double percentage);
}
// 具体形状
public class CircleShape extends Shape {
private double x, y, radius;
public CircleShape(double x, double y, double radius, DrawingAPI drawingAPI) {
super(drawingAPI);
this.x = x;
this.y = y;
this.radius = radius;
}
public void draw() {
drawingAPI.drawCircle(x, y, radius);
}
public void resize(double percentage) {
radius *= percentage;
}
}
// 使用示例
public class BridgePatternDemo {
public static void main(String[] args) {
Shape[] shapes = new Shape[] {
new CircleShape(1, 2, 3, new DrawingAPI1()),
new CircleShape(5, 7, 11, new DrawingAPI2())
};
for (Shape shape : shapes) {
shape.resize(2.5);
shape.draw();
}
}
}
生成器模式(Builder Pattern)
结构图
classDiagram
class Director {
-builder: Builder
+construct()
}
class Builder {
<<interface>>
+buildPartA()
+buildPartB()
+buildPartC()
+getResult()
}
class ConcreteBuilder {
-product: Product
+buildPartA()
+buildPartB()
+buildPartC()
+getResult()
}
class Product {
+parts: List~String~
+add(String)
+show()
}
Director --> Builder
Builder <|.. ConcreteBuilder
ConcreteBuilder --> Product
代码实现
// 产品类
public class Pizza {
private String dough = "";
private String sauce = "";
private String topping = "";
public void setDough(String dough) {
this.dough = dough;
}
public void setSauce(String sauce) {
this.sauce = sauce;
}
public void setTopping(String topping) {
this.topping = topping;
}
public void showPizza() {
System.out.println("Pizza with " + dough + " dough, " +
sauce + " sauce, and " + topping + " topping.");
}
}
// 抽象生成器
public abstract class PizzaBuilder {
protected Pizza pizza;
public Pizza getPizza() {
return pizza;
}
public void createNewPizzaProduct() {
pizza = new Pizza();
}
public abstract void buildDough();
public abstract void buildSauce();
public abstract void buildTopping();
}
// 具体生成器
public class HawaiianPizzaBuilder extends PizzaBuilder {
public void buildDough() {
pizza.setDough("cross");
}
public void buildSauce() {
pizza.setSauce("mild");
}
public void buildTopping() {
pizza.setTopping("ham+pineapple");
}
}
public class SpicyPizzaBuilder extends PizzaBuilder {
public void buildDough() {
pizza.setDough("pan baked");
}
public void buildSauce() {
pizza.setSauce("hot");
}
public void buildTopping() {
pizza.setTopping("pepperoni+salami");
}
}
// 指导者
public class Cook {
private PizzaBuilder pizzaBuilder;
public void setPizzaBuilder(PizzaBuilder pb) {
pizzaBuilder = pb;
}
public Pizza getPizza() {
return pizzaBuilder.getPizza();
}
public void constructPizza() {
pizzaBuilder.createNewPizzaProduct();
pizzaBuilder.buildDough();
pizzaBuilder.buildSauce();
pizzaBuilder.buildTopping();
}
}
// 使用示例
public class BuilderExample {
public static void main(String[] args) {
Cook cook = new Cook();
PizzaBuilder hawaiianPizzaBuilder = new HawaiianPizzaBuilder();
PizzaBuilder spicyPizzaBuilder = new SpicyPizzaBuilder();
cook.setPizzaBuilder(hawaiianPizzaBuilder);
cook.constructPizza();
Pizza hawaiian = cook.getPizza();
hawaiian.showPizza();
cook.setPizzaBuilder(spicyPizzaBuilder);
cook.constructPizza();
Pizza spicy = cook.getPizza();
spicy.showPizza();
}
}
责任链模式(Chain of Responsibility Pattern)
结构图
classDiagram
class Handler {
<<abstract>>
-successor: Handler
+setSuccessor(Handler)
+handleRequest(Request)*
}
class ConcreteHandler1 {
+handleRequest(Request)
}
class ConcreteHandler2 {
+handleRequest(Request)
}
class ConcreteHandler3 {
+handleRequest(Request)
}
class Request {
-type: String
-amount: double
+getType()
+getAmount()
}
Handler <|-- ConcreteHandler1
Handler <|-- ConcreteHandler2
Handler <|-- ConcreteHandler3
Handler --> Handler
ConcreteHandler1 --> Request
代码实现
// 请求类
public class PurchaseRequest {
private double amount;
private String purpose;
public PurchaseRequest(double amount, String purpose) {
this.amount = amount;
this.purpose = purpose;
}
public double getAmount() {
return amount;
}
public void setAmount(double amount) {
this.amount = amount;
}
public String getPurpose() {
return purpose;
}
}
// 处理器接口
public abstract class PurchasePower {
protected static final double BASE = 500;
protected PurchasePower successor;
public void setSuccessor(PurchasePower successor) {
this.successor = successor;
}
abstract public void processRequest(PurchaseRequest request);
}
// 具体处理器
public class ManagerPPower extends PurchasePower {
private final double ALLOWABLE = 10 * BASE;
public void processRequest(PurchaseRequest request) {
if (request.getAmount() < ALLOWABLE) {
System.out.println("Manager will approve $" + request.getAmount());
} else if (successor != null) {
successor.processRequest(request);
}
}
}
public class DirectorPPower extends PurchasePower {
private final double ALLOWABLE = 20 * BASE;
public void processRequest(PurchaseRequest request) {
if (request.getAmount() < ALLOWABLE) {
System.out.println("Director will approve $" + request.getAmount());
} else if (successor != null) {
successor.processRequest(request);
}
}
}
public class VicePresidentPPower extends PurchasePower {
private final double ALLOWABLE = 40 * BASE;
public void processRequest(PurchaseRequest request) {
if (request.getAmount() < ALLOWABLE) {
System.out.println("Vice President will approve $" + request.getAmount());
} else if (successor != null) {
successor.processRequest(request);
}
}
}
public class PresidentPPower extends PurchasePower {
private final double ALLOWABLE = 60 * BASE;
public void processRequest(PurchaseRequest request) {
if (request.getAmount() < ALLOWABLE) {
System.out.println("President will approve $" + request.getAmount());
} else {
System.out.println("Your request for $" + request.getAmount() + " needs a board meeting!");
}
}
}
// 使用示例
public class CheckAuthority {
public static void main(String[] args) {
ManagerPPower manager = new ManagerPPower();
DirectorPPower director = new DirectorPPower();
VicePresidentPPower vp = new VicePresidentPPower();
PresidentPPower president = new PresidentPPower();
manager.setSuccessor(director);
director.setSuccessor(vp);
vp.setSuccessor(president);
// 处理各种金额的请求
manager.processRequest(new PurchaseRequest(500, "General"));
manager.processRequest(new PurchaseRequest(5000, "General"));
manager.processRequest(new PurchaseRequest(15000, "General"));
manager.processRequest(new PurchaseRequest(35000, "General"));
}
}
蝇量模式(Flyweight Pattern)
结构图
classDiagram
class FlyweightFactory {
-flyweights: Map~String, Flyweight~
+getFlyweight(String)
}
class Flyweight {
<<interface>>
+operation(extrinsicState)
}
class ConcreteFlyweight {
-intrinsicState
+operation(extrinsicState)
}
class UnsharedConcreteFlyweight {
-allState
+operation(extrinsicState)
}
class Client {
+operation()
}
FlyweightFactory --> Flyweight
Flyweight <|.. ConcreteFlyweight
Flyweight <|.. UnsharedConcreteFlyweight
Client --> Flyweight
Client --> FlyweightFactory
代码实现
import java.util.*;
// 蝇量接口
public interface Shape {
void draw(int x, int y);
}
// 具体蝇量
public class Circle implements Shape {
private String color;
private int radius;
public Circle(String color) {
this.color = color;
}
public void setRadius(int radius) {
this.radius = radius;
}
@Override
public void draw(int x, int y) {
System.out.println("Drawing Circle [Color: " + color +
", Radius: " + radius +
", x: " + x + ", y: " + y + "]");
}
}
// 蝇量工厂
public class ShapeFactory {
private static final HashMap<String, Shape> circleMap = new HashMap<>();
public static Shape getCircle(String color) {
Circle circle = (Circle)circleMap.get(color);
if (circle == null) {
circle = new Circle(color);
circleMap.put(color, circle);
System.out.println("Creating circle of color: " + color);
}
return circle;
}
}
// 使用示例
public class FlyweightPatternDemo {
private static final String[] colors = {"Red", "Green", "Blue", "White", "Black"};
public static void main(String[] args) {
for (int i = 0; i < 20; ++i) {
Circle circle = (Circle)ShapeFactory.getCircle(getRandomColor());
circle.setRadius(100);
circle.draw(getRandomX(), getRandomY());
}
}
private static String getRandomColor() {
return colors[(int)(Math.random() * colors.length)];
}
private static int getRandomX() {
return (int)(Math.random() * 100);
}
private static int getRandomY() {
return (int)(Math.random() * 100);
}
}
解释器模式(Interpreter Pattern)
结构图
classDiagram
class AbstractExpression {
<<abstract>>
+interpret(Context)
}
class TerminalExpression {
+interpret(Context)
}
class NonterminalExpression {
-expression: AbstractExpression
+interpret(Context)
}
class Context {
-input: String
-output: String
+getInput()
+setInput(String)
+getOutput()
+setOutput(String)
}
AbstractExpression <|-- TerminalExpression
AbstractExpression <|-- NonterminalExpression
NonterminalExpression --> AbstractExpression
TerminalExpression --> Context
NonterminalExpression --> Context
代码实现
import java.util.*;
// 上下文
public class Context {
private String input;
private int output;
public Context(String input) {
this.input = input;
}
public String getInput() {
return input;
}
public void setInput(String input) {
this.input = input;
}
public int getOutput() {
return output;
}
public void setOutput(int output) {
this.output = output;
}
}
// 抽象表达式
public interface Expression {
void interpret(Context context);
}
// 终端表达式
public class NumberExpression implements Expression {
private int number;
public NumberExpression(int number) {
this.number = number;
}
@Override
public void interpret(Context context) {
context.setOutput(number);
}
}
// 非终端表达式 - 加法
public class AddExpression implements Expression {
private Expression leftExpression;
private Expression rightExpression;
public AddExpression(Expression left, Expression right) {
leftExpression = left;
rightExpression = right;
}
@Override
public void interpret(Context context) {
leftExpression.interpret(context);
int leftResult = context.getOutput();
rightExpression.interpret(context);
int rightResult = context.getOutput();
context.setOutput(leftResult + rightResult);
}
}
// 非终端表达式 - 减法
public class SubtractExpression implements Expression {
private Expression leftExpression;
private Expression rightExpression;
public SubtractExpression(Expression left, Expression right) {
leftExpression = left;
rightExpression = right;
}
@Override
public void interpret(Context context) {
leftExpression.interpret(context);
int leftResult = context.getOutput();
rightExpression.interpret(context);
int rightResult = context.getOutput();
context.setOutput(leftResult - rightResult);
}
}
// 解析器
public class ExpressionParser {
private Stack<Expression> stack = new Stack<>();
public int parse(String expression) {
String[] tokens = expression.split(" ");
for (String token : tokens) {
if (isOperator(token)) {
Expression rightExpression = stack.pop();
Expression leftExpression = stack.pop();
Expression operator = getOperatorInstance(token, leftExpression, rightExpression);
int result = evaluate(operator);
stack.push(new NumberExpression(result));
} else {
Expression number = new NumberExpression(Integer.parseInt(token));
stack.push(number);
}
}
return stack.pop().interpret(new Context(""));
}
private boolean isOperator(String token) {
return token.equals("+") || token.equals("-");
}
private Expression getOperatorInstance(String token, Expression left, Expression right) {
if (token.equals("+")) {
return new AddExpression(left, right);
} else if (token.equals("-")) {
return new SubtractExpression(left, right);
}
return null;
}
private int evaluate(Expression expression) {
Context context = new Context("");
expression.interpret(context);
return context.getOutput();
}
}
// 使用示例
public class InterpreterDemo {
public static void main(String[] args) {
ExpressionParser parser = new ExpressionParser();
String expression1 = "2 3 +"; // 2 + 3 = 5
String expression2 = "5 2 -"; // 5 - 2 = 3
String expression3 = "2 3 + 4 -"; // (2 + 3) - 4 = 1
System.out.println(expression1 + " = " + parser.parse(expression1));
System.out.println(expression2 + " = " + parser.parse(expression2));
System.out.println(expression3 + " = " + parser.parse(expression3));
}
}
中介者模式(Mediator Pattern)
结构图
classDiagram
class Mediator {
<<interface>>
+send(String, Colleague)
}
class ConcreteMediator {
-colleague1: Colleague
-colleague2: Colleague
+send(String, Colleague)
}
class Colleague {
<<abstract>>
-mediator: Mediator
+Colleague(Mediator)
+send(String)
+receive(String)*
}
class ConcreteColleague1 {
+receive(String)
}
class ConcreteColleague2 {
+receive(String)
}
Mediator <|.. ConcreteMediator
Colleague <|-- ConcreteColleague1
Colleague <|-- ConcreteColleague2
ConcreteMediator --> Colleague
Colleague --> Mediator
代码实现
// 中介者接口
public interface ChatMediator {
void sendMessage(String msg, User user);
void addUser(User user);
}
// 具体中介者
public class ChatMediatorImpl implements ChatMediator {
private List<User> users;
public ChatMediatorImpl() {
this.users = new ArrayList<>();
}
@Override
public void addUser(User user) {
this.users.add(user);
}
@Override
public void sendMessage(String msg, User user) {
for (User u : this.users) {
// 消息不应该被发送者接收
if (u != user) {
u.receive(msg);
}
}
}
}
// 抽象同事类
public abstract class User {
protected ChatMediator mediator;
protected String name;
public User(ChatMediator med, String name) {
this.mediator = med;
this.name = name;
}
public abstract void send(String msg);
public abstract void receive(String msg);
}
// 具体同事类
public class UserImpl extends User {
public UserImpl(ChatMediator med, String name) {
super(med, name);
}
@Override
public void send(String msg) {
System.out.println(this.name + ": Sending Message: " + msg);
mediator.sendMessage(msg, this);
}
@Override
public void receive(String msg) {
System.out.println(this.name + ": Received Message: " + msg);
}
}
// 使用示例
public class ChatClient {
public static void main(String[] args) {
ChatMediator mediator = new ChatMediatorImpl();
User user1 = new UserImpl(mediator, "Alice");
User user2 = new UserImpl(mediator, "Bob");
User user3 = new UserImpl(mediator, "Charlie");
User user4 = new UserImpl(mediator, "Diana");
mediator.addUser(user1);
mediator.addUser(user2);
mediator.addUser(user3);
mediator.addUser(user4);
user1.send("Hi All!");
user3.send("Hello everyone!");
}
}
备忘录模式(Memento Pattern)
结构图
classDiagram
class Originator {
-state: String
+setState(String)
+getState()
+saveStateToMemento()
+getStateFromMemento(Memento)
}
class Memento {
-state: String
+Memento(String)
+getState()
}
class CareTaker {
-mementoList: List~Memento~
+add(Memento)
+get(int)
}
Originator --> Memento
CareTaker --> Memento
代码实现
import java.util.*;
// 备忘录
public class Memento {
private final String state;
public Memento(String state) {
this.state = state;
}
public String getState() {
return state;
}
}
// 原发器
public class Originator {
private String state;
public void setState(String state) {
this.state = state;
}
public String getState() {
return state;
}
public Memento saveStateToMemento() {
return new Memento(state);
}
public void getStateFromMemento(Memento memento) {
state = memento.getState();
}
}
// 管理者
public class CareTaker {
private List<Memento> mementoList = new ArrayList<>();
public void add(Memento state) {
mementoList.add(state);
}
public Memento get(int index) {
return mementoList.get(index);
}
public List<Memento> getMementoList() {
return mementoList;
}
}
// 使用示例
public class MementoPatternDemo {
public static void main(String[] args) {
Originator originator = new Originator();
CareTaker careTaker = new CareTaker();
originator.setState("State #1");
originator.setState("State #2");
careTaker.add(originator.saveStateToMemento());
originator.setState("State #3");
careTaker.add(originator.saveStateToMemento());
originator.setState("State #4");
System.out.println("Current State: " + originator.getState());
// 恢复到之前的状态
originator.getStateFromMemento(careTaker.get(0));
System.out.println("First saved State: " + originator.getState());
originator.getStateFromMemento(careTaker.get(1));
System.out.println("Second saved State: " + originator.getState());
}
}
原型模式(Prototype Pattern)
结构图
classDiagram
class Prototype {
<<interface>>
+clone() Prototype
}
class ConcretePrototype1 {
-field: String
+ConcretePrototype1(String)
+clone() Prototype
+getField()
}
class ConcretePrototype2 {
-field: String
+ConcretePrototype2(String)
+clone() Prototype
+getField()
}
class Client {
+operation()
}
Prototype <|.. ConcretePrototype1
Prototype <|.. ConcretePrototype2
Client --> Prototype
代码实现
import java.util.*;
// 原型接口
public interface Prototype extends Cloneable {
Prototype clone() throws CloneNotSupportedException;
}
// 具体原型
public class Circle implements Prototype {
private String color;
private int x;
private int y;
private int radius;
public Circle(String color) {
this.color = color;
}
public void setX(int x) {
this.x = x;
}
public void setY(int y) {
this.y = y;
}
public void setRadius(int radius) {
this.radius = radius;
}
@Override
public Prototype clone() throws CloneNotSupportedException {
return (Circle) super.clone();
}
public void draw() {
System.out.println("Drawing Circle [Color: " + color +
", x: " + x + ", y: " + y +
", radius: " + radius + "]");
}
}
// 原型注册表
public class PrototypeRegistry {
private Map<String, Prototype> prototypes = new HashMap<>();
public PrototypeRegistry() {
// 预创建一些原型
Circle redCircle = new Circle("Red");
redCircle.setRadius(10);
prototypes.put("RedCircle", redCircle);
Circle blueCircle = new Circle("Blue");
blueCircle.setRadius(20);
prototypes.put("BlueCircle", blueCircle);
}
public void addPrototype(String key, Prototype prototype) {
prototypes.put(key, prototype);
}
public Prototype getPrototype(String key) throws CloneNotSupportedException {
return prototypes.get(key).clone();
}
}
// 使用示例
public class PrototypeDemo {
public static void main(String[] args) {
PrototypeRegistry registry = new PrototypeRegistry();
try {
Circle redCircle1 = (Circle) registry.getPrototype("RedCircle");
redCircle1.setX(10);
redCircle1.setY(20);
redCircle1.draw();
Circle redCircle2 = (Circle) registry.getPrototype("RedCircle");
redCircle2.setX(30);
redCircle2.setY(40);
redCircle2.draw();
// 验证两个对象是不同的实例
System.out.println("Are both circles the same instance? " +
(redCircle1 == redCircle2));
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
}
}
访问者模式(Visitor Pattern)
结构图
classDiagram
class Visitor {
<<interface>>
+visit(ElementA)
+visit(ElementB)
}
class ConcreteVisitor1 {
+visit(ElementA)
+visit(ElementB)
}
class ConcreteVisitor2 {
+visit(ElementA)
+visit(ElementB)
}
class Element {
<<interface>>
+accept(Visitor)
}
class ElementA {
+accept(Visitor)
+operationA()
}
class ElementB {
+accept(Visitor)
+operationB()
}
class ObjectStructure {
-elements: List~Element~
+add(Element)
+remove(Element)
+accept(Visitor)
}
Visitor <|.. ConcreteVisitor1
Visitor <|.. ConcreteVisitor2
Element <|.. ElementA
Element <|.. ElementB
ObjectStructure --> Element
ConcreteVisitor1 --> ElementA
ConcreteVisitor1 --> ElementB
代码实现
import java.util.*;
// 访问者接口
public interface ComputerPartVisitor {
void visit(Computer computer);
void visit(Mouse mouse);
void visit(Keyboard keyboard);
void visit(Monitor monitor);
}
// 具体访问者
public class ComputerPartDisplayVisitor implements ComputerPartVisitor {
@Override
public void visit(Computer computer) {
System.out.println("Displaying Computer.");
}
@Override
public void visit(Mouse mouse) {
System.out.println("Displaying Mouse.");
}
@Override
public void visit(Keyboard keyboard) {
System.out.println("Displaying Keyboard.");
}
@Override
public void visit(Monitor monitor) {
System.out.println("Displaying Monitor.");
}
}
// 元素接口
public interface ComputerPart {
void accept(ComputerPartVisitor computerPartVisitor);
}
// 具体元素
public class Keyboard implements ComputerPart {
@Override
public void accept(ComputerPartVisitor computerPartVisitor) {
computerPartVisitor.visit(this);
}
}
public class Monitor implements ComputerPart {
@Override
public void accept(ComputerPartVisitor computerPartVisitor) {
computerPartVisitor.visit(this);
}
}
public class Mouse implements ComputerPart {
@Override
public void accept(ComputerPartVisitor computerPartVisitor) {
computerPartVisitor.visit(this);
}
}
public class Computer implements ComputerPart {
ComputerPart[] parts;
public Computer() {
parts = new ComputerPart[] {new Mouse(), new Keyboard(), new Monitor()};
}
@Override
public void accept(ComputerPartVisitor computerPartVisitor) {
for (ComputerPart part : parts) {
part.accept(computerPartVisitor);
}
computerPartVisitor.visit(this);
}
}
// 使用示例
public class VisitorPatternDemo {
public static void main(String[] args) {
ComputerPart computer = new Computer();
computer.accept(new ComputerPartDisplayVisitor());
}
}
🎯 模式选择指南
根据问题类型选择模式
| 问题类型 | 推荐模式 | 说明 |
|---|---|---|
| 需要创建复杂对象 | 生成器模式 | 分离构建过程和表示 |
| 需要创建大量相似对象 | 原型模式 | 通过克隆提高性能 |
| 需要控制对象创建 | 工厂模式 | 封装对象创建逻辑 |
| 需要处理对象组合 | 组合模式 | 统一处理整体和部分 |
| 需要为对象添加功能 | 装饰者模式 | 动态扩展功能 |
| 需要统一接口 | 适配器模式 | 转换不兼容接口 |
| 需要简化复杂接口 | 外观模式 | 提供统一入口 |
| 需要处理算法变化 | 策略模式 | 封装可互换算法 |
| 需要处理状态变化 | 状态模式 | 封装状态相关行为 |
| 需要处理一对多依赖 | 观察者模式 | 实现发布-订阅机制 |
模式组合使用示例
// 组合使用工厂模式和策略模式
public class PaymentProcessor {
private PaymentStrategy strategy;
public void setPaymentStrategy(String type) {
this.strategy = PaymentStrategyFactory.createStrategy(type);
}
public void processPayment(double amount) {
strategy.processPayment(amount);
}
}
// 组合使用装饰者模式和工厂模式
public class CoffeeShop {
public Beverage createCoffee(String type, List<String> condiments) {
Beverage beverage = CoffeeFactory.createCoffee(type);
for (String condiment : condiments) {
beverage = CondimentFactory.createCondiment(condiment, beverage);
}
return beverage;
}
}
📊 模式对比总结
| 模式 | 类型 | 主要用途 | 关键特点 |
|---|---|---|---|
| 桥接模式 | 结构型 | 分离抽象和实现 | 通过组合建立桥梁 |
| 生成器模式 | 创建型 | 构建复杂对象 | 分步构建,相同过程不同表示 |
| 责任链模式 | 行为型 | 处理请求链 | 多个处理器,动态链 |
| 蝇量模式 | 结构型 | 共享细粒度对象 | 减少内存使用,共享状态 |
| 解释器模式 | 行为型 | 解释语言文法 | 定义文法,构建解释器 |
| 中介者模式 | 行为型 | 简化对象交互 | 集中控制,减少依赖 |
| 备忘录模式 | 行为型 | 保存和恢复状态 | 不破坏封装性的状态保存 |
| 原型模式 | 创建型 | 克隆对象 | 通过复制创建新对象 |
| 访问者模式 | 行为型 | 分离算法和结构 | 在不修改类的前提下添加操作 |
🎓 设计原则总结
核心设计原则
- 封装变化:找出应用中可能需要变化之处,把它们独立出来
- 针对接口编程:针对接口编程,而不是针对实现编程
- 多用组合,少用继承:使用组合建立系统具有更大的弹性
- 为交互对象之间的松耦合设计而努力:松耦合的设计更有弹性,更能应对变化
- 开闭原则:对扩展开放,对修改关闭
- 依赖倒置原则:依赖抽象,不要依赖具体类
- 最少知识原则:只和你的密友谈话
- 好莱坞原则:别调用我们,我们会调用你
- 单一责任原则:一个类应该只有一个引起变化的原因
原则与模式的关系
设计模式是设计原则的具体体现,每个模式都体现了某些设计原则:
- 策略模式体现了封装变化、针对接口编程、多用组合少用继承
- 观察者模式体现了松耦合、针对接口编程
- 装饰者模式体现了开闭原则、多用组合少用继承
- 工厂模式体现了依赖倒置原则
- 模板方法模式体现了好莱坞原则
🏁 结语
设计模式不是银弹,而是经过验证的解决方案。掌握设计模式的真正价值在于:
- 建立共享词汇:让团队成员能够高效沟通
- 培养设计直觉:在面对新问题时能够识别出适合的模式
- 理解设计原则:模式背后的原则比模式本身更重要
- 提高代码质量:构建出更灵活、可维护、可扩展的系统
记住,模式是工具,而不是目标。在实际项目中,要根据具体需求选择合适的模式,避免过度设计。最好的设计往往是简单而优雅的。
"优秀的软件设计不是没有bug,而是当需求变化时,修改的成本很低。"
—— Robert C. Martin
希望这篇全面的设计模式指南能够帮助你在软件设计的道路上走得更远,构建出更加优雅和健壮的软件系统!