Ruby中的设计模式应用案例解析
单例模式在 Ruby 中的应用
单例模式是一种创建型设计模式,它确保一个类仅有一个实例,并提供一个全局访问点。在 Ruby 中,实现单例模式有多种方式。
使用 Singleton
模块
Ruby 标准库提供了 Singleton
模块,使用它可以很方便地将一个类变成单例类。
require 'singleton'
class DatabaseConnection
include Singleton
def connect
puts "Connecting to the database..."
end
end
# 使用单例实例
connection1 = DatabaseConnection.instance
connection2 = DatabaseConnection.instance
puts connection1.object_id == connection2.object_id # 输出 true
connection1.connect
在上述代码中,通过 include Singleton
,DatabaseConnection
类变成了单例类。instance
方法用于获取该单例类的唯一实例。无论调用多少次 instance
方法,返回的都是同一个对象,这通过比较两个实例的 object_id
可以验证。
手动实现单例模式
不依赖 Singleton
模块,也可以手动实现单例模式。
class Logger
def self.instance
@instance ||= new
@instance
end
private_class_method :new
def log(message)
puts "[#{Time.now}] #{message}"
end
end
# 使用单例实例
logger1 = Logger.instance
logger2 = Logger.instance
puts logger1.object_id == logger2.object_id # 输出 true
logger1.log("This is a log message")
这里,通过定义一个类方法 instance
,在方法中使用 @instance ||= new
来确保只有一个实例被创建。同时,通过 private_class_method :new
防止外部直接调用 new
方法创建新的实例。
工厂模式在 Ruby 中的应用
工厂模式是一种创建型设计模式,它提供了一种创建对象的方式,将对象的创建和使用分离。
简单工厂模式
简单工厂模式定义了一个工厂类,用于创建产品对象。
class Animal
def speak
raise NotImplementedError, "Subclasses must implement #speak"
end
end
class Dog < Animal
def speak
"Woof!"
end
end
class Cat < Animal
def speak
"Meow!"
end
end
class AnimalFactory
def self.create_animal(type)
case type
when 'dog'
Dog.new
when 'cat'
Cat.new
else
raise ArgumentError, "Unsupported animal type: #{type}"
end
end
end
# 使用工厂创建动物
dog = AnimalFactory.create_animal('dog')
cat = AnimalFactory.create_animal('cat')
puts dog.speak # 输出 Woof!
puts cat.speak # 输出 Meow!
在这段代码中,AnimalFactory
类是工厂类,create_animal
方法根据传入的类型参数创建相应的动物对象。这样,对象的创建逻辑集中在工厂类中,使用方只需要调用工厂方法获取对象,而不需要关心对象的具体创建过程。
工厂方法模式
工厂方法模式将对象的创建延迟到子类中实现。
class Shape
def draw
raise NotImplementedError, "Subclasses must implement #draw"
end
end
class Circle < Shape
def draw
puts "Drawing a circle"
end
end
class Rectangle < Shape
def draw
puts "Drawing a rectangle"
end
end
class ShapeFactory
def create_shape
raise NotImplementedError, "Subclasses must implement #create_shape"
end
end
class CircleFactory < ShapeFactory
def create_shape
Circle.new
end
end
class RectangleFactory < ShapeFactory
def create_shape
Rectangle.new
end
end
# 使用工厂创建形状
circle_factory = CircleFactory.new
circle = circle_factory.create_shape
circle.draw # 输出 Drawing a circle
rectangle_factory = RectangleFactory.new
rectangle = rectangle_factory.create_shape
rectangle.draw # 输出 Drawing a rectangle
这里,ShapeFactory
是抽象工厂类,定义了 create_shape
抽象方法。CircleFactory
和 RectangleFactory
是具体的工厂子类,分别实现 create_shape
方法来创建具体的形状对象。通过这种方式,不同类型对象的创建逻辑分布在不同的工厂子类中,增加了代码的可扩展性。
策略模式在 Ruby 中的应用
策略模式是一种行为型设计模式,它定义了一系列算法,将每个算法封装起来,并使它们可以相互替换。
class PaymentStrategy
def pay(amount)
raise NotImplementedError, "Subclasses must implement #pay"
end
end
class CreditCardPayment < PaymentStrategy
def initialize(card_number, expiration, cvv)
@card_number = card_number
@expiration = expiration
@cvv = cvv
end
def pay(amount)
puts "Paying $#{amount} with credit card #{@card_number} (expires #{@expiration}, CVV #{@cvv})"
end
end
class PayPalPayment < PaymentStrategy
def initialize(email)
@email = email
end
def pay(amount)
puts "Paying $#{amount} with PayPal account #{@email}"
end
end
class Order
def initialize(payment_strategy)
@payment_strategy = payment_strategy
end
def checkout(amount)
@payment_strategy.pay(amount)
end
end
# 使用不同的支付策略
credit_card = CreditCardPayment.new('1234567890123456', '12/25', '123')
paypal = PayPalPayment.new('user@example.com')
order1 = Order.new(credit_card)
order1.checkout(100) # 输出 Paying $100 with credit card 1234567890123456 (expires 12/25, CVV 123)
order2 = Order.new(paypal)
order2.checkout(200) # 输出 Paying $200 with PayPal account user@example.com
在上述代码中,PaymentStrategy
是抽象策略类,定义了 pay
抽象方法。CreditCardPayment
和 PayPalPayment
是具体的策略子类,实现了 pay
方法。Order
类接受一个支付策略对象,并在 checkout
方法中调用该策略的 pay
方法进行支付。这样,不同的支付策略可以方便地替换,而 Order
类的代码不需要修改。
观察者模式在 Ruby 中的应用
观察者模式是一种行为型设计模式,它定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。当主题对象状态发生变化时,会通知所有观察者对象,使它们能够自动更新。
class Subject
def initialize
@observers = []
end
def attach(observer)
@observers << observer
end
def detach(observer)
@observers.delete(observer)
end
def notify
@observers.each do |observer|
observer.update(self)
end
end
end
class Observer
def update(subject)
raise NotImplementedError, "Subclasses must implement #update"
end
end
class ConcreteSubject < Subject
def initialize
super
@state = nil
end
def state=(new_state)
@state = new_state
notify
end
def state
@state
end
end
class ConcreteObserver < Observer
def initialize(name)
@name = name
end
def update(subject)
puts "#{@name} observed a state change: #{subject.state}"
end
end
# 使用观察者模式
subject = ConcreteSubject.new
observer1 = ConcreteObserver.new('Observer 1')
observer2 = ConcreteObserver.new('Observer 2')
subject.attach(observer1)
subject.attach(observer2)
subject.state = 'new state'
# 输出 Observer 1 observed a state change: new state
# 输出 Observer 2 observed a state change: new state
在这段代码中,Subject
类是主题类,维护了一个观察者列表,并提供了添加、移除观察者和通知观察者的方法。Observer
类是抽象观察者类,定义了 update
抽象方法。ConcreteSubject
是具体主题类,当 state
发生变化时会通知观察者。ConcreteObserver
是具体观察者类,实现了 update
方法来处理主题状态变化的通知。
装饰器模式在 Ruby 中的应用
装饰器模式是一种结构型设计模式,它允许向一个现有的对象添加新的功能,同时又不改变其结构。
class Beverage
def cost
raise NotImplementedError, "Subclasses must implement #cost"
end
def description
raise NotImplementedError, "Subclasses must implement #description"
end
end
class Coffee < Beverage
def cost
2.0
end
def description
'Coffee'
end
end
class MilkDecorator < Beverage
def initialize(beverage)
@beverage = beverage
end
def cost
@beverage.cost + 0.5
end
def description
"#{@beverage.description}, with milk"
end
end
class SugarDecorator < Beverage
def initialize(beverage)
@beverage = beverage
end
def cost
@beverage.cost + 0.2
end
def description
"#{@beverage.description}, with sugar"
end
end
# 使用装饰器模式
coffee = Coffee.new
puts "Cost: #{coffee.cost}, Description: #{coffee.description}" # 输出 Cost: 2.0, Description: Coffee
coffee_with_milk = MilkDecorator.new(coffee)
puts "Cost: #{coffee_with_milk.cost}, Description: #{coffee_with_milk.description}" # 输出 Cost: 2.5, Description: Coffee, with milk
coffee_with_milk_and_sugar = SugarDecorator.new(coffee_with_milk)
puts "Cost: #{coffee_with_milk_and_sugar.cost}, Description: #{coffee_with_milk_and_sugar.description}" # 输出 Cost: 2.7, Description: Coffee, with milk, with sugar
在上述代码中,Beverage
是抽象组件类,定义了 cost
和 description
抽象方法。Coffee
是具体组件类。MilkDecorator
和 SugarDecorator
是装饰器类,它们接受一个 Beverage
对象,并在其基础上添加新的功能(增加成本和修改描述)。通过层层装饰,可以为对象动态地添加不同的功能。
代理模式在 Ruby 中的应用
代理模式是一种结构型设计模式,它为其他对象提供一种代理以控制对这个对象的访问。
class RealImage
def initialize(filename)
@filename = filename
load_image
end
def display
puts "Displaying #{@filename}"
end
private
def load_image
puts "Loading #{@filename}"
end
end
class ImageProxy
def initialize(filename)
@filename = filename
@real_image = nil
end
def display
@real_image ||= RealImage.new(@filename)
@real_image.display
end
end
# 使用代理模式
proxy = ImageProxy.new('image.jpg')
# 此时尚未真正加载图片
proxy.display # 输出 Loading image.jpg, Displaying image.jpg
在这段代码中,RealImage
类是实际的对象,它在初始化时会加载图片(这里通过 load_image
方法模拟加载过程)。ImageProxy
类是代理类,它持有一个 RealImage
对象的引用,但只有在调用 display
方法时才会真正创建 RealImage
对象。这样可以在需要时才加载实际对象,提高系统的性能和资源利用率。
模板方法模式在 Ruby 中的应用
模板方法模式是一种行为型设计模式,它定义了一个操作中的算法的骨架,而将一些步骤延迟到子类中。子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
class AbstractClass
def template_method
step1
step2
step3
end
def step1
puts "AbstractClass: Step 1 implementation"
end
def step2
raise NotImplementedError, "Subclasses must implement #step2"
end
def step3
puts "AbstractClass: Step 3 implementation"
end
end
class ConcreteClass < AbstractClass
def step2
puts "ConcreteClass: Step 2 implementation"
end
end
# 使用模板方法模式
concrete = ConcreteClass.new
concrete.template_method
# 输出 AbstractClass: Step 1 implementation
# 输出 ConcreteClass: Step 2 implementation
# 输出 AbstractClass: Step 3 implementation
在上述代码中,AbstractClass
定义了 template_method
方法,它包含了算法的骨架,由 step1
、step2
和 step3
组成。其中 step1
和 step3
有默认实现,而 step2
是抽象方法,需要子类实现。ConcreteClass
是子类,实现了 step2
方法。通过这种方式,子类可以在不改变算法整体结构的情况下,定制算法的特定步骤。
组合模式在 Ruby 中的应用
组合模式是一种结构型设计模式,它将对象组合成树形结构以表示“部分 - 整体”的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。
class Component
def initialize(name)
@name = name
end
def add(component)
raise NotImplementedError, "Subclasses must implement #add"
end
def remove(component)
raise NotImplementedError, "Subclasses must implement #remove"
end
def display
raise NotImplementedError, "Subclasses must implement #display"
end
end
class Leaf < Component
def add(component)
raise "Cannot add to a leaf"
end
def remove(component)
raise "Cannot remove from a leaf"
end
def display
puts "Leaf: #{@name}"
end
end
class Composite < Component
def initialize(name)
super
@children = []
end
def add(component)
@children << component
end
def remove(component)
@children.delete(component)
end
def display
puts "Composite: #{@name}"
@children.each do |child|
child.display
end
end
end
# 使用组合模式
root = Composite.new('Root')
branch1 = Composite.new('Branch 1')
branch2 = Composite.new('Branch 2')
leaf1 = Leaf.new('Leaf 1')
leaf2 = Leaf.new('Leaf 2')
root.add(branch1)
root.add(branch2)
branch1.add(leaf1)
branch2.add(leaf2)
root.display
# 输出 Composite: Root
# 输出 Composite: Branch 1
# 输出 Leaf: Leaf 1
# 输出 Composite: Branch 2
# 输出 Leaf: Leaf 2
在这段代码中,Component
是抽象类,定义了添加、移除和显示的抽象方法。Leaf
类是叶子节点,它不能包含其他组件,因此 add
和 remove
方法会抛出异常。Composite
类是组合节点,它可以包含其他组件,并实现了添加、移除和显示方法。通过组合模式,可以方便地构建和操作具有层次结构的对象。
桥接模式在 Ruby 中的应用
桥接模式是一种结构型设计模式,它将抽象部分与它的实现部分分离,使它们都可以独立地变化。
class Abstraction
def initialize(implementation)
@implementation = implementation
end
def operation
@implementation.operation_implementation
end
end
class RefinedAbstraction < Abstraction
def operation
"Refined " + super
end
end
class Implementation
def operation_implementation
raise NotImplementedError, "Subclasses must implement #operation_implementation"
end
end
class ConcreteImplementationA < Implementation
def operation_implementation
"ConcreteImplementationA"
end
end
class ConcreteImplementationB < Implementation
def operation_implementation
"ConcreteImplementationB"
end
end
# 使用桥接模式
implementation_a = ConcreteImplementationA.new
abstraction = Abstraction.new(implementation_a)
puts abstraction.operation # 输出 ConcreteImplementationA
implementation_b = ConcreteImplementationB.new
refined_abstraction = RefinedAbstraction.new(implementation_b)
puts refined_abstraction.operation # 输出 Refined ConcreteImplementationB
在上述代码中,Abstraction
类持有一个 Implementation
对象的引用,并通过 operation
方法调用 Implementation
的 operation_implementation
方法。RefinedAbstraction
是 Abstraction
的子类,进一步扩展了 operation
方法。Implementation
是抽象实现类,定义了 operation_implementation
抽象方法。ConcreteImplementationA
和 ConcreteImplementationB
是具体实现类,实现了 operation_implementation
方法。通过桥接模式,抽象部分和实现部分可以独立变化,提高了代码的灵活性和可维护性。
解释器模式在 Ruby 中的应用
解释器模式是一种行为型设计模式,它给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。
class Context
def initialize
@variables = {}
end
def set_variable(name, value)
@variables[name] = value
end
def get_variable(name)
@variables[name]
end
end
class Expression
def interpret(context)
raise NotImplementedError, "Subclasses must implement #interpret"
end
end
class VariableExpression < Expression
def initialize(name)
@name = name
end
def interpret(context)
context.get_variable(@name)
end
end
class AddExpression < Expression
def initialize(left, right)
@left = left
@right = right
end
def interpret(context)
@left.interpret(context) + @right.interpret(context)
end
end
# 使用解释器模式
context = Context.new
context.set_variable('x', 5)
context.set_variable('y', 3)
x = VariableExpression.new('x')
y = VariableExpression.new('y')
add_expression = AddExpression.new(x, y)
puts add_expression.interpret(context) # 输出 8
在这段代码中,Context
类用于存储变量的值。Expression
是抽象表达式类,定义了 interpret
抽象方法。VariableExpression
表示变量表达式,它从 Context
中获取变量的值。AddExpression
表示加法表达式,它将左右两个表达式的值相加。通过这种方式,可以构建一个简单的表达式解释器,对特定语言的句子进行解释。
备忘录模式在 Ruby 中的应用
备忘录模式是一种行为型设计模式,它在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态。
class Originator
def initialize(state)
@state = state
end
def state
@state
end
def state=(new_state)
@state = new_state
end
def create_memento
Memento.new(@state)
end
def restore_memento(memento)
@state = memento.state
end
end
class Memento
def initialize(state)
@state = state
end
def state
@state
end
end
class Caretaker
def initialize(originator)
@originator = originator
@mementos = []
end
def save_state
memento = @originator.create_memento
@mementos << memento
end
def restore_state(index)
memento = @mementos[index]
@originator.restore_memento(memento)
end
end
# 使用备忘录模式
originator = Originator.new('State 1')
caretaker = Caretaker.new(originator)
caretaker.save_state
originator.state = 'State 2'
caretaker.restore_state(0)
puts originator.state # 输出 State 1
在上述代码中,Originator
类是需要保存和恢复状态的对象,它提供了创建备忘录和从备忘录恢复状态的方法。Memento
类用于保存 Originator
的状态。Caretaker
类负责管理备忘录,包括保存状态和恢复状态。通过备忘录模式,可以在不破坏 Originator
封装性的情况下,实现对象状态的保存和恢复。
状态模式在 Ruby 中的应用
状态模式是一种行为型设计模式,它允许对象在内部状态改变时改变它的行为,对象看起来好像修改了它的类。
class State
def handle(context)
raise NotImplementedError, "Subclasses must implement #handle"
end
end
class ConcreteStateA < State
def handle(context)
puts "ConcreteStateA handles request"
context.state = ConcreteStateB.new
end
end
class ConcreteStateB < State
def handle(context)
puts "ConcreteStateB handles request"
context.state = ConcreteStateA.new
end
end
class Context
def initialize
@state = ConcreteStateA.new
end
def state=(new_state)
@state = new_state
end
def request
@state.handle(self)
end
end
# 使用状态模式
context = Context.new
context.request # 输出 ConcreteStateA handles request
context.request # 输出 ConcreteStateB handles request
在这段代码中,State
是抽象状态类,定义了 handle
抽象方法。ConcreteStateA
和 ConcreteStateB
是具体状态类,实现了 handle
方法,在处理请求时会改变 Context
的状态。Context
类持有一个状态对象,并通过 request
方法调用当前状态的 handle
方法。通过状态模式,对象的行为可以根据其内部状态的变化而改变。
访问者模式在 Ruby 中的应用
访问者模式是一种行为型设计模式,它表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。
class Element
def accept(visitor)
raise NotImplementedError, "Subclasses must implement #accept"
end
end
class ConcreteElementA < Element
def accept(visitor)
visitor.visit_concrete_element_a(self)
end
def operation_a
"Operation A of ConcreteElementA"
end
end
class ConcreteElementB < Element
def accept(visitor)
visitor.visit_concrete_element_b(self)
end
def operation_b
"Operation B of ConcreteElementB"
end
end
class Visitor
def visit_concrete_element_a(element)
raise NotImplementedError, "Subclasses must implement #visit_concrete_element_a"
end
def visit_concrete_element_b(element)
raise NotImplementedError, "Subclasses must implement #visit_concrete_element_b"
end
end
class ConcreteVisitor < Visitor
def visit_concrete_element_a(element)
puts "ConcreteVisitor visiting #{element.operation_a}"
end
def visit_concrete_element_b(element)
puts "ConcreteVisitor visiting #{element.operation_b}"
end
end
# 使用访问者模式
element_a = ConcreteElementA.new
element_b = ConcreteElementB.new
visitor = ConcreteVisitor.new
element_a.accept(visitor) # 输出 ConcreteVisitor visiting Operation A of ConcreteElementA
element_b.accept(visitor) # 输出 ConcreteVisitor visiting Operation B of ConcreteElementB
在上述代码中,Element
是抽象元素类,定义了 accept
抽象方法。ConcreteElementA
和 ConcreteElementB
是具体元素类,实现了 accept
方法,用于接受访问者。Visitor
是抽象访问者类,定义了访问不同具体元素的抽象方法。ConcreteVisitor
是具体访问者类,实现了这些访问方法。通过访问者模式,可以在不改变元素类的情况下,为元素添加新的操作。