通过装饰器模式,可以灵活地为发票添加各种额外信息,而无需修改原有的发票类,使得代码更加模块化、易于维护和扩展

假设发票有基本的内容(如发票号、日期、金额等),并且我们希望在不改变原有发票类的情况下,动态地为发票添加额外的信息,如折扣、税、备注等。装饰器模式非常适合这种场景。

1. 定义组件接口(发票)

public interface Invoice {
    String print();
}

2. 实现具体组件(基本发票)

public class BasicInvoice implements Invoice {
    private String invoiceNumber;
    private String date;
    private double amount;

    public BasicInvoice(String invoiceNumber, String date, double amount) {
        this.invoiceNumber = invoiceNumber;
        this.date = date;
        this.amount = amount;
    }

    @Override
    public String print() {
        return "发票号: " + invoiceNumber + "\n日期: " + date + "\n金额: " + amount;
    }
}

3. 定义装饰器类(发票装饰器)

public abstract class InvoiceDecorator implements Invoice {
    protected Invoice decoratedInvoice;

    public InvoiceDecorator(Invoice decoratedInvoice) {
        this.decoratedInvoice = decoratedInvoice;
    }

    @Override
    public String print() {
        return decoratedInvoice.print();
    }
}

4. 实现具体装饰器(添加折扣、税、备注)

public class DiscountDecorator extends InvoiceDecorator {
    private double discount;

    public DiscountDecorator(Invoice decoratedInvoice, double discount) {
        super(decoratedInvoice);
        this.discount = discount;
    }

    @Override
    public String print() {
        return super.print() + "\n折扣: " + discount;
    }
}

public class TaxDecorator extends InvoiceDecorator {
    private double tax;

    public TaxDecorator(Invoice decoratedInvoice, double tax) {
        super(decoratedInvoice);
        this.tax = tax;
    }

    @Override
    public String print() {
        return super.print() + "\n税: " + tax;
    }
}

public class NoteDecorator extends InvoiceDecorator {
    private String note;

    public NoteDecorator(Invoice decoratedInvoice, String note) {
        super(decoratedInvoice);
        this.note = note;
    }

    @Override
    public String print() {
        return super.print() + "\n备注: " + note;
    }
}

5. 客户端代码

public class Main {
    public static void main(String[] args) {
        // 创建基本发票
        Invoice invoice = new BasicInvoice("INV12345", "2024-05-10", 100.00);
        System.out.println(invoice.print());

        // 添加折扣
        invoice = new DiscountDecorator(invoice, 10.00);
        System.out.println(invoice.print());

        // 添加税
        invoice = new TaxDecorator(invoice, 8.00);
        System.out.println(invoice.print());

        // 添加备注
        invoice = new NoteDecorator(invoice, "感谢您的惠顾!");
        System.out.println(invoice.print());
    }
}

6. 输出结果

运行客户端代码,输出结果如下:

发票号: INV12345
日期: 2024-05-10
金额: 100.0
发票号: INV12345
日期: 2024-05-10
金额: 100.0
折扣: 10.0
发票号: INV12345
日期: 2024-05-10
金额: 100.0
折扣: 10.0
税: 8.0
发票号: INV12345
日期: 2024-05-10
金额: 100.0
折扣: 10.0
税: 8.0
备注: 感谢您的惠顾!

7. 装饰器模式的优点

  • 扩展性好:可以在不修改原有类的情况下,动态地添加新的功能。
  • 灵活性高:可以根据需要组合多个装饰器,实现多种功能。
  • 符合开闭原则:对扩展开放,对修改封闭,无需修改原有代码即可添加新功能。

8. 适用场景

装饰器模式适用于以下场景:

  • 当需要为一个类动态地添加额外的功能时。
  • 当需要组合多个功能时。
  • 当不想使用继承来扩展功能,因为继承会增加子类的数量,导致系统复杂度增加。

通过装饰器模式,可以灵活地为发票添加各种额外信息,而无需修改原有的发票类,使得代码更加模块化、易于维护和扩展。
下面是一个使用装饰器模式实现的打印发票系统 Python 程序。装饰器模式非常适合这种需要动态添加功能或修改行为的场景,特别是当需要为发票添加多个可选特性时。

from abc import ABC, abstractmethod

# 组件接口:发票
class Invoice(ABC):
    @abstractmethod
    def print_invoice(self):
        pass


# 具体组件:基础发票
class BasicInvoice(Invoice):
    def __init__(self, order_number, customer_name, items, total):
        self.order_number = order_number
        self.customer_name = customer_name
        self.items = items  # 商品列表
        self.total = total  # 总计金额
    
    def print_invoice(self):
        invoice = f"订单号: {self.order_number}\n"
        invoice += f"客户: {self.customer_name}\n"
        invoice += "商品列表:\n"
        for item in self.items:
            invoice += f"- {item['name']}: ¥{item['price']}\n"
        invoice += f"总计: ¥{self.total}\n"
        return invoice


# 装饰器基类:发票装饰器
class InvoiceDecorator(Invoice):
    def __init__(self, invoice):
        self.invoice = invoice
    
    def print_invoice(self):
        return self.invoice.print_invoice()


