程序设计模式详解
以下是常见设计模式的详细说明,每个模式都提供了JavaScript、Java和Python三种语言的实现示例,可通过切换标签查看不同语言的代码。
1. 单例模式 (Singleton)
单例模式确保一个类只有一个实例,并提供一个全局访问点。常用于日志记录器、配置管理器等需要唯一实例的场景。
javascript
class Singleton {
constructor() {
if (Singleton.instance) {
return Singleton.instance;
}
Singleton.instance = this;
// 初始化代码
this.timestamp = new Date();
}
static getInstance() {
if (!Singleton.instance) {
Singleton.instance = new Singleton();
}
return Singleton.instance;
}
getCreationTime() {
return this.timestamp;
}
}
// 使用示例
const instance1 = new Singleton();
const instance2 = Singleton.getInstance();
console.log(instance1 === instance2); // true
console.log(instance1.getCreationTime());
java
public class Singleton {
// volatile确保多线程环境下的可见性
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;
}
// 示例方法
public void doSomething() {
System.out.println("Singleton instance is working");
}
}
// 使用示例
public class Main {
public static void main(String[] args) {
Singleton instance1 = Singleton.getInstance();
Singleton instance2 = Singleton.getInstance();
System.out.println(instance1 == instance2); // true
instance1.doSomething();
}
}
python
class Singleton:
_instance = None
def __new__(cls):
if cls._instance is None:
cls._instance = super().__new__(cls)
# 初始化代码
cls._instance.timestamp = datetime.datetime.now()
return cls._instance
def get_creation_time(self):
return self.timestamp
# 使用示例
import datetime
instance1 = Singleton()
instance2 = Singleton()
print(instance1 is instance2) # True
print(instance1.get_creation_time())
2. 工厂模式 (Factory)
工厂模式通过工厂类封装对象创建逻辑,客户端无需知道具体产品的类名,只需知道相应的参数即可创建所需对象。
javascript
// 产品类
class Car {
drive() {
return 'Driving a car';
}
}
class Bike {
ride() {
return 'Riding a bike';
}
}
class Truck {
haul() {
return 'Hauling with a truck';
}
}
// 工厂类
class VehicleFactory {
createVehicle(type) {
switch(type) {
case 'car':
return new Car();
case 'bike':
return new Bike();
case 'truck':
return new Truck();
default:
throw new Error('Invalid vehicle type');
}
}
}
// 使用示例
const factory = new VehicleFactory();
const myCar = factory.createVehicle('car');
console.log(myCar.drive()); // Driving a car
const myBike = factory.createVehicle('bike');
console.log(myBike.ride()); // Riding a bike
java
// 产品接口
interface Vehicle {
String operate();
}
// 具体产品
class Car implements Vehicle {
@Override
public String operate() {
return "Driving a car";
}
}
class Bike implements Vehicle {
@Override
public String operate() {
return "Riding a bike";
}
}
// 工厂类
class VehicleFactory {
public Vehicle createVehicle(String type) {
switch(type) {
case "car":
return new Car();
case "bike":
return new Bike();
default:
throw new IllegalArgumentException("Invalid vehicle type");
}
}
}
// 使用示例
public class Main {
public static void main(String[] args) {
VehicleFactory factory = new VehicleFactory();
Vehicle myCar = factory.createVehicle("car");
System.out.println(myCar.operate()); // Driving a car
Vehicle myBike = factory.createVehicle("bike");
System.out.println(myBike.operate()); // Riding a bike
}
}
python
# 产品类
class Car:
def operate(self):
return "Driving a car"
class Bike:
def operate(self):
return "Riding a bike"
class Truck:
def operate(self):
return "Hauling with a truck"
# 工厂类
class VehicleFactory:
def create_vehicle(self, vehicle_type):
if vehicle_type == "car":
return Car()
elif vehicle_type == "bike":
return Bike()
elif vehicle_type == "truck":
return Truck()
else:
raise ValueError(f"Invalid vehicle type: {vehicle_type}")
# 使用示例
factory = VehicleFactory()
my_car = factory.create_vehicle("car")
print(my_car.operate()) # Driving a car
my_bike = factory.create_vehicle("bike")
print(my_bike.operate()) # Riding a bike
3. 策略模式 (Strategy)
策略模式定义了一系列算法,将每个算法封装起来,并使它们可以相互替换。策略模式让算法独立于使用它的客户而变化。
javascript
// 策略接口
class PaymentStrategy {
pay(amount) {
throw new Error('子类必须实现pay方法');
}
}
// 具体策略
class CreditCardPayment extends PaymentStrategy {
constructor(cardNumber, name) {
super();
this.cardNumber = cardNumber;
this.name = name;
}
pay(amount) {
return `Paid ${amount} using credit card (${this.cardNumber}) by ${this.name}`;
}
}
class PayPalPayment extends PaymentStrategy {
constructor(email) {
super();
this.email = email;
}
pay(amount) {
return `Paid ${amount} using PayPal (${this.email})`;
}
}
// 上下文
class ShoppingCart {
constructor(paymentStrategy) {
this.items = [];
this.paymentStrategy = paymentStrategy;
}
setPaymentStrategy(strategy) {
this.paymentStrategy = strategy;
}
addItem(item) {
this.items.push(item);
}
calculateTotal() {
return this.items.reduce((total, item) => total + item.price, 0);
}
checkout() {
const total = this.calculateTotal();
return this.paymentStrategy.pay(total);
}
}
// 使用示例
const creditCard = new CreditCardPayment('4111-1111-1111-1111', 'John Doe');
const cart = new ShoppingCart(creditCard);
cart.addItem({ name: 'Shirt', price: 29.99 });
cart.addItem({ name: 'Pants', price: 49.99 });
console.log(cart.checkout()); // Paid 79.98 using credit card...
// 切换支付策略
const paypal = new PayPalPayment('john.doe@example.com');
cart.setPaymentStrategy(paypal);
console.log(cart.checkout()); // Paid 79.98 using PayPal...
java
// 策略接口
interface PaymentStrategy {
String pay(double amount);
}
// 具体策略
class CreditCardPayment implements PaymentStrategy {
private String cardNumber;
private String name;
public CreditCardPayment(String cardNumber, String name) {
this.cardNumber = cardNumber;
this.name = name;
}
@Override
public String pay(double amount) {
return String.format("Paid %.2f using credit card (%s) by %s",
amount, cardNumber, name);
}
}
class PayPalPayment implements PaymentStrategy {
private String email;
public PayPalPayment(String email) {
this.email = email;
}
@Override
public String pay(double amount) {
return String.format("Paid %.2f using PayPal (%s)", amount, email);
}
}
// 上下文
class ShoppingCart {
private PaymentStrategy paymentStrategy;
private double total = 0;
public ShoppingCart(PaymentStrategy strategy) {
this.paymentStrategy = strategy;
}
public void setPaymentStrategy(PaymentStrategy strategy) {
this.paymentStrategy = strategy;
}
public void addItem(double price) {
total += price;
}
public String checkout() {
return paymentStrategy.pay(total);
}
}
// 使用示例
public class Main {
public static void main(String[] args) {
PaymentStrategy creditCard = new CreditCardPayment(
"4111-1111-1111-1111", "John Doe");
ShoppingCart cart = new ShoppingCart(creditCard);
cart.addItem(29.99);
cart.addItem(49.99);
System.out.println(cart.checkout());
// 切换支付策略
PaymentStrategy paypal = new PayPalPayment("john.doe@example.com");
cart.setPaymentStrategy(paypal);
System.out.println(cart.checkout());
}
}
python
# 策略接口
from abc import ABC, abstractmethod
class PaymentStrategy(ABC):
@abstractmethod
def pay(self, amount):
pass
# 具体策略
class CreditCardPayment(PaymentStrategy):
def __init__(self, card_number, name):
self.card_number = card_number
self.name = name
def pay(self, amount):
return f"Paid {amount:.2f} using credit card ({self.card_number}) by {self.name}"
class PayPalPayment(PaymentStrategy):
def __init__(self, email):
self.email = email
def pay(self, amount):
return f"Paid {amount:.2f} using PayPal ({self.email})"
# 上下文
class ShoppingCart:
def __init__(self, payment_strategy):
self.items = []
self.payment_strategy = payment_strategy
def set_payment_strategy(self, strategy):
self.payment_strategy = strategy
def add_item(self, price):
self.items.append(price)
def calculate_total(self):
return sum(self.items)
def checkout(self):
total = self.calculate_total()
return self.payment_strategy.pay(total)
# 使用示例
credit_card = CreditCardPayment('4111-1111-1111-1111', 'John Doe')
cart = ShoppingCart(credit_card)
cart.add_item(29.99)
cart.add_item(49.99)
print(cart.checkout()) # Paid 79.98 using credit card...
# 切换支付策略
paypal = PayPalPayment('john.doe@example.com')
cart.set_payment_strategy(paypal)
print(cart.checkout()) # Paid 79.98 using PayPal...
4. 代理模式 (Proxy)
代理模式为其他对象提供一种代理以控制对这个对象的访问。常用于延迟加载、权限控制、日志记录等场景。
javascript
// 真实主题
class RealImage {
constructor(filename) {
this.filename = filename;
this.loadFromDisk(); // 模拟加载 heavy 资源
}
loadFromDisk() {
console.log(`Loading image: ${this.filename}`);
}
display() {
console.log(`Displaying image: ${this.filename}`);
}
}
// 代理
class ImageProxy {
constructor(filename) {
this.filename = filename;
this.realImage = null; // 延迟初始化
}
display() {
// 只有在需要时才创建真实对象
if (!this.realImage) {
this.realImage = new RealImage(this.filename);
}
this.realImage.display();
}
}
// 使用示例
// 图片不会立即加载
const proxyImage = new ImageProxy('large_image.jpg');
// 第一次调用display()时才会加载图片
console.log("First display:");
proxyImage.display();
// 第二次调用display()时不会重新加载
console.log("Second display:");
proxyImage.display();
java
// 主题接口
interface Image {
void display();
}
// 真实主题
class RealImage implements Image {
private String filename;
public RealImage(String filename) {
this.filename = filename;
loadFromDisk(); // 模拟加载 heavy 资源
}
private void loadFromDisk() {
System.out.println("Loading image: " + filename);
}
@Override
public void display() {
System.out.println("Displaying image: " + filename);
}
}
// 代理
class ImageProxy implements Image {
private String filename;
private RealImage realImage; // 延迟初始化
public ImageProxy(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 ImageProxy("large_image.jpg");
// 第一次调用display()时才会加载图片
System.out.println("First display:");
image.display();
// 第二次调用display()时不会重新加载
System.out.println("Second display:");
image.display();
}
}
python
# 主题接口
from abc import ABC, abstractmethod
class Image(ABC):
@abstractmethod
def display(self):
pass
# 真实主题
class RealImage(Image):
def __init__(self, filename):
self.filename = filename
self._load_from_disk() # 模拟加载 heavy 资源
def _load_from_disk(self):
print(f"Loading image: {self.filename}")
def display(self):
print(f"Displaying image: {self.filename}")
# 代理
class ImageProxy(Image):
def __init__(self, filename):
self.filename = filename
self._real_image = None # 延迟初始化
def display(self):
# 只有在需要时才创建真实对象
if self._real_image is None:
self._real_image = RealImage(self.filename)
self._real_image.display()
# 使用示例
# 图片不会立即加载
proxy_image = ImageProxy('large_image.jpg')
# 第一次调用display()时才会加载图片
print("First display:")
proxy_image.display()
# 第二次调用display()时不会重新加载
print("Second display:")
proxy_image.display()
5. 中介者模式 (Mediator)
中介者模式定义一个对象来封装一系列对象的交互方式。它使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。
javascript
// 中介者
class ChatRoom {
showMessage(user, message) {
const time = new Date().toLocaleTimeString();
const userName = user.getName();
console.log(`[${time}] ${userName}: ${message}`);
}
}
// 同事类
class User {
constructor(name, chatRoom) {
this.name = name;
this.chatRoom = chatRoom;
}
getName() {
return this.name;
}
sendMessage(message) {
this.chatRoom.showMessage(this, message);
}
}
// 使用示例
const chatRoom = new ChatRoom();
const user1 = new User("Alice", chatRoom);
const user2 = new User("Bob", chatRoom);
const user3 = new User("Charlie", chatRoom);
user1.sendMessage("Hi, everyone!");
user2.sendMessage("Hello, Alice!");
user3.sendMessage("What's up?");
java
// 中介者
class ChatRoom {
public void showMessage(User user, String message) {
String time = java.time.LocalTime.now().toString();
String userName = user.getName();
System.out.printf("[%s] %s: %s%n", time, userName, message);
}
}
// 同事类
class User {
private String name;
private ChatRoom chatRoom;
public User(String name, ChatRoom chatRoom) {
this.name = name;
this.chatRoom = chatRoom;
}
public String getName() {
return name;
}
public void sendMessage(String message) {
chatRoom.showMessage(this, message);
}
}
// 使用示例
public class Main {
public static void main(String[] args) {
ChatRoom chatRoom = new ChatRoom();
User user1 = new User("Alice", chatRoom);
User user2 = new User("Bob", chatRoom);
User user3 = new User("Charlie", chatRoom);
user1.sendMessage("Hi, everyone!");
user2.sendMessage("Hello, Alice!");
user3.sendMessage("What's up?");
}
}
python
import datetime
# 中介者
class ChatRoom:
def show_message(self, user, message):
time = datetime.datetime.now().strftime("%H:%M:%S")
user_name = user.get_name()
print(f"[{time}] {user_name}: {message}")
# 同事类
class User:
def __init__(self, name, chat_room):
self.name = name
self.chat_room = chat_room
def get_name(self):
return self.name
def send_message(self, message):
self.chat_room.show_message(self, message)
# 使用示例
chat_room = ChatRoom()
user1 = User("Alice", chat_room)
user2 = User("Bob", chat_room)
user3 = User("Charlie", chat_room)
user1.send_message("Hi, everyone!")
user2.send_message("Hello, Alice!")
user3.send_message("What's up?")
6. 装饰者模式 (Decorator)
装饰者模式动态地给一个对象添加一些额外的职责。就增加功能来说,装饰者模式比生成子类更为灵活。
javascript
// 组件接口
class Beverage {
getDescription() {
return 'Unknown Beverage';
}
cost() {
return 0;
}
}
// 具体组件
class Espresso extends Beverage {
getDescription() {
return 'Espresso';
}
cost() {
return 1.99;
}
}
class HouseBlend extends Beverage {
getDescription() {
return 'House Blend Coffee';
}
cost() {
return 0.89;
}
}
// 装饰者
class Decorator extends Beverage {
constructor(beverage) {
super();
this.beverage = beverage;
}
getDescription() {
return this.beverage.getDescription();
}
cost() {
return this.beverage.cost();
}
}
// 具体装饰者
class Milk extends Decorator {
constructor(beverage) {
super(beverage);
}
getDescription() {
return super.getDescription() + ', Milk';
}
cost() {
return super.cost() + 0.10;
}
}
class Mocha extends Decorator {
constructor(beverage) {
super(beverage);
}
getDescription() {
return super.getDescription() + ', Mocha';
}
cost() {
return super.cost() + 0.20;
}
}
// 使用示例
let beverage = new Espresso();
console.log(`${beverage.getDescription()} $${beverage.cost().toFixed(2)}`);
// 装饰Espresso
beverage = new Mocha(new Milk(new Espresso()));
console.log(`${beverage.getDescription()} $${beverage.cost().toFixed(2)}`);
// 装饰HouseBlend
beverage = new Mocha(new Mocha(new Milk(new HouseBlend())));
console.log(`${beverage.getDescription()} $${beverage.cost().toFixed(2)}`);
java
// 组件接口
abstract class Beverage {
String description = "Unknown Beverage";
public String getDescription() {
return description;
}
public abstract double cost();
}
// 具体组件
class Espresso extends Beverage {
public Espresso() {
description = "Espresso";
}
@Override
public double cost() {
return 1.99;
}
}
class HouseBlend extends Beverage {
public HouseBlend() {
description = "House Blend Coffee";
}
@Override
public double cost() {
return 0.89;
}
}
// 装饰者
abstract class CondimentDecorator extends Beverage {
public abstract String getDescription();
}
// 具体装饰者
class Milk extends CondimentDecorator {
Beverage beverage;
public Milk(Beverage beverage) {
this.beverage = beverage;
}
@Override
public String getDescription() {
return beverage.getDescription() + ", Milk";
}
@Override
public double cost() {
return beverage.cost() + 0.10;
}
}
class Mocha extends CondimentDecorator {
Beverage beverage;
public Mocha(Beverage beverage) {
this.beverage = beverage;
}
@Override
public String getDescription() {
return beverage.getDescription() + ", Mocha";
}
@Override
public double cost() {
return beverage.cost() + 0.20;
}
}
// 使用示例
public class Main {
public static void main(String[] args) {
Beverage beverage = new Espresso();
System.out.printf("%s $%.2f%n", beverage.getDescription(), beverage.cost());
// 装饰Espresso
Beverage beverage2 = new Mocha(new Milk(new Espresso()));
System.out.printf("%s $%.2f%n", beverage2.getDescription(), beverage2.cost());
// 装饰HouseBlend
Beverage beverage3 = new Mocha(new Mocha(new Milk(new HouseBlend())));
System.out.printf("%s $%.2f%n", beverage3.getDescription(), beverage3.cost());
}
}
python
# 组件接口
from abc import ABC, abstractmethod
class Beverage(ABC):
description = "Unknown Beverage"
def get_description(self):
return self.description
@abstractmethod
def cost(self):
pass
# 具体组件
class Espresso(Beverage):
def __init__(self):
self.description = "Espresso"
def cost(self):
return 1.99
class HouseBlend(Beverage):
def __init__(self):
self.description = "House Blend Coffee"
def cost(self):
return 0.89
# 装饰者
class CondimentDecorator(Beverage):
@abstractmethod
def get_description(self):
pass
# 具体装饰者
class Milk(CondimentDecorator):
def __init__(self, beverage):
self.beverage = beverage
def get_description(self):
return f"{self.beverage.get_description()}, Milk"
def cost(self):
return self.beverage.cost() + 0.10
class Mocha(CondimentDecorator):
def __init__(self, beverage):
self.beverage = beverage
def get_description(self):
return f"{self.beverage.get_description()}, Mocha"
def cost(self):
return self.beverage.cost() + 0.20
# 使用示例
beverage = Espresso()
print(f"{beverage.get_description()} ${beverage.cost():.2f}")
# 装饰Espresso
beverage2 = Mocha(Milk(Espresso()))
print(f"{beverage2.get_description()} ${beverage2.cost():.2f}")
# 装饰HouseBlend
beverage3 = Mocha(Mocha(Milk(HouseBlend())))
print(f"{beverage3.get_description()} ${beverage3.cost():.2f}")
总结
设计模式是解决特定问题的成熟方案,掌握它们可以帮助我们:
- 编写更具可读性和可维护性的代码
- 提高代码的复用性和灵活性
- 便于团队成员之间的沟通(使用共同的设计语言)
- 更好地应对需求变化
选择合适的设计模式需要根据具体问题场景,过度使用设计模式也可能导致代码复杂化。最好的做法是理解每种模式的适用场景,在实际开发中灵活运用。