摘要:抽象组件: 定义一个接口或抽象类, 是具体组件和装饰器的共同父类。定义了客户端可以调用的基本操作。具体组件: 实现抽象组件接口, 是原始的、未被装饰的对象。实现了抽象组件定义的基本操作。抽象装饰器: 实现抽象组件接口, 并持有一个抽象组件的引用。它是所有具体装
结构型设计模式, 旨在动态地给一个对象添加额外的职责。在不改变原有对象结构的基础上, 通过包装的方式, 为对象提供新的功能。
通过引入一个抽象的装饰器类和具体的装饰器实现, 将核心功能和附加功能解耦, 从而实现功能的灵活组合和扩展。
#技术分享装饰器模式的核心思想是 透明地动态扩展对象功能 , 它将核心功能和附加功能拆分为两个独立的层次结构: 组件和装饰器。
抽象组件 : 定义一个接口或抽象类, 是具体组件和装饰器的共同父类。定义了客户端可以调用的基本操作。具体组件 : 实现抽象组件接口, 是原始的、未被装饰的对象。实现了抽象组件定义的基本操作。抽象装饰器 : 实现抽象组件接口, 并持有一个抽象组件的引用。它是所有具体装饰器的抽象父类。具体装饰器 : 继承抽象装饰器, 并实现特定的装饰功能。每个具体装饰器都代表一个要添加的新职责。当需要动态地给一个对象添加功能, 且这些功能可以独立地被添加或移除时, 可以选择装饰器模式, 若功能是静态的, 或者只有少数几种组合, 那么 继承可以更简单。装饰器和被装饰器的对象都实现了相同的接口或继承相同的抽象类, 确保了客户端代码可以无差别的调用同一个接口。明确哪些是对象的基本、核心职责, 哪些是可以在运行时动态添加的附加职责。核心功能应由具体组件实现, 附加功能由装饰器实现。假设我们正在开发一个在线咖啡店的订单系统, 顾客可以点不同种类的咖啡, 并且可以添加各种配料, 如牛奶、糖、巧克力等。每种咖啡和配料都有基 础价格, 配料的价格会叠加到咖啡的总价上。包含以下几种咖啡: 浓缩咖啡(10元)、美式咖啡(12元) 可以添加配料如下: 牛奶(2元)、糖(1元)、巧克力(3元)
将咖啡和配料分别抽象为不同的类:
咖啡种类作为具体组件, 实现统一的咖啡接口配料作为装饰器, 继承自抽象装饰器类, 并通过组合方式包装咖啡对象。根据装饰器模式的角色进行代码划分 并对代码进行统一的解释,不需要在代码中增加注释,在每个小节后进行解释。
public interface Coffee {String getDescription;double getCost;}接口定义了咖啡的基本行为, 包含两个方法获取描述( getDescription )及价格( getCost ), 所有具体咖啡和装饰器都必须实现该接口。作为顶层接口, 保证装饰器和组件之间的兼容性。public class Americano implements Coffee {@Override public String getDescription { return "美式咖啡"; }@Override public double getCost { return 12.0; } } public class Espresso implements Coffee {@Override public String getDescription { return "浓缩咖啡"; }@Override public double getCost { return 10.0; } }Americano 和 Espresso 是具体组件类, 分别表示一种基础咖啡类型, 实现了 Coffee 接口中定义的方法, 提供咖啡的基础行为。作为被装饰的基础对象, 通过装饰器扩展功能。public abstract class CondimentDecorator implements Coffee {protected Coffee coffee;public CondimentDecorator(Coffee coffee) { this.coffee = coffee; }@Override public abstract String getDescription;@Override public abstract double getCost; }CondimentDecorator 是抽象装饰器类, 也实现了 Coffee 接口, 并持有一个 Coffee 类型的引用。子类通过该引用调用被装饰对象的方 法, 并在其基础上添加新的行为。通过构造函数注入被装饰对象, 实现装饰器链的嵌套。具体装饰器public class MilkDecorator extends CondimentDecorator {public MilkDecorator(Coffee coffee) { super(coffee); }@Override public String getDescription { return coffee.getDescription +}@Override public double getCost { return coffee.getCost +} }public class SugarDecorator extends CondimentDecorator {public SugarDecorator(Coffee coffee) { super(coffee); }@Override public String getDescription { return coffee.getDescription +}@Override public double getCost { return coffee.getCost +} }public class ChocolateDecorator extends CondimentDecorator {public ChocolateDecorator(Coffee coffee) { super(coffee); }@Override public String getDescription { return coffee.getDescription +}@Override public double getCost { return coffee.getCost +} }MilkDecorator 、 SugarDecorator 和 ChocolateDecorator 是具体装饰器类, 分别表示不同的配料。通过构造函数接收一个 Coffee 对象, 并在其基础上增加相应的描述和价格。public class DecoratorCoffeeTest {@Test public void test_coffee {Coffee coffee1 = new Espresso; System.out.println("订单1: " + coffee1.getDescription + ", 价格: " + coffee1.getCost + "元");Coffee coffee2 = new MilkDecorator(new Espresso); System.out.println("订单2: " + coffee2.getDescription + ", 价格: " + coffee2.getCost + "元");Coffee coffee3 = new SugarDecorator(new MilkDecorator(new Americano)); System.out.println("订单3: " + coffee3.getDescription + ", 价格: " + coffee3.getCost + "元");}}订单1: 浓缩咖啡, 价格: 10.0元订单2: 浓缩咖啡, 加牛奶, 价格: 12.0元订单3: 美式咖啡, 加牛奶, 加糖, 价格: 15.0元Process finished with exit code 0定义一个用于创建对象的接口, 但让子类决定实例化哪一个, 工厂方法让类的实例化延迟到子类。它的核心思想是将对象的创建与使用分离, 从而使得系统在增加新产品时, 无需修改客户端代码, 只需要增加新的具体产品类和对应的具体工厂类。
案例准备开发一个在线游戏角色系统, 玩家可以选择不同的基础角色(如战士、法师), 并且可以为这些角色穿戴各种装备(如盔甲、武器、魔法卷轴), 每种装备都能为角色提供额外的属性加成或特殊能力。随着游戏的发展, 会不断退出新的角色类型和新的装备。我们希望能够动态的创建角色, 并为它们动态穿戴装备, 同事避免在客户端代码中之间处理复杂的对象创建逻辑和装备组合逻辑。
模式职责装饰器模式: 负责动态地为游戏角色添加状态和属性加成, 从而避免修改基础角色类的代码。每件装备都可以抽象为一个装饰器。工厂方法模式: 负责创建不同类型的游戏角色对象。提供一个统一的接口来创建角色, 具体的角色创建逻辑由不同的具体工厂子类来实现。这样, 当有新的角色类型或新的装备组合方式时, 只需添加新的工厂子类, 而无需修改客户端代码。public interface GameCharacter {String getName;int getAttack;int getDefense;String getDescription;}定义游戏角色的基本行为, 包括获取名称( getName )、攻击力( getAttack )、防御力( getDefense )和描述( getDescription )。public class Warrior implements GameCharacter {@Override public String getName { return "战士"; }@Override public int getAttack { return 100; }@Override public int getDefense { return 80; }@Override public String getDescription { return "英勇的战士"; } } public class Mage implements GameCharacter {@Override public String getName { return "法师"; }@Override public int getAttack { return 120; }@Override public int getDefense { return 50; }@Override public String getDescription { return "神秘的法师"; } }public class EquipmentDecorator implements GameCharacter {protected GameCharacter character;public EquipmentDecorator(GameCharacter character) { this.character = character; }@Override public String getName { return character.getName; }@Override public int getAttack { return character.getAttack; }@Override public int getDefense { return character.getDefense; }@Override public String getDescription { return character.getDescription; } }实现了 GameCharacter 接口, 并持有一个 GameCharacter 类型的 character 成员变量构造函数接收一个 GameCharacter 对象, 代表要装饰的对象。默认转发所有 GameCharacter 接口的方法调用给其内部持有的 character 对象, 子类可以重写这些方法来添加新的行为或修改原有行为。具体装饰器public class ArmorDecorator extends EquipmentDecorator {public ArmorDecorator(GameCharacter character) { super(character); }@Override public int getDefense { return super.getDefense +}@Override public String getDescription { return super.getDescription +}} public class WeaponDecorator extends EquipmentDecorator {public WeaponDecorator(GameCharacter character) { super(character); }@Override public int getAttack { return super.getAttack +}@Override public String getDescription { return super.getDescription +} } public class ScrollDecorator extends EquipmentDecorator {public ScrollDecorator(GameCharacter character) { super(character); }@Override public int getAttack { return super.getAttack +}@Override public int getDefense { return super.getDefense +}@Override public String getDescription { return super.getDescription +} }继承 EquipmentDecorator , 它们分别代表了盔甲( ArmorDecorator )、武器( WeaponDecorator )和魔法卷轴( ScrollDecorator )三种装备。每个装饰器都重写各自所具有的行为, 在调用被装饰对象的相应方法的基础上, 添加自己的额外功能(如: 增加防御、增加攻击、修改描述)public interface CharacterFactory {GameCharacter createCharacter;}定义了一个工厂方法 createCharacter , 用于创建 GameCharacter 对象将对象的创建过程抽象化, 使得客户端无需关心具体创建哪个角色以及如何创建具体工厂public class WarriorFactory implements CharacterFactory { @Override public GameCharacter createCharacter {System.out.println("战士工厂: 正在创建基础战士..."); System.out.println("战士工厂: 为战士穿戴默认盔甲和武器..."); return new WeaponDecorator(new ArmorDecorator(new Warrior)); } } public class MageFactory implements CharacterFactory { @Override public GameCharacter createCharacter {System.out.println("法师工厂: 正在创建基础法师..."); System.out.println("法师工厂: 为法师学习魔法卷轴..."); return new ScrollDecorator(new Mage); } }实现了 CharacterFactory 接口, 分别负责创建战士和法师在 createCharacter 方法中, 不仅实例化了基础的 Warrior 或 Mage 对象, 还利用装饰器模式, 为基础角色默认添加了特定的装备, 封装了装饰器模式。测试类public class GameCharacterTest {@Test public void test_warrior {System.out.println("\n---CharacterFactory warriorFactory = new WarriorFactory; GameCharacter warrior = warriorFactory.createCharacter; System.out.println("创建完成的角色: " +++++++);}@Test public void test_mage {System.out.println("\n---CharacterFactory mageFactory = new MageFactory; GameCharacter mage = mageFactory.createCharacter; System.out.println("创建完成的角色: " +++++++);}}运行结果---法师工厂: 正在创建基础法师... 法师工厂: 为法师学习魔法卷轴... 创建完成的角色: 法师, 描述: 神秘的法师, 学习魔法卷轴, 攻击力: 130, 防御力: 60---战士工厂: 正在创建基础战士... 战士工厂: 为战士穿戴默认盔甲和武器... 创建完成的角色: 战士, 描述: 英勇的战士, 穿戴盔甲, 装备武器, 攻击力: 130, 防御力: 130Process finished with exit code 0组合优势工厂方法模式将创建复杂对象的逻辑封装, 客户端无需了解角色如何被装饰创建, 只需要通过工厂方法获取所需角色, 降低客户端的耦合度。新增角色类型或新的默认装备组合时, 只需要增加新的具体工厂类和相应的装饰器类, 无需修改现有代码。定义了一系列算法, 将每个算法封装起来, 并使它们可以互相替换。 策略模式让算法独立于使用它的客户端而变化,核心思想是将算法的实现与使用算法的客户端分离, 使得客户端可以在运行时选择不同的算法, 而无需修改客户端代码, 使得算法可以独立地演化和扩展。
案例假设需要实现一个在线支付系统, 用户可以选择不同的支付方式(如: 信用卡支付、借记卡支付、第三方支付), 每种支付方式都有其独特的处理逻辑,此外, 支付过程可能还需要额外的安全措施, 例如支付钱进行风险评估、支付后进行积分计算等。用户希望能够灵活地选择支付方式, 并能动态地为支付过程添加或移除这些安全或增值服务, 而无需修改核心支付逻辑。
模式职责装饰器模式: 负责动态地位支付策略添加额外的处理逻辑, 如风险评估、日志记录、积分计算等策略模式: 负责封装不同的支付算法, 它定义了一个统一的支付接口, 并提供多种具体的支付实现, 使得客户端可以在运行时选择并切换不同的支付方式。public interface PaymentStrategy {void pay(double amount);String getDescription;}定义了具体支付策略必须实现的接口pay(double amount) 定义支付接口, 传入 amount 支付金额。getDescription 定义获取当前支付方式的描述。public class CreditCardPayment implements PaymentStrategy {private String cardNumber;public CreditCardPayment(String cardNumber) { this.cardNumber = cardNumber; }@Override public void pay(double amount) { System.out.println("使用信用卡 " +}@Override public String getDescription { return "信用卡支付"; } } public class DebitCardPayment implements PaymentStrategy {private String accountNumber;public DebitCardPayment(String accountNumber) { this.accountNumber = accountNumber; }@Override public void pay(double amount) { System.out.println("使用借记卡 " +}@Override public String getDescription { return "借记卡支付"; } } public class ThirdPartyPayment implements PaymentStrategy {private String platformName;public ThirdPartyPayment(String platformName) { this.platformName = platformName; }@Override public void pay(double amount) { System.out.println("使用第三方支付平台 " +}@Override public String getDescription { return "第三方支付(" +} }实现了 PaymentStrategy 接口, 提供了信用卡( CreditCardPayment )、借记卡( DebitCardPayment )和第三方支付( ThirdPartyPayment )的具体支付逻辑, 且代表了原始的支付方式。pay 方法执行各自的支付操作, getDescription 方法返回其基本描述。public class PaymentDecorator implements PaymentStrategy {protected PaymentStrategy decoratedPayment;public PaymentDecorator(PaymentStrategy decoratedPayment) { this.decoratedPayment = decoratedPayment; }@Override public void pay(double amount) { decoratedPayment.pay(amount); }@Override public String getDescription { return decoratedPayment.getDescription; } }实现了 PaymentStrategy 接口, 并持有一个 PaymentStrategy 类型的 decoratedPayment 成员变量构造函数接收一个 PaymentStrategy 对象, 表示它将要装饰的支付策略默认转发 pay 和 getDescription 方法调用给其内部持有的 decoratedPayment 对象public class RiskAssessmentDecorator extends PaymentDecorator {public RiskAssessmentDecorator(PaymentStrategy decoratedPayment) { super(decoratedPayment); }@Override public void pay(double amount) { System.out.println("执行风险评估...");if (amount > 1000) { System.out.println("金额较大, 建议进行二次验证。"); } super.pay(amount);System.out.println("风险评估完成。"); }@Override public String getDescription { return super.getDescription +} } public class LoyaltyPointDecorator extends PaymentDecorator {public LoyaltyPointDecorator(PaymentStrategy decoratedPayment) { super(decoratedPayment); }@Override public void pay(double amount) { super.pay(amount); int points = (int) (amount *System.out.println("计算积分: 获得 " +}@Override public String getDescription { return super.getDescription +} } public class LoggingDecorator extends PaymentDecorator {public LoggingDecorator(PaymentStrategy decoratedPayment) { super(decoratedPayment); }@Override public void pay(double amount) { System.out.println("记录支付日志: 支付金额 " +super.pay(amount); System.out.println("支付日志记录完成。"); }@Override public String getDescription { return super.getDescription +} }继承了 PaymentDecorator , 分别代表了风险评估( RiskAssessmentDecorator )、积分计算( LoyaltyPointDecorator )和日志记录( LoggingDecorator )三种附加功能。重写 pay 方法, 在调用 super.pay(amount) 方法之前或折后添加自己的特定逻辑。重写 getDescription 方法, 在原有基础上添加自己的功能描述。策略模式部分上下文public class PaymentProcessor {private PaymentStrategy paymentStrategy;public void setPaymentStrategy(PaymentStrategy paymentStrategy) { this.paymentStrategy = paymentStrategy; }public void processPayment(double amount) { if (paymentStrategy == null) { System.out.println("未设置支付策略"); return; }System.out.println("\n---paymentStrategy.pay(amount); System.out.println("---} }持有一个 PaymentStrategy 类型引用, 并提供 setPaymentStrategy 方法来设置具体的支付策略, 以及 processPayment 方法来执行支付操作。PaymentProcessor 不关心具体的支付方式或附加功能, 只通过 PaymentStrategy 接口与它们交互, 从而实现了客户端与具体策略的解耦。测试类public class PayTest {@Test public void test_payment {PaymentProcessor processor = new PaymentProcessor;System.out.println("\n 场景1: 简单的信用卡支付"); processor.setPaymentStrategy(new CreditCardPayment("1234-5678-9012-3456")); processor.processPayment(150.0);System.out.println("\n 场景2: 借记卡支付, 并进行风险评估和积分计算"); processor.setPaymentStrategy(new RiskAssessmentDecorator(new LoyaltyPointDecorator(new DebitCardPayment("987654321")))); processor.processPayment(1200.0);System.out.println("\n 场景3: 第三方支付, 并记录日志"); processor.setPaymentStrategy(new LoggingDecorator(new ThirdPartyPayment("支付宝"))); processor.processPayment(500.0);}}运行结果场景1: 简单的信用卡支付使用信用卡 1234-5678-9012-3456 支付 150.0 元。场景2: 借记卡支付, 并进行风险评估和积分计算执行风险评估... 金额较大, 建议进行二次验证。使用借记卡 987654321 支付 1200.0 元。计算积分: 获得 120 积分 风险评估完成。场景3: 第三方支付, 并记录日志记录支付日志: 支付金额 500.0, 支付方式: 第三方支付(支付宝)。使用第三方支付平台 支付宝 支付 500.0 元。支付日志记录完成。Process finished with exit code 0组合优势装饰器模式专注于 如何增强, 策略模式专注于 做什么, 每个模式都解决了其特定的问题, 使得系统结构清晰, 易于理解和维护。策略模式使得核心算法可以独立于客户端进行切换, 而装饰器模式则允许在不修改核心算法代码的情况下, 动态地添加各种横切关注点。将一个复杂对象的构建和它的表示分离, 使得同样的构建过程可以创建不同的表示。核心思想是一步步地构建一个复杂对象, 通过一个建造者对象来封装构建过程, 从而使得客户端无需关心对象的内部构建细节, 只需调用建造者提供的方法即可。
案例制作一个在线简历生成器, 用户可以根据自己的需求, 定制不同类型的简历, 例如:
标准简历: 包含基本信息、教育背景、工作经验。技术简历: 在标准简历基础上, 额外包含项目经验、技能列表。高级简历: 在技术简历的基础上, 额外包含荣誉奖项、发表论文。 此外, 用户还可以选择为简历的某些部分添加额外的修饰或增强, 例如:突出显示: 将某些关键信息加粗或高亮。格式化: 为教育背景或工作经验添加特定的排版样式。图片嵌入: 在简历中嵌入个人照片或作品集图片。模式职责public interface ResumeElement {String render;}定义了简历元素的基本行为 render , 用于渲染元素内容。public class TextElement implements ResumeElement {private String content;public TextElement(String content) { this.content = content; }@Override public String render { return content; } } public class ImageElement implements ResumeElement {private String imageUrl;public ImageElement(String imageUrl) { this.imageUrl = imageUrl; }@Override public String render { return "[图片: " +} }实现了 ResumeElement 接口, 分别代表简历中的基本文本块( TextElement )和图片元素( ImageElement )。public abstract class ElementDecorator implements ResumeElement {protected ResumeElement decoratedElement;public ElementDecorator(ResumeElement decoratedElement) { this.decoratedElement = decoratedElement; }@Override public String render { return decoratedElement.render; } }实现了 ResumeElement 接口, 并持有一个 ResumeElement 类型的 decoratedElement 成员变量, 是所有简历元素修饰器的抽象父类。构造函数接收一个 ResumeElement 对象, 表示将要装饰的元素。render 方法中, 默认调用持有的 decoratedElement 对象的 render 方法。public class HighlightDecorator extends ElementDecorator {public HighlightDecorator(ResumeElement decoratedElement) { super(decoratedElement); }@Override public String render { return "" +} } public class FormatterDecorator extends ElementDecorator {private String prefix;private String suffix;public FormatterDecorator(ResumeElement decoratedElement, String prefix, String suffix) { super(decoratedElement); this.prefix = prefix; this.suffix = suffix; }@Override public String render { return prefix +} } public class BorderDecorator extends ElementDecorator {public BorderDecorator(ResumeElement decoratedElement) { super(decoratedElement); }@Override public String render { return "[边框]" +} }继承 ElementDecorator , 分别代表了高亮( HighlightDecorator )、格式化( FormatterDecorator )和边框( BorderDecorator )这三种修饰功能。每个装饰器都重写了 render 方法, 在调用 super.render 的基础上, 添加各自特定的修饰逻辑(如: 添加HTML标签、前缀后缀等)。public class Resume {private String basicInfo;private List education;private List workExperience;private List projects;private List skills;private List awards;private List publications;public Resume { this.education = new ArrayList; this.workExperience = new ArrayList; this.projects = new ArrayList; this.skills = new ArrayList; this.awards = new ArrayList; this.publications = new ArrayList; }public void setBasicInfo(String basicInfo) { this.basicInfo = basicInfo; }public void addEducation(String edu) { this.education.add(edu); }public void addWorkExperience(String workExp) { this.workExperience.add(workExp); }public void addProject(String project) { this.projects.add(project); }public void addSkill(String skill) { this.skills.add(skill); }public void addAward(String award) { this.awards.add(award); }public void addPublication(String publication) { this.publications.add(publication); }public void display { System.out.println("\n---if (basicInfo != null) { System.out.println("基本信息: " +}if (!education.isEmpty) { System.out.println("教育背景: "); education.forEach(e -> System.out.println(" -}if (!workExperience.isEmpty) { System.out.println("工作经验: "); workExperience.forEach(w -> System.out.println(" -}if (!projects.isEmpty) { System.out.println("项目经验: "); projects.forEach(p -> System.out.println(" -}if (!skills.isEmpty) { System.out.println("技能列表: "); skills.forEach(s -> System.out.println(" -}if (!awards.isEmpty) { System.out.println("荣誉奖项: "); awards.forEach(a -> System.out.println(" -}if (!publications.isEmpty) { System.out.println("发表论文: "); publications.forEach(pub -> System.out.println(" -}System.out.println(""); }}代表最终构建的复杂简历对象, 包含了简历的各个部分, 提供了 set 和 add 方法来设置和添加简历的各个组成部分, 以及 display 方法打印简历的内容。public interface ResumeBuilder {void buildBasicInfo(String info);void buildEducation(String edu);void buildWorkExperience(String workExp);void buildProjects(String project);void buildSkills(String skill);void buildAwards(String award);void buildPublications(String publication);Resume build;}定义了构建简历各个部分的抽象方法(如: buildBasicInfo 、 buildEducation 等 ), 以及获取最终简历对象的方法 build 。public class StandardResumeBuilder implements ResumeBuilder {private Resume resume;public StandardResumeBuilder { this.resume = new Resume; }@Override public void buildBasicInfo(String info) { resume.setBasicInfo(info); }@Override public void buildEducation(String edu) { resume.addEducation(new TextElement(edu).render); }@Override public void buildWorkExperience(String workExp) { resume.addWorkExperience(new TextElement(workExp).render); }@Override public void buildProjects(String project) { }@Override public void buildSkills(String skill) { }@Override public void buildAwards(String award) { }@Override public void buildPublications(String publication) { }@Override public Resume build { return this.resume; } }public class TechnicalResumeBuilder implements ResumeBuilder {private Resume resume;public TechnicalResumeBuilder { this.resume = new Resume; }@Override public void buildBasicInfo(String info) { resume.setBasicInfo(info); }@Override public void buildEducation(String edu) { ResumeElement eduElement = new FormatterDecorator(new TextElement(edu), "[教育]", ""); resume.addEducation(eduElement.render); }@Override public void buildWorkExperience(String workExp) { ResumeElement workExpElement = new HighlightDecorator(new TextElement(workExp)); resume.addWorkExperience(workExpElement.render); }@Override public void buildProjects(String project) { ResumeElement projectElement = new HighlightDecorator(new TextElement(project)); resume.addProject(projectElement.render); }@Override public void buildSkills(String skill) { ResumeElement skillElement = new FormatterDecorator(new TextElement(skill), "", ""); resume.addSkill(skillElement.render); }@Override public void buildAwards(String award) { }@Override public void buildPublications(String publication) { }@Override public Resume build { return this.resume; } }public class AdvancedResumeBuilder implements ResumeBuilder {private Resume resume;public AdvancedResumeBuilder { this.resume = new Resume; }@Override public void buildBasicInfo(String info) { resume.setBasicInfo(info); } @Override public void buildEducation(String edu) { ResumeElement eduElement = new FormatterDecorator(new TextElement(edu), "[教育]", ""); resume.addEducation(eduElement.render); } @Override public void buildWorkExperience(String workExp) { ResumeElement workExpElement = new HighlightDecorator(new TextElement(workExp)); resume.addWorkExperience(workExpElement.render); } @Override public void buildProjects(String project) { ResumeElement projectElement = new HighlightDecorator(new TextElement(project)); resume.addProject(projectElement.render); } @Override public void buildSkills(String skill) { ResumeElement skillElement = new FormatterDecorator(new TextElement(skill), "", ""); resume.addSkill(skillElement.render); }@Override public void buildAwards(String award) { ResumeElement awardElement = new HighlightDecorator(new TextElement(award)); resume.addAward(awardElement.render); }@Override public void buildPublications(String publication) { ResumeElement pubElement = new FormatterDecorator(new TextElement(publication), "《", "》"); resume.addPublication(pubElement.render); } @Override public Resume build { return this.resume; } }实现了 ResumeBuilder 接口, 负责构建特定类型的简历。在构建方法中, 可以根据简历类型的不同, 选择是否使用装饰器来修饰特定部分。也可以在参数中将渲染元素类传入, 动态控制渲染的装饰器。指挥者public class ResumeDirector {public Resume constructStandardResume(ResumeBuilder builder) { builder.buildBasicInfo("姓名: 张三, 电话: 13898473281"); builder.buildEducation("2018-2022 A 大学 计算机科学与技术 本科"); builder.buildWorkExperience("2022-至今 B 科技公司 软件工程师");return builder.build; }public Resume constructTechnicalResume(ResumeBuilder builder) { builder.buildBasicInfo("姓名: 张三, 电话: 13898473281"); builder.buildEducation("2018-2022 A 大学 计算机科学与技术 本科"); builder.buildWorkExperience("2022-至今 B 科技公司 软件工程师"); builder.buildProjects("在线商城系统开发"); builder.buildSkills("Java, Spring Boot, MySQL, Vue");return builder.build; }public Resume constructAdvancedResume(ResumeBuilder builder) { builder.buildBasicInfo("姓名: 张三, 电话: 13898473281"); builder.buildEducation("2018-2022 A 大学 计算机科学与技术 本科"); builder.buildWorkExperience("2022-至今 B 科技公司 软件工程师"); builder.buildProjects("在线商城系统开发"); builder.buildSkills("Java, Spring Boot, MySQL, Vue");ResumeElement awardImage = new BorderDecorator(new ImageElement("award_certificate.png")); builder.buildAwards(awardImage.render + " 优秀员工奖");ResumeElement publicationText = new HighlightDecorator(new TextElement("深度学习在自然语言处理中的应用")); builder.buildPublications(publicationText.render + " (SCI 收录)");return builder.build; }}负责使用 ResumeBuilder 来构建特定类型的简历, 封装了构建过程的算法。constructResume 、 constructTechnicalResume 、 constructAdvancedResume 演示了简单、技术、高级简历的构建。public class ResumeTest {@Test public void test_resume {ResumeDirector director = new ResumeDirector System.out.println("\n 场景1: 构建标准简历") ResumeBuilder standardBuilder = new StandardResumeBuilder Resume standardResume = director.constructStandardResume(standardBuilder) standardResume.displaySystem.out.println("\n 场景2: 构建技术简历") ResumeBuilder technicalBuilder = new TechnicalResumeBuilder Resume technicalResume = director.constructTechnicalResume(technicalBuilder) technicalResume.displaySystem.out.println("\n 场景3: 构建高级简历") ResumeBuilder advancedBuilder = new AdvancedResumeBuilder Resume advancedResume = director.constructAdvancedResume(advancedBuilder) advancedResume.display} }运行结果场景1: 构建标准简历---基本信息: 姓名: 张三, 电话: 13898473281 教育背景: -工作经验: 场景2: 构建技术简历---基本信息: 姓名: 张三, 电话: 13898473281 教育背景: -工作经验: - 2022-至今 B 科技公司 软件工程师项目经验: - 在线商城系统开发技能列表: - Java, Spring Boot, MySQL, Vue场景3: 构建高级简历---基本信息: 姓名: 张三, 电话: 13898473281 教育背景: -工作经验: - 2022-至今 B 科技公司 软件工程师项目经验: - 在线商城系统开发技能列表: - Java, Spring Boot, MySQL, Vue荣誉奖项: - [边框][图片: award_certificate.png][边框] 优秀员工奖发表论文: Process finished with exit code 0建造者模式允许客户端通过不同的建造者或指挥者来创建不同配置的简历, 装饰器模式则提供了在构建过程中对简历的局部进行精细化修饰的能力, 实现了高度的定制化。客户端无需关系简历的复杂构建细节和内部元素的修饰逻辑, 只需通过建造者和指挥者提供的接口, 即可一步步构建所需简历。不积跬步,无以至千里;不积小流,无以成江海。
来源:墨码行者