用实际的软件编程示例解释C#中的装饰器模式

目录

背景

使用代码

兴趣点


背景

GoF定义:动态将附加职责附加到对象。装饰器为子类提供了灵活的替代方案,以扩展功能。

此模式支持SOLID -原理,这意味着您可以将新功能添加到现有类中,而无需对其进行修改。您可以使用继承组合向现有类添加新功能。

让我们考虑一个实际的软件编程示例。

我的应用程序中有一个发票模块,可打印简单的客户发票。该发票包含文本数据,例如客户名称、地址、订单号、订单金额和订单日期。数年来,我的几个客户一直使用此功能。

现在,我的一位客户(客户A)希望使用Colors打印发票。第二个客户端(客户端B)要打印发票Headers。第三个客户(客户C)希望使用Footers打印发票。那么,您认为我如何满足这一要求?继承?让我们尝试一下。

通过继承,我将以上述类结束。我将为每个新功能创建一个子类。到目前为止似乎还不错。但是,但是,当一个新客户端(客户端D)想要同时打印页眉和页脚时,上述场景会产生复杂性。如果我们想满足客户D的要求,我们的结构可能如下所示:

哦,等等,这是多重继承。我在C#中无法做到这一点。我不能从以上两个类实现。因此,现在我们将不得不创建一个新的子类,该子类将打印带有页眉和页脚的发票,并满足客户D的要求。

上述子分类方法存在两个问题:

  1. 您最终会遇到许多子类。确切地说,每种组合(如页眉+页脚)的一个子类就是一种组合。另一个组合可以是颜色+标题...”等等。在大型系统中,很难维护和调试许多子类。
  2. 如果您遵循SOLID单一职责原则,则说明类应该处理功能的单个部分。因此,我们的子类不应处理任务的组合。这意味着一类应该添加颜色,而另一类应该添加页眉信息。

为了克服上述问题,使用了装饰器模式。

使用Decorator模式,可以在不影响现有类的情况下附加新功能。它为扩展现有类提供了子类替代方法

在上面的示例中,InvoiceBaseInvoice类是现有的类。我需要添加的任何新功能都将是Decorator。我可以将多个装饰器附加到我们现有的类中,而无需为每个组合创建单独的子类。我创建了一个abstractInvoiceDecorator和另外三个类ColorDecoratorHeaderDecoratorFooterDecoratorInvoiceDecorator具有InvoiceBase对象的组成。当我们想向现有功能添加新功能时,我们使用AttachTo 方法。其背后的想法是将来在不影响我现有Invoice类的情况下添加新的装饰器。

我创建了一个示例应用程序,可以模拟发票打印操作。

使用代码

以下是我现有的类,在添加新功能时将不会对其进行修改。

 

// This is the base abstract class which is inherited 
    // by all concrete and decorator classes
    abstract class InvoiceBase
    {
        // string data stores the content which it to be printed in the invoice.
        // This variable will be altered by the subclasses. Thus, it is marked protected.
        protected static string data;
        
        // This function will be implemented in all the concrete classes as well as decorators
        public abstract void CreateInvoice();

        public void PrintInvoice()
        {
            Console.WriteLine(data);
        }

        //This function clear the variable value after invoice is printed.
        public void Reset()
        {
            data = string.Empty;
        }
    }

    public class Invoice : InvoiceBase
    {
        public override void CreateInvoice()
        {
            data += "\n";
            data += "\tCustomer Name : Chris\n";
            data += "\tCustomer Address : Edmond Road, NJ\n";
            data += "\tOrder No : 1254158\n";
            data += "\tOrder Amount : Rs. 2540/- \n";
            data += "\tOrder Date : 09-Apr-2020 \n";
            data += "\n";
        }
    }

以下是Decorator与分离的具体实现类。我们可以添加任意数量的Decorator来扩展功能。另外,请注意,我已经按照SOLID原则为一个职责创建了一个类,即颜色处理由ColorDecorater类负责,页眉信息处理由HeaderDecorator类负责。

// This is the base Decorator class which has the composition i.e. InvoiceBase object
// AttachTo method is used to attach responsibility dynamically through client code.
abstract class InvoiceDecorator : InvoiceBase
{
    InvoiceBase invoiceBase;
    public void AttachTo(InvoiceBase invoice)
    {
        this.invoiceBase = invoice;
    }
    public override void CreateInvoice()
    {
        invoiceBase.CreateInvoice();
    }
}

//These are individual decorator classes.
class ColorDecorator : InvoiceDecorator
{
    public override void CreateInvoice()
    {
        AddColor();
        base.CreateInvoice();
    }
    private void AddColor()
    {
        Console.ForegroundColor = ConsoleColor.Green;
    }
}

class HeaderDecorator : InvoiceDecorator
{
    public override void CreateInvoice()
    {
        AddHeader();
        base.CreateInvoice();
    }
    private void AddHeader()
    {
        string header = "\n\tBlue Heaven Inc.\n"
                        + "\tBay Area, NC\n"
                        + "\t+1 784251485\n\n";
        data = header + data;
    }
}

class FooterDecorator : InvoiceDecorator
{
    public override void CreateInvoice()
    {
        base.CreateInvoice();
        AddFooter();
    }
    void AddFooter()
    {
        string footer = "\n\tCopyright @ 2020.All rights reserved\n";
        data += footer;
    }
}

客户端代码如下所示:

// CASE 1: This is the existing implementation to print a simple invoice.
InvoiceBase invoice = new Invoice();
invoice.CreateInvoice();
invoice.PrintInvoice();

// CASE 2: Add color to the invoice
InvoiceBase invoice = new Invoice();
InvoiceDecorator colorDecorator = new ColorDecorator();

colorDecorator.AttachTo(invoice);
colorDecorator.CreateInvoice();

invoice.PrintInvoice();

// CASE 3: Add Color, Header and Footer to the invoice
InvoiceBase invoice = new Invoice();
InvoiceDecorator colorDecorator = new ColorDecorator();
InvoiceDecorator headerDecorator = new HeaderDecorator();
InvoiceDecorator footerDecorator = new FooterDecorator();

colorDecorator.AttachTo(invoice);
footerDecorator.AttachTo(colorDecorator);
headerDecorator.AttachTo(footerDecorator);
headerDecorator.CreateInvoice();

invoice.PrintInvoice();

兴趣点

在处理客户需求时,很多时候您没有完整的需求,而是逐步进行开发。可以在这种情况下使用此模式。您可以根据新要求添加Decorators,从而确保您的Base类首先不复杂。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值