2010-11-02 74 views
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() { 
      ... 
     } 
    } 
} 

什么技术或设计模式可用于分离出印刷reponsibility?

思路:

  • 与测试为Invoice每个子类,并运行相应的印码一个伟大的大if声明一个单独的类。这似乎是错误的。
  • 访客模式。问题在于访问者接口需要存在于核心层中,并且引用了定制层中的类。我希望能够在修改Core层的Customized图层中添加新的子类。

回答

1

您可能要考虑Acyclic Visitor (PDF)

+0

有趣的阅读!该解决方案使用多继承和dynamic_cast在C++中提供。我恰好在使用C#,但我想我仍然可以通过将抽象访问类更改为接口来使用它。 – 2010-11-03 00:18:16

+0

查看[这里](http://codecrafter.blogspot.ca/2012/12/the-acyclic-visitor-pattern.html)为C#示例。 – 2012-12-25 05:55:47

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实例。

1

我认为bellow解决方案对于C#很有用,它没有外部参数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); 
    } 
} 
+0

我不确定这有助于消除检查发票的每个子类的if语句。如果我有要打印的发票对象,如何获取适当的InvoicePrinter来打印它? – 2010-11-03 00:12:06

+0

当你知道呼叫者在哪里时,如果你不需要额外的话,但是如果你不知道呼叫者,是的,你应该有经理,我不知道如何防止转换和反思,我会考虑但是直到现在我还没有找到任何好主意 – 2010-11-03 07:19:46

+0

@Joe Daley,我刚刚更新了我的答案,还有一些额外的物件可以删除它。但我认为应该是更好的方法。 – 2010-11-03 09:18:58