在课堂上应用单一责任原则?

时间:2017-09-24 14:57:13

标签: java solid-principles design-principles

单一责任原则(SRP): -

每个班级都应该承担单一责任。基本上,应该有一个改变的理由。我不确定 最后一个陈述究竟意味着什么。我的解释是,以一种应该有一个改变的理由的方式设计类是可以有一个方法,因为每个方法都是一个行为,因此是理由。那是对的吗?如果没有确切定义的原因是什么?

考虑一个股票交易系统,其中大多数开发人员提出StockService.java同时拥有买卖方法的设计。这里有两个原因(买入和卖出)来改变这个类

public class StockService {

   private String name = "ABC";
   private int quantity = 10;

   public void buy(){
      System.out.println("Stock [ Name: "+name+", 
         Quantity: " + quantity +" ] bought");
   }
   public void sell(){
      System.out.println("Stock [ Name: "+name+", 
         Quantity: " + quantity +" ] sold");
   }

   // other methods related to socks
}

要遵循SRM原则,我是否需要在StockBuyService.java(包含购买相关方法)和StockSellService(包含销售相关方法)的单独类中找到。是吗?

2 个答案:

答案 0 :(得分:0)

不一定。当您认为类的目的是buy()时,sell()StockService方法是有意义的。从名称来看,有理由期望股票服务处理投资者的交易请求,这些交易请求可以是buy()sell()。 (事实上​​,使用单一方法trade()的股票服务可能会违反接口隔离原则,具体取决于它的实施方式。)

可能存在将本类内部的买卖分开的情况,如果您必须一起处理所有类型的交易,而是针对每种类型实施不同的规则或规则。在这种情况下,您可以考虑使用策略模式,该模式使用多态来根据正在发生的交易类型实施规则。但是您的示例课程并没有涉及到这些细节,因此在YAGNI principle之后,您还没有。

但是既然你在问这个问题,那就表明这个名字可能不够清晰。 (在重构的实践中,这被称为代码气味。)现在是审查它并且问自己该类是否正确命名的好时机。这真的是一种股票服务吗?如果班级被命名为StockTradingService,你会不确定吗?你能想到一个更清楚地表达这个班级服务目的的更好的名字吗?我并不是说这个名字不好,或者说它必须改变;我只是说你应该认识到不得不提出这个问题应该引起一些小心谨慎。在你的脑海里举旗。

答案 1 :(得分:0)

首先,正如@MatsLindh评论的那样,在评估SRP时,方法的数量不是一个因素。

让我们调查一下StockService吧!如果您希望StockService承担一项责任,您应该发现一项责任通常意味着您必须在适当的服务抽象层为您的服务定义一个简单的目标。

例如,StockService的目标可以是管理交易,换句话说,描述交易的流程。在这种情况下,StockService将是这样的:

public class StockService{
  PriceService priceService;
  AccountService accountService;
  Stock stock

  public void buy(int amount){
    int fullPrice = getFullPrice(amount);
    if(accountService.hasEnoughMoney(fullPrice){
         accountService.buyStock(stock, amount, fullPrice)
    }
  }
  public void sell(int amount){
     accountService.sellStock(stock,amount)
  }
  private int getFullPrice(int amount){
     return amount * priceService.getPrice(stock);
  }
}

正如您所看到的,该课程只有一个责任:管理交易。它对细节一无所知(如何实施支票或购买)。 改变班级的唯一原因是交易流程的变化。

在我看来,SRP就是要找到适当的抽象层次来定义一个目标,并尽可能少地实现代码或逻辑来覆盖这个目标,让其他类完成其余的工作。