2

例如,单一职责原则说,一个Invoice类不应包含打印自身的代码。打印应该被分成不同的类。

但是假设您Invoice在软件的不同层中有一个类层次结构:

namespace CoreLayer {
    public class Invoice {
        public virtual void Print() {
            ...
        }
    }
}

namespace CustomizedLayer {
    public class LaborInvoice : Invoice {
        public override void Print() {
            ...
        }
    }

    public class AccountInvoice : Invoice {
        public override void Print() {
            ...
        }
    }
}

可以使用哪些技术或设计模式来分离印刷责任?

想法:

  • 一个单独的类,带有一个很大的if语句,用于测试每个子类Invoice并运行适当的打印代码。这似乎是错误的。
  • 访客模式。问题是访问者界面需要存在于核心层中,并引用自定义层中的类。我希望能够通过修改核心层在自定义层中添加新的子类。
4

3 回答 3

1

你真的需要子类发票吗?除了打印之外,发票在其他方面是否有所不同?如果不是,则不需要有不同的Invoice类型,您只需将不同InvoicePrinter的类型传递给Invoice实例:

namespace CoreLayer
{
    public class IInvoicePrinter
    {
        void Print(Invoice invoice);
    }

    public class Invoice
    {
    }
}

namespace CustomizedLayer
{
    public class LaborInvoicePrinter : IInvoicePrinter 
    {
        public void Print(Invoice invoice) 
        {
            ...
        }
    }

    public class AccountInvoicePrinter : IInvoicePrinter 
    {
        public void Print(Invoice invoice) 
        {
            ...
        }
    }
}

你应该有某种 IoC 来为你提供适当的InvoicePrinter实例。

于 2010-11-02T08:42:14.260 回答
1

我认为波纹管解决方案对 C# 很有用,它没有 extera if,据我所知,visitor不推荐使用模式。

public class InvoicePrinterManager
{
     public void Print(AccountInvoice invoice)
     {
         AccountInvoicePrinter p1 = new AccountInvoicePrinter(invoice);
         p1.print();
     }

     public void Print(LaborInvoice invoice)
     {
         LaborInvoicePrinter p1 = new LaborInvoicePrinter(invoice);
         p1.print();
     }
}

public class InvoicePrinter<T> where T : Invoice, new()
{
    T instance;

    public InvoicePrinter(T invoice)
    {
        if (invoice != null)
        {
            this.instance = invoice;
        }
        else
            instance = new T();
    }

    public virtual void Print()
    {
        /// Arrange objects as you want and print them.
    }
}

public class AccountInvoicePrinter : InvoicePrinter<AccountInvoice>
{
    public AccountInvoicePrinter(AccountInvoice invoice)
        : base(invoice)
    { 
    }

    public override void Print()
    {
       /// todo
    }
}

public class LaborInvoicePrinter : InvoicePrinter<LaborInvoice>
{
    public LaborInvoicePrinter(LaborInvoice invoice)
        : base(invoice)
    { 
    }
    public override void Print()
    {
        /// todo: use instance
    }
}

public class Test
{
    public void TestPrint()
    {
        LaborInvoice li = new LaborInvoice();
        InvoicePrintManager printerManager = new InvoicePrintManager();
        printerManager.Print(li);
    }
}
于 2010-11-02T09:15:54.087 回答
1

您可能需要考虑非循环访问者 (PDF)

于 2010-11-02T12:17:12.743 回答