哈尔滨网站建设有限公司,优秀的室内设计案例,网站建设服务案例,wordpress 安全性设置装饰模式#xff08;Decorator Pattern#xff09;详解一、装饰模式简介
装饰模式#xff08;Decorator Pattern#xff09; 是一种 结构型设计模式#xff0c;它允许你动态地给对象添加行为或职责#xff0c;而无需修改其源代码#xff0c;也不需要使用继承来扩展功能。…装饰模式Decorator Pattern详解一、装饰模式简介
装饰模式Decorator Pattern 是一种 结构型设计模式它允许你动态地给对象添加行为或职责而无需修改其源代码也不需要使用继承来扩展功能。
是一种用于替代继承的技术它通过一种无须定义子类的方式给对象动态增加职责使用对象之间的关联关系取代类之间的继承关系
引入了装饰类在装饰类中既可以调用待装饰的原有类的方法还可以增加新的方法以扩展原有类的功能
你可以把它理解为“在不改变原对象的前提下为其添加新功能的方式”。与继承不同的是装饰模式是运行时动态组合的更加灵活。
动态地给一个对象增加一些额外的职责。就扩展功能而言装饰模式提供了一种比使用子类更加灵活的替代方案。
以对客户透明的方式动态地给一个对象附加上更多的责任
可以在不需要创建更多子类的情况下让对象的功能得以扩展
装饰模式的结构
装饰模式包含以下4个角色
Component抽象构件
ConcreteComponent具体构件
Decorator抽象装饰类
ConcreteDecorator具体装饰类二、解决的问题类型
装饰模式主要用于解决以下问题
当子类扩展不再适用比如当你有多个可选功能并且这些功能可以自由组合时如果用继承方式实现会导致类爆炸。希望以透明和动态的方式给对象添加职责不需要修改客户端代码就可以为对象添加新的功能。保持类责任清晰每个装饰器只关注一个功能符合单一职责原则。三、使用场景
你想在不影响其他对象的情况下动态、透明地给某个对象添加职责。你需要在运行时决定是否添加某个功能甚至多次添加多个功能。替代多重继承的方案避免由于多层继承导致的类爆炸问题。Java I/O 流系统中广泛使用装饰者模式如 BufferedInputStream 包裹 FileInputStream。当不能采用继承的方式对系统进行扩展或者采用继承不利于系统扩展和维护时可以使用装饰模式四、实际生活案例
想象你在点一杯咖啡
基础咖啡美式咖啡Espresso可选配料牛奶Milk、摩卡Mocha、奶油Whip
每种配料都可以看作是对咖啡的“装饰”你可以选择加一样也可以叠加多种最终价格也会随之变化。
这种“基础 动态添加”的场景非常适合使用装饰模式。五、代码案例
我们通过一个简单的咖啡加料的例子来演示装饰模式。
1. 定义组件接口
// 组件接口饮料
interface Beverage {double cost(); // 价格String description(); // 描述
}2. 实现具体组件基础对象
// 具体组件美式咖啡
class Espresso implements Beverage {Overridepublic double cost() {return 2.0;}Overridepublic String description() {return Espresso;}
}3. 抽象装饰器类所有装饰器的基础
// 抽象装饰器类
abstract class BeverageDecorator implements Beverage {protected Beverage decoratedBeverage;public BeverageDecorator(Beverage decoratedBeverage) {this.decoratedBeverage decoratedBeverage;}Overridepublic double cost() {return decoratedBeverage.cost();}Overridepublic String description() {return decoratedBeverage.description();}
}4. 具体装饰器类装饰行为
// 加牛奶的装饰器
class MilkDecorator extends BeverageDecorator {public MilkDecorator(Beverage decoratedBeverage) {super(decoratedBeverage);}Overridepublic double cost() {return super.cost() 0.5;}Overridepublic String description() {return super.description() , Milk;}
}// 加摩卡的装饰器
class MochaDecorator extends BeverageDecorator {public MochaDecorator(Beverage decoratedBeverage) {super(decoratedBeverage);}Overridepublic double cost() {return super.cost() 0.7;}Overridepublic String description() {return super.description() , Mocha;}
}// 加奶油的装饰器
class WhipDecorator extends BeverageDecorator {public WhipDecorator(Beverage decoratedBeverage) {super(decoratedBeverage);}Overridepublic double cost() {return super.cost() 0.6;}Overridepublic String description() {return super.description() , Whip;}
}5. 客户端调用示例
public class Client {public static void main(String[] args) {// 点一杯加牛奶和摩卡的咖啡Beverage beverage new Espresso();beverage new MilkDecorator(beverage);beverage new MochaDecorator(beverage);System.out.println(Cost: $ beverage.cost());System.out.println(Description: beverage.description());// 再加奶油beverage new WhipDecorator(beverage);System.out.println(\nAfter adding whip:);System.out.println(Cost: $ beverage.cost());System.out.println(Description: beverage.description());}
}输出结果
Cost: $3.2
Description: Espresso, Milk, MochaAfter adding whip:
Cost: $3.8
Description: Espresso, Milk, Mocha, Whip抽象构件类典型代码(c)
abstract class Component
{public abstract void Operation();
}具体构件类典型代码
class ConcreteComponent : Component
{public override void Operation(){//基本功能实现}
}抽象装饰类典型代码
class Decorator : Component
{
private Component component; //维持一个对抽象构件对象的引用//注入一个抽象构件类型的对象public Decorator(Component component){this.component component;}public override void Operation(){component.Operation(); //调用原有业务方法}
}具体装饰类典型代码
class ConcreteDecorator : Decorator
{public ConcreteDecorator(Component component) : base(component){}public override void Operation() {base.Operation(); //调用原有业务方法AddedBehavior(); //调用新增业务方法}
//新增业务方法
public void AddedBehavior() { //功能扩展}
}其他案例
某软件公司基于面向对象技术开发了一套图形界面构件库——VisualComponent该构件库提供了大量基本构件如窗体、文本框、列表框等由于在使用该构件库时用户经常要求定制一些特殊的显示效果如带滚动条的窗体、带黑色边框的文本框、既带滚动条又带黑色边框的列表框等等因此经常需要对该构件库进行扩展以增强其功能。
现使用装饰模式来设计该图形界面构件库。
变形金刚变形金刚在变形之前是一辆汽车它可以在陆地上移动。当它变成机器人之后除了能够在陆地上移动之外还可以说话如果需要它还可以变成飞机除了在陆地上移动还可以在天空中飞翔。
多重加密系统
某系统提供了一个数据加密功能可以对字符串进行加密。最简单的加密算法通过对字母进行移位来实现同时还提供了稍复杂的逆向输出加密还提供了更为高级的求模加密。用户先使用最简单的加密算法对字符串进行加密如果觉得还不够可以对加密之后的结果使用其他加密算法进行二次加密当然也可以进行第三次加密。现使用装饰模式设计该多重加密系统六、优缺点分析优点描述✅ 比继承更灵活可在运行时动态添加功能避免了类爆炸问题。可以通过一种动态的方式来扩展一个对象的功能通过配置文件可以在运行时选择不同的具体装饰类从而实现不同的行为✅ 遵循开闭原则扩展功能时不需要修改原有代码。具体构件类与具体装饰类可以独立变化用户可以根据需要增加新的具体构件类和具体装饰类且原有类库代码无须改变符合开闭原则✅ 职责分离清晰每个装饰器只负责一个功能便于维护和复用。可以对一个对象进行多次装饰
缺点描述❌ 增加系统复杂度多个装饰器嵌套后可能让代码难以理解和调试。使用装饰模式进行系统设计时将产生很多小对象大量小对象的产生势必会占用更多的系统资源在一定程度上影响程序的性能❌ 调试困难对象层层包装追踪执行路径较为麻烦。比继承更加易于出错排错也更困难对于多次装饰的对象调试时寻找错误可能需要逐级排查较为烦琐❌ 容易误用装饰顺序某些情况下装饰顺序会影响最终效果需特别注意。
七、与其他模式对比补充模式名称目标代理模式控制对对象的访问强调保护或增强但不改变接口。适配器模式解决接口不兼容问题强调转换。装饰模式动态增强对象功能强调组合和扩展。
八、最终小结
装饰模式是一种非常实用的设计模式尤其适合用于那些需要在不修改现有对象的前提下动态扩展其功能的场景。
它的核心思想是“组合优于继承”“透明地增强对象能力”。在 Java 中最经典的使用就是 IO 流体系例如 BufferedReader(new InputStreamReader(System.in))就是一个典型的装饰链。
作为一名 Java 开发工程师掌握装饰模式可以帮助你写出更优雅、更灵活、更容易扩展的代码特别是在开发插件化、模块化系统时尤为重要。
如果你正在设计一个需要支持“插件式”功能扩展的系统或者希望避免因继承带来的类爆炸问题那么装饰模式将是一个非常好的选择。一句话总结装饰模式就像“洋葱”一层层包裹原始对象在不破坏原有结构的前提下动态赋予新功能。九、扩展
透明装饰模式
透明(Transparent)装饰模式要求客户端完全针对抽象编程装饰模式的透明性要求客户端程序不应该将对象声明为具体构件类型或具体装饰类型而应该全部声明为抽象构件类型。
对于客户端而言具体构件对象和具体装饰对象没有任何区别。
可以让客户端透明地使用装饰之前的对象和装饰之后的对象无须关心它们的区别
可以对一个已装饰过的对象进行多次装饰得到更为复杂、功能更为强大的对象
无法在客户端单独调用新增方法AddedBehavior()
……
Component component_o,component_d1,component_d2; //全部使用抽象构件定义
component_o new ConcreteComponent();
component_d1 new ConcreteDecorator1(component_o);
component_d2 new ConcreteDecorator2(component_d1);
component_d2.Operation();
//无法单独调用component_d2的AddedBehavior()方法
……半透明装饰模式
半透明(Semi-transparent)装饰模式用具体装饰类型来定义装饰之后的对象而具体构件使用抽象构件类型来定义。
对于客户端而言具体构件类型无须关心是透明的但是具体装饰类型必须指定这是不透明的。
可以给系统带来更多的灵活性设计相对简单使用起来也非常方便
客户端使用具体装饰类型来定义装饰后的对象因此可以单独调用AddedBehavior()方法
最大的缺点在于不能实现对同一个对象的多次装饰而且客户端需要有区别地对待装饰之前的对象和装饰之后的对象
……
Component component_o; //使用抽象构件类型定义
component_o new ConcreteComponent();
component_o.Operation();
ConcreteDecorator component_d; //使用具体装饰类型定义
component_d new ConcreteDecorator(component_o);
component_d.Operation();
component_d.AddedBehavior(); //单独调用新增业务方法
……以上内容部分由AI大模型生成注意识别