装饰模式例子

本文介绍了Java中装饰器模式的应用实例,通过实现组件接口和装饰接口,展示如何动态地扩展对象的功能。具体展示了如何创建具体组件类和装饰类,并通过组合实现功能扩展。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

package io;

public interface Component
{
public void doSomething();
}


package io;


public class ConcreteComponent implements Component
{
@Override
public void doSomething()
{
System.out.println("功能A");
}


}

package io;
public class Decorator implements Component
{
	private Component component;
	
	public Decorator(Component component)
	{
		this.component = component;
	}
	
	@Override
	public void doSomething()
	{
		component.doSomething();
	}
}

package io;

public class ConcreteDecorator1 extends Decorator
{
	public ConcreteDecorator1(Component component)
	{
		super(component);
	}
	
	@Override
	public void doSomething()
	{
		super.doSomething();
		
		this.doAnotherThing();
	}
	
	private void doAnotherThing()
	{
		System.out.println("功能B");
	}

}



package io;


public class ConcreteDecorator2 extends Decorator
{
public ConcreteDecorator2(Component component)
{
super(component);
}

@Override
public void doSomething()
{
super.doSomething();

this.doAnotherThing();
}

private void doAnotherThing()
{
System.out.println("功能C");
}
}




package io;


public class Client
{
public static void main(String[] args)
{
/*
* //节点流 Component component = new ConcreteComponent();
* 
* //过滤流 Component component2 = new ConcreteDecorator1(component);
* 
* component2.doSomething();
* 
* System.out.println("------------");
* 
* //过滤流 Component component3 = new ConcreteDecorator2(component2);
* 
* component3.doSomething();
*/


Component component = new ConcreteDecorator1(new ConcreteDecorator2(
new ConcreteComponent()));


component.doSomething();
}
}


