2016-09-30 37 views
4

我很難理解是否有時可以接受打破單一責任原則,或者不惜一切代價避免它。SRP應該受到尊重嗎?

請注意以下代碼已被簡化爲只保留相關部分。

我有Hero類,表示一個字符,它可以擁有多個不同的Items
我有從Items繼承的倍數類,例如QuestItemsBackpackItems
當我想在我的Hero上添加Item時,根據Item的種類,我應採取不同的行爲。
我已經試過2個不同的方式做到這一點的第一種尊重SRP:

public abstract class Item 
{ 
    private string _Name{get;set;} 

    public string Name 
    { 
     get 
     { 
      return _Name; 
     } 
     protected set 
     { 
      if (_Name != value) 
      { 
       _Name = value; 
      } 
     } 
    } 
} 

public class QuestItem: Item 
{ 
    public QuestItem(String name) 
    { 
     Name = name; 
    } 
} 

public class BackpackItem: Item 
{ 
    public BackpackItem(String name) 
    { 
     Name = name; 
    } 
} 
public class Hero 
{ 
    public void AddItem(Item item){ 
     if(item is QuestItem){ 
     //Do stuff to add QuestItem 
     return; 
     } 
     if(item is BackpackItem){ 
     //Do stuff to add BackpackItem 
     return; 
     } 
    } 
} 

優點:SRP尊重
缺點:如果我創建一個新項目實物Item繼承和忘記改變我AddItem函數Hero我冒着很多麻煩。
我的AddItem功能成爲

public void AddItem(Item item){ 
      item.AddToHero(this); 
     } 

我的項目類變成:

我的不尊重SRP第二個解決方案

public abstract class Item 
{ 
    private string _Name{get;set;} 

    public string Name 
    { 
     get 
     { 
      return _Name; 
     } 
     protected set 
     { 
      if (_Name != value) 
      { 
       _Name = value; 
      } 
     } 
    } 
    public abstract void AddToHero(Hero hero); 
} 

public class QuestItem: Item 
{ 
    public QuestItem(String name) 
    { 
     Name = name; 
    } 
    public override void AddToHero(Hero hero) 
    { 
     //Do my stuff to add my QuestItem to Hero 
    } 
} 

public class BackpackItem: Item 
{ 
    public BackpackItem(String name) 
    { 
     Name = name; 
    } 
    public override void AddToHero(Hero hero) 
    { 
     //Do my stuff to add my BackpackItem to Hero 
    } 
} 

優勢:我無法忘記從add方法一個新的Item類,因爲我在編譯時會出錯。 缺點:我不尊重SRP,但現在我不明白爲什麼它會如此糟糕。

我更喜歡使用什麼實現? (另一個?)

+1

你只是感興趣的SRP,或所有的SOLID?因爲在第一個例子中,Hero.AddItem方法違反了打開/關閉原則。 –

+0

我對如何學習/應用最佳實踐感興趣,以提高我的代碼質量。 所以我應該/可以改變的任何事情。 – Belterius

回答

2

那麼,只有Heros在存儲庫中有「有」項目嗎?是不是有地點,非英雄角色(也許怪物)等誰也可以擁有物品?

既然您提到這是簡化的,很難給出正確答案的正確答案。也許都不是。

對我來說,這類問題並不是關於SRP,而是關於應該如何泛化,並與KISS平衡。例如,可能是是一個更好的解決方案,將項目和英雄完全分開,而是有相互作用的規則來決定什麼樣的對象可以用什麼方式作爲哪個英雄或角色。因爲你可能面臨的下一個問題是你有不同類型的英雄,也許是一個巫師和一個戰士,他們不能對同樣的東西做同樣的事情。另外,請記住,OOP(單一)繼承往往不能很好地映射到現實世界的情況;考慮使用更多的組合模型。

+0

感謝您的意見。 現在我'Heros'是唯一能與'Items'互動。 整個代碼可以在這裏找到:https://github.com/Belterius/LDVELH/tree/ViewModel/LDVELH_WPF,但我認爲它不會有太大的用處。 你有鏈接到一個「更多組合模型」的例子/教程嗎?到目前爲止,我只接觸過OOP類型的項目。 – Belterius

+1

@Belterius查看https://en.wikipedia.org/wiki/Composition_over_inheritance開始。也值得一讀:https://ericlippert.com/2015/04/27/wizards-and-warriors-part-one/(和以下博客文章) – Lucero

1

首先,SRP很容易被提及和引用,但很多時候經常會在現實中遵循。只要確定「什麼是一個要求」(應該進入一個班級)可能很難。

在你的情況,一個替代方案可能是移動將項目添加到某些英雄的責任(或怪物或什麼!)到自己的類。含義:有時是有意義的創建服務類實現特定一塊行爲影響其他類A,B,C,......但真的不適合任何A,B,C的。 ..

你知道,並不是所有的類都需要反映的「對象」。他們也可以代表「行爲」!因此,考慮如果一些ItemAdderService會幫助你!

+0

你的意思是實現一個接口,將照顧「添加「部分? – Belterius

+0

理想情況下一個接口;允許不同的實現! – GhostCat