2017-08-20 78 views
4

我想知道是否有一些設計模式來幫助我解決這個問題。決定哪個枚舉返回基於對象的屬性

比方說,我有一個類Person它有三個屬性:namenicknamespeaksEnglish和枚舉PersonTypeTypeOneTypeTwoTypeThree

比方說,如果PersonnicknamespeaksEnglish它是TypeOne。如果它有nickame但不是speaksEnglish,它是TypeTwo。如果它沒有nickame,那麼它是TypeThree

我首先想到的方法是一些if-else並返回相關Enum。在未來我可以有更多的屬性在Person和其他類型的PersonType來決定。

所以,我首先想到的是創建了一堆if (...) { return <PersonType> }switch-case的方法,但我想知道如果有一些設計模式,我可以用它代替ifsswitch-case

+0

如何在枚舉中添加一個抽象方法,比方說'布爾測試(Person)',以便每個枚舉類型都能夠檢查人是那種類型。後來你只需要遍歷Enum.values()並調用test(person)。不確定是否是最好的想法,但是你會將邏輯放在一個地方e避免所有if/else –

+0

你的Person對象是可變的還是不可變的? – ByeBye

回答

0

我會推薦你​​使用簡單的繼承與不可變的對象。

所以,首先你必須創建抽象類:

public abstract class AbstractPerson { 

    private final String name; 
    private final Optional<String> nickname; 
    private final boolean speaksEnglish; 
    private final PersonType personType; 

    protected AbstractPerson(final String name, final Optional<String> nickname, final boolean speaksEnglish, final PersonType personType) { 
     this.name = name; 
     this.nickname = nickname; 
     this.speaksEnglish = speaksEnglish; 
     this.personType = personType; 
    } 

    public String getName() { 
     return name; 
    } 

    public Optional<String> getNickname() { 
     return nickname; 
    } 

    public boolean getSpeaksEnglish() { 
     return speaksEnglish; 
    } 

    public PersonType getPersonType() { 
     return personType; 
    } 

} 

隨着PersonType枚舉:

public enum PersonType { 

    TypeOne, TypeTwo, TypeThree; 

} 

現在,我們有相應的構造三個選項中的子類:

public final class EnglishSpeakingPerson extends AbstractPerson { 

    public EnglishSpeakingPerson(final String name, final String nickname) { 
     super(name, Optional.of(nickname), true, PersonType.TypeOne); 
    } 

} 

public final class Person extends AbstractPerson { 

    public Person(final String name, final String nickname) { 
     super(name, Optional.of(nickname), false, PersonType.TypeTwo); 
    } 

    public Person(final String name) { 
     super(name, Optional.empty(), false, PersonType.TypeThree); 
    } 

} 

在這種情況下,我們的具體類是不可變的,它的類型是defi在創作的時刻。你不需要創建if-else梯形圖 - 如果你想創建新的類型,只需創建新的類/構造函數。

0

我不認爲Type確實可以是Person的屬性。我並不反對@ ByeBye的回答,但是在實現時,如果引入了新類型,您仍將最終更改Person類。

X型人最終是一個人本身。假設一個ManagerDeveloper都是一家公司的僱員,所以將它們作爲從Employee派生的專用類很有意義。同樣在你的情況下,將人類類型作爲一個屬性,然後做所有if-else的東西顯然違反了SOLID。

我會改爲具體實現Person類,並將其自身標記爲抽象類。

public abstract class Person { 
    public Person(string name) { 
     Name = name; 
    } 
    public abstract string Name { get; set; } 
    public abstract string NickName { get; set; } 
    public abstract bool SpeaksEnglish { get; set; } 
} 

public class TypeOnePerson : Person { 
    public TypeOnePerson(string name, string nickName) : base(name) { 
     NickName = nickName; // Validate empty/ null 
    } 
    SpeaksEnglish = true; 
} 

public class TypeTwoPerson : Person { 
    public TypeOnePerson(string name, string nickName) : base(name) { 
     NickName = nickName; // Validate empty/ null 
    } 
    SpeaksEnglish = false; 
} 

我也認爲這個問題是語言不可知的,這是一個純粹的設計問題。所以請耐心等待,因爲上面的代碼是用C#編寫的。但是,這並不重要。

+0

我喜歡你的選擇,但我認爲該類型必須是類的一部分 - 我們必須避免使用類似'instanceOf'的構造。如果我們想按類型或類似方式進行過濾將會很有幫助 – ByeBye

+0

您不需要爲類型檢查執行'instanceOf'。因爲你所有的代碼都會和'Person'抽象而不是特定的實現對話。只有在代碼需要'Person'時纔會注入特定的實現。 – niksofteng

+0

但是,如果您有'Person'列表,並且您只想過濾'TypeTwoPerson',則您沒有此類信息 – ByeBye

0

就OO原則而言,爲什麼要用可選屬性組合來創建對象?如果其問題的一個或兩個可選的方法將保持可維護,但類型將基於許多組合(在未來的代碼將充滿布爾代數),問題也說「...在未來,我可以有Person和PersonType中的更多屬性來決定。「」。

我會建議使用Decorator模式的方法,它允許我們創建具有完整代碼重用的自定義對象。 Person將是Component和Optional屬性(它們是類型,例如NickName,其中驗證爲行爲)將是具體的裝飾器。

不限除了人添加新的混凝土裝飾型保持兩個單獨的擔憂。 裝修模式是這類需求的最佳人選。它的意圖來自GOF書籍(通過Erich gamma)pattern Catalog說 - 「動態地將附加職責附加到一個對象。裝飾器提供了一個靈活的替代方法來擴展功能」。 [儘管對於非常小數量的預期擴展,前面的答案更有意義。]