<think>我们正在讨论C++中的装饰器模式。根据引用内容,装饰器模式用于动态地给对象添加额外的职责,而不改变其结构。它通过创建一个包装对象(装饰器)来包裹真实对象,并在转发请求前后执行额外操作。使用场景包括:动态添加功能(如日志、权限检查)、图形界面组件扩展(如添加边框、滚动条)等(引用[3][4])。示例代码结构通常包含:1.组件接口(抽象基类)2.具体组件(实现基本功能)3.装饰器基类(继承组件接口,并包含一个指向组件对象的指针)4.具体装饰器(实现额外的功能)下面我们提供一个C++的装饰器模式示例,该示例模拟文本格式的添加(如加粗、斜体、下划线)。注意:在C++中,我们需要注意内存管理,这里为了简洁使用原始指针,实际应用中可以考虑智能指针。代码示例: ```cpp#include <iostream>#include <string>//抽象组件:定义文本渲染接口class Text{ public:virtual ~Text(){}virtual std::stringrender()const =0; };//具体组件:纯文本class PlainText :public Text{ private:std::string text; public:PlainText(const std::string& t) :text(t) {}std::stringrender()const override{return text;} };//抽象装饰器:继承Text,并包含一个Text指针classTextDecorator :public Text{ protected:Text*text;//被装饰的文本对象public:TextDecorator(Text* t) :text(t) {}virtual~TextDecorator() {deletetext;//释放内存,注意:这里假设TextDecorator拥有text对象的所有权}//默认实现:调用被装饰对象的render方法std::stringrender()const override{return text->render();} };//具体装饰器:加粗classBoldText: publicTextDecorator {public:BoldText(Text*t): TextDecorator(t){}std::string render() constoverride {return"<b>" +text->render() +"</b>";} };//具体装饰器:斜体classItalicText :public TextDecorator{ public:ItalicText(Text*t): TextDecorator(t){}std::string render() constoverride {return"<i>" +text->render()+ "</i>";}}; //具体装饰器:下划线class UnderlineText: publicTextDecorator {public:UnderlineText(Text* t) :TextDecorator(t) {}std::stringrender()const override{return "<u>"+ text->render() +"</u>";} };int main() {//创建原始文本Text*plain =new PlainText("Hello,World!");//动态添加装饰:加粗、斜体、下划线Text*decorated =new UnderlineText(new ItalicText(new BoldText(plain)));//注意:上面的装饰链中,plain已经被最内层的BoldText所拥有,所以不需要再单独释放plain//渲染并输出std::cout<< decorated->render() <<std::endl;//释放内存(装饰器链的释放:最外层的装饰器在析构时会逐层释放内层的对象)deletedecorated;return0; }```解释:1. `Text`是抽象组件,定义了渲染接口。2.`PlainText`是具体组件,实现基本的文本渲染。3. `TextDecorator`是抽象装饰器,它继承自`Text`并包含一个指向`Text`的指针。它维护了对组件的引用,并将请求转发给组件。4.具体装饰器(`BoldText`、`ItalicText`、`UnderlineText`)重了`render`方法,在调用组件的`render`方法前后添加了额外的格式(这里用HTML标签模拟)。在`main`函数中,我们创建了一个纯文本对象,然后用装饰器动态地给它添加格式。装饰器可以嵌套,从而组合多个功能。注意:上面的代码中,装饰器在析构时释放了它所持有的组件对象(在`TextDecorator`的析构函数中)。这样,我们只需要释放最外层的装饰器,整个链都会被正确释放。但是,如果同一个组件被多个装饰器共享,则不能这样设计,需要改用共享指针。这里我们假设装饰器独占组件对象。使用场景:1.当需要动态、透明地给对象添加职责时(即不影响其他对象)。2.当不能通过子类扩展(或子类扩展不切实际)时。例如,扩展功能可能有很多种组合,使用子类会导致类爆炸(引用[3])。例如,在图形界面中,我们可以有一个基本的窗口组件,然后通过装饰器添加滚动条、边框等。每个装饰器都可以独立使用,也可以组合使用。优缺点:优点:比继承更灵活,可以动态添加和删除职责,避免子类爆炸。缺点:多层装饰会增加系统复杂性,且调试困难。根据引用[3][4][5],装饰模式在需要遵循开放/封闭原则(对扩展开放,对修改封闭)的场景中非常有用。希望这个示例能帮助你理解装饰器模式在C++中的实现和使用。 §§相关问题§§1.装饰器模式与继承相比有什么优势? 2.装饰器模式在什么情况下会导致内存管理复杂? 3.如何避免装饰器模式中的多层装饰导致的复杂性?4.装饰器模式能否用于添加新的方法(而不仅仅是增强已有方法)? 5.在C++中,使用智能指针实现装饰器模式有什么好处?</think>### C++ 装饰模式详解 #### 基本概念 装饰模式(Decorator Pattern)是一种结构型设计模式,允许**动态地向对象添加新功能**而不改变其结构。核心思想是通过创建**包装对象**(装饰器)来包裹真实对象,在转发请求前后执行额外操作[^3]。 #### 使用场景 1. **动态扩展功能**:运行时添加日志记录、权限检查等(如引用[4]) 2. **避免子类爆炸**:当多种功能组合会导致类数量激增时(如引用[1]) 3. **GUI组件增强**:为窗口/按钮添加边框、滚动条等(如引用[3][4]) 4. **遵循开放封闭原则**:扩展功能时不修改原有代码(如引用[4]) #### 示例代码(文本格式化装饰器) ```cpp #include <iostream> #include <string> // 抽象组件接口 class Text { public: virtual ~Text() = default; virtual std::string render() const = 0; }; // 具体组件:纯文本 class PlainText : public Text { std::string content; public: explicit PlainText(std::string str) : content(std::move(str)) {} std::string render() const override { return content; } }; // 抽象装饰器基类 class TextDecorator : public Text { protected: Text* wrapped; // 被装饰对象 public: explicit TextDecorator(Text* txt) : wrapped(txt) {} ~TextDecorator() override { delete wrapped; } }; // 具体装饰器:加粗文本 class BoldText : public TextDecorator { public: using TextDecorator::TextDecorator; std::string render() const override { return "<b>" + wrapped->render() + "</b>"; } }; // 具体装饰器:斜体文本 class ItalicText : public TextDecorator { public: using TextDecorator::TextDecorator; std::string render() const override { return "<i>" + wrapped->render() + "</i>"; } }; // 具体装饰器:下划线文本 class UnderlineText : public TextDecorator { public: using TextDecorator::TextDecorator; std::string render() const override { return "<u>" + wrapped->render() + "</u>"; } }; int main() { // 创建基础文本 Text* text = new PlainText("Hello Design Patterns"); // 动态添加装饰 text = new BoldText(text); // 加粗 text = new ItalicText(text); // 斜体 text = new UnderlineText(text); // 下划线 // 渲染结果:<u><i><b>Hello Design Patterns</b></i></u> std::cout << text->render() << std::endl; delete text; // 释放内存 return 0; } ``` #### 关键设计点 1. **双重继承**:装饰器同时继承组件接口和包含组件对象(组合关系) 2. **透明性**:装饰器与原始组件接口一致,客户端无感知 3. **动态嵌套**:装饰器可多层嵌套,实现功能组合 4. **内存管理**:装饰器负责管理其包裹对象的内存(示例中通过析构函数实现) #### 优缺点对比 | **优点** | **缺点** | |------------------------------|--------------------------| | 避免子类爆炸问题 | 多层装饰增加调试难度 | | 动态添加/移除功能 | 可能产生大量小对象 | | 符合开闭原则 | 装饰顺序影响结果 | | 功能组合比继承更灵活 | 初始化配置较复杂 | > 当需要为对象添加多个独立扩展功能时,装饰模式比继承更灵活,能有效避免类数量指数级增长[^1][^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值