# 具体装饰器:添加折扣信息
class DiscountDecorator(InvoiceDecorator):
    def __init__(self, invoice, discount_rate, discount_amount):
        super().__init__(invoice)
        self.discount_rate = discount_rate
        self.discount_amount = discount_amount
    
    def print_invoice(self):
        original_invoice = self.invoice.print_invoice()
        discount_info = f"折扣率: {self.discount_rate}%\n"
        discount_info += f"折扣金额: ¥{self.discount_amount}\n"
        new_total = self.invoice.total - self.discount_amount
        discount_info += f"折后总计: ¥{new_total}\n"
        return original_invoice + discount_info


# 具体装饰器:添加增值税信息
class VATDecorator(InvoiceDecorator):
    def __init__(self, invoice, vat_rate):
        super().__init__(invoice)
        self.vat_rate = vat_rate
        self.vat_amount = invoice.total * (vat_rate / 100)
    
    def print_invoice(self):
        original_invoice = self.invoice.print_invoice()
        vat_info = f"增值税率: {self.vat_rate}%\n"
        vat_info += f"增值税金额: ¥{self.vat_amount:.2f}\n"
        total_with_vat = self.invoice.total + self.vat_amount
        vat_info += f"含税总计: ¥{total_with_vat:.2f}\n"
        return original_invoice + vat_info


# 具体装饰器:添加优惠券信息
class CouponDecorator(InvoiceDecorator):
    def __init__(self, invoice, coupon_code, coupon_amount):
        super().__init__(invoice)
        self.coupon_code = coupon_code
        self.coupon_amount = coupon_amount
    
    def print_invoice(self):
        original_invoice = self.invoice.print_invoice()
        coupon_info = f"优惠券代码: {self.coupon_code}\n"
        coupon_info += f"优惠券金额: ¥{self.coupon_amount}\n"
        new_total = self.invoice.total - self.coupon_amount
        coupon_info += f"使用优惠券后总计: ¥{new_total}\n"
        return original_invoice + coupon_info


# 具体装饰器:添加公司信息
class CompanyInfoDecorator(InvoiceDecorator):
    def __init__(self, invoice, company_name, address, contact):
        super().__init__(invoice)
        self.company_name = company_name
        self.address = address
        self.contact = contact
    
    def print_invoice(self):
        company_info = f"公司名称: {self.company_name}\n"
        company_info += f"地址: {self.address}\n"
        company_info += f"联系方式: {self.contact}\n"
        company_info += "=" * 30 + "\n"
        return company_info + self.invoice.print_invoice()


# 客户端代码
if __name__ == "__main__":
    # 创建基础发票
    items = [
        {"name": "商品A", "price": 100},
        {"name": "商品B", "price": 200},
        {"name": "商品C", "price": 150}
    ]
    basic_invoice = BasicInvoice("ORD-2023001", "张三", items, 450)
    
    # 打印基础发票
    print("=== 基础发票 ===")
    print(basic_invoice.print_invoice())
    
    # 添加公司信息
    company_invoice = CompanyInfoDecorator(
        basic_invoice,
        "ABC科技有限公司",
        "北京市朝阳区科技园A座1001室",
        "电话: 010-12345678"
    )
    print("=== 添加公司信息的发票 ===")
    print(company_invoice.print_invoice())
    
    # 添加折扣和增值税
    discounted_invoice = DiscountDecorator(company_invoice, 10, 45)
    invoice_with_tax = VATDecorator(discounted_invoice, 13)
    print("=== 添加折扣和增值税的发票 ===")
    print(invoice_with_tax.print_invoice())
    
    # 添加优惠券
    final_invoice = CouponDecorator(invoice_with_tax, "SAVE50", 50)
    print("=== 添加优惠券的最终发票 ===")
    print(final_invoice.print_invoice())
    
    # 动态修改发票(扩展场景)
    print("\n=== 动态修改发票 ===")
    # 创建新的基础发票
    new_items = [
        {"name": "笔记本电脑", "price": 5000},
        {"name": "鼠标", "price": 100}
    ]
    new_basic_invoice = BasicInvoice("ORD-2023002", "李四", new_items, 5100)
    
    # 直接添加增值税和优惠券
    invoice_with_vat = VATDecorator(new_basic_invoice, 13)
    final_invoice = CouponDecorator(invoice_with_vat, "NEWCUST", 200)
    print(final_invoice.print_invoice())

这个实现中,我们定义了:

  1. 组件接口(Invoice):定义了发票的基本操作,即打印发票。
  2. 具体组件(BasicInvoice):实现了基础发票的打印功能,包含订单号、客户信息、商品列表和总计金额。
  3. 装饰器基类(InvoiceDecorator):继承自 Invoice,维护一个指向被装饰对象的引用。
  4. 具体装饰器(DiscountDecorator、VATDecorator、CouponDecorator、CompanyInfoDecorator):扩展了装饰器基类,为发票添加额外的信息和功能。

通过这种设计,我们可以轻松地添加新的发票特性或修改现有特性,而不需要修改现有的代码结构。客户端可以动态地组合不同的装饰器,实现了系统的可扩展性和灵活性。

装饰器模式的核心优势在于可以在运行时动态地为对象添加功能,而不需要通过继承来扩展类。在这个打印发票系统中,基础发票和各种附加信息是两个独立的变化维度,通过装饰器模式,我们可以灵活地组合不同的附加信息,实现了系统的动态扩展能力。
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Bol5261

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值