装饰器模式是一种结构型设计模式,它允许你在不改变对象接口的情况下动态地给对象添加职责。装饰器模式通过创建一系列包装类,每个包装类都封装一个被装饰的对象,并且每个包装类都可以添加新的功能。
背景
在 Ruby 中,装饰器模式通常用于需要动态地为对象添加行为的场景。这与子类化不同,因为子类化是静态的,而装饰器模式则提供了动态扩展功能的能力。
实现装饰器模式
创建基础组件
首先,我们需要定义一个基础组件接口,所有的具体组件和装饰器都应该实现这个接口。
class Component
def operation
raise NotImplementedError, "#{self.class} has not implemented method '#{__method__}'"
end
end创建具体组件
接着,我们创建一个具体的组件类,这个类实现了基础组件接口,并提供了一些基本的行为。
class ConcreteComponent < Component
def operation
'ConcreteComponent'
end
end创建装饰器基类
接下来,我们创建一个装饰器基类,该基类也实现了基础组件接口,并且包含了对被装饰对象的引用。
// www.javascriptcn.com code example
class Decorator < Component
attr_accessor :component
def initialize(component)
@component = component
end
def operation
@component.operation
end
end创建具体装饰器
最后,我们创建具体的装饰器类,这些类继承自装饰器基类,并且可以添加额外的功能。
// www.javascriptcn.com code example
class ConcreteDecoratorA < Decorator
def operation
"ConcreteDecoratorA(#{super})"
end
end
class ConcreteDecoratorB < Decorator
def operation
"ConcreteDecoratorB(#{super})"
end
end使用装饰器模式
现在我们可以使用上面定义的类来动态地为对象添加功能了。
// www.javascriptcn.com code example # 创建一个具体组件 basic_component = ConcreteComponent.new # 使用装饰器 A 包装它 decorated_component_a = ConcreteDecoratorA.new(basic_component) # 再使用装饰器 B 包装它 decorated_component_b = ConcreteDecoratorB.new(decorated_component_a) # 输出最终的结果 puts decorated_component_b.operation # 输出: ConcreteDecoratorB(ConcreteDecoratorA(ConcreteComponent))
在这个例子中,我们首先创建了一个基础的 ConcreteComponent 对象,然后使用 ConcreteDecoratorA 和 ConcreteDecoratorB 依次对其进行包装。这样,我们就能够动态地给对象添加功能,而不必修改其原始代码。
总结
装饰器模式提供了一种比子类化更灵活的方式来动态地给对象添加功能。这种模式非常适合那些需要在运行时改变对象行为的应用场景。通过这种方式,你可以保持代码的清晰和可维护性,同时又能灵活地应对需求的变化。