2017-08-20 56 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说 - “动态地将附加职责附加到一个对象。装饰器提供了一个灵活的替代方法来扩展功能”。 [尽管对于非常小数量的预期扩展,前面的答案更有意义。]