说我有以下课程

    class FootballPlayer
    {
        public string Name { get; set; }
        public string TeamName { get; set; }

        public int CareerGoals { get; set; }
        public int CareerAssists { get; set; }
        public int CareerPasses { get; set; }

        public int SeasonGoals { get; set; }
        public int SeasonAssists { get; set; }
        public int SeasonPasses { get; set; }

        public int CurrentMatchGoals { get; set; }
        public int CurrentMatchAssists { get; set; }
        public int CurrentMatchPasses { get; set; }
    }


但是我想更好地组织它,那么我该怎么做。此刻,我尝试了类似的操作-

    class CareerDetails
    {
        public int Goals;
        public int Assists;
        public int Passes;
    }

    class CurrentMatchDetails
    {
        public int Goals;
        public int Assists;
        public int Passes;
        public bool IsCaptain;
    }

    class GeneralDetails
    {
        public string Name;
        public string TeamName;
    }

    class SeasonDetails
    {
        public int Goals;
        public int Assists;
        public int Passes;
        public int MatchesPlayed;
    }

    class FootballPlayer
    {
        public CurrentMatchDetails CurrentMatchDetails { get; set; }
        public SeasonDetails SeasonDetails { get; set; }
        public CareerDetails CareerDetails { get; set; }
        public GeneralDetails GeneralDetails { get; set; }
    }


我对此不满意的几件事


我必须公开课程(SeasonDetails,CareerDetails等)
在实例化FootballPlayerClass之后,我必须分别实例化所有这些类。


但是我不确定这是否是最佳实践。我当时正在考虑在FootballPlayer类中创建一个嵌入式类。

我将在WPF应用程序中使用该类,并在INotifyPropertyChanged类上实现FootballPlayer。通过使用上述方法,我将必须将INPC植入所有类(例如CareerDetails等)中。那么我应该怎么做还是应该坚持自己拥有的呢?

我可能还有另一个名为“ FootballTeam”的基类,该基类也可能有一个名为CurrentMatchDetails的子类-看起来像这样

    class CurrentMatchDetails
    {
        public double TimeElapsed;
        public string RefereeName;
    }


因此我应该能够访问诸如teamObject.CurrentMatchDetails.RefereeName或playerObject.CurrentMatchDetails.Goals之类的属性;

最佳答案

我可能还有另一个名为“ FootballTeam”的基类,它也可能有一个名为CurrentMatchDetails的子类。


首先,一个名为FootBallTeam的类不应包含一个名为CurrentMatchDetails的子类。继承不是代码共享机制,而是根据物理世界进行建模。 CurrentMatchDetailsFootballTeam吗?我没办法此类模型的继承工作:

class FootballPlayer
{

}

class StarPlayer : FootballPlayer
{

}


这里StarPlayerFootballPlayer,所以足球运动员的所有那些属性也应该在明星运动员上可用。您应该使用合成,请在此处阅读更多信息:Prefer composition over inheritance?。您的情况FootBallTeam应该是CurrentMatchDetails上的一个属性。

我没有比埃德(他的+1)更好的答案,我只是想进一步充实他。

public class PlayerStat //Add 'Player' to name since stats can be for tourneys too
{
    public int Goals { get; set; }
    public int Assists { get; set; }
    public int Passes { get; set; }
}

public class PlayerCurrentMatchStat : PlayerStat
{
    public bool IsCaptain { get; set; }
}


public class PlayerSeasonStat : PlayerStat
{
    public int MatchesPlayed { get; set; }
}

public class PlayerCareerStat : PlayerStat
{

}


//And your football player goes like this:
class FootballPlayer
{
    public FootballPlay()
    {
        CurrentStats = new CurrentStat();
        SeasonStats = new SeasonStat();
        CareerStats = new CareerStat();
    }

    public string Name { get; set; }
    public string TeamName { get; set; }
    public PlayerCurrentMatchStat CurrentMatchStat { get; set; }
    public PlayerSeasonStat  SeasonStat { get; set; } //no need of naming 'Player'
    public PlayerCareerStat CareerStat { get; set; }  //inside Player class
}


如果某些类的可见性困扰您,可以通过将它们推送到某些特定的名称空间来保护它。最后,即使没有比赛,一支足球队仍然是完全有效的实体。以这种方式建模:

class FootballTeam
{
    // all what makes a good unit
}

class FootballMatch
{
    public FootBallTeam Team1 { get; set; }
    public FootBallTeam Team2 { get; set; }
    public double TimeElapsed { get; set; }
    public string RefereeName { get; set; }
}


说得通。现在这样称呼:

FootballMatch currentMatch = new FootballMatch(...whatever




警报:上面的设计还可以,但仍然有点臭。为什么FootballPlayer会有PlayerCurrentMatchStat?即使坐在板凳上,足球运动员仍然是完美的球员。如果他不在比赛中,也许可以将其设为空。 PlayerSeasonStat同样适用-如果是哪个季节?我会完全重新设计它,而imo则稍微复杂一些,但更具逻辑性。

public interface Stat //common interface which can be for tourneys, matches etc too
{
    int Goals { get; set; }
    int Assists { get; set; }
    int Passes { get; set; }
}
//You might want to break this interface further to fit in other specific stats
//like player stat, match stat etc.
//Also making it an interface rather than base class is better, you shouldnt have
//2 different entities like PlayerStat and MatchStat share a common base class

public class PlayerStat : Stat //can be career stat, single match stat etc;
{                              //depends on context where you call it
    public int Goals { get; set; }
    public int Assists { get; set; }
    public int Passes { get; set; }
}

//another example
public class MatchStat : Stat
{
    public int Goals { get; set; }
    public int Assists { get; set; }
    public int Passes { get; set; }
    public int Viewership { get; set; }
}



class Team
{
    // all what makes a good unit
}

class Match
{
    public Team Team1 { get; set; }
    public Team Team2 { get; set; }
    public double TimeElapsed { get; set; }
    public string RefereeName { get; set; }
    public MatchStat Stat { get; set; } //a match has match stat
}



//provide a suitable constructor that takes a player and a match
public class PlayerMatchStat
{
    public Player Player { get; set; }
    public Match Match { get; set; }
    public PlayerStat Stat { get; set; } //should return player's stat for this match
    public bool IsCaptain { get; set; }
    public int DistanceCompleted { get; set; }
}

//provide a suitable constructor that takes a player and a season
public class PlayerSeasonStat
{
    public bool Player { get; set; }
    public Season Season { get; set; } //have a season class
    public PlayerStat Stat { get; set; } //should return player's stat for this season
    public int RedCards { get; set; }
}


//and lastly
class Player
{
    public Player()
    {
        //init work
    }

    public string Name { get; set; }
    public PlayerStat CareerStat { get; set; } //just like match has match stat
    public Team[] Teams { get; set; } //Team name shouldn't go within a player
                                      //class, he could be in many teams.

    //since player inherently has no match or season, we shall provide methods to query them
    public PlayerMatchStat GetMatchStat(Match match)
    {
        return new PlayerMatchStat(match, this);
    }
    public PlayerSeasonStat GetSeasonStat(Season season)
    {
        return new PlayerSeasonStat(season, this);
    }
}


在这里,很少使用继承(必要时使用),并且用来取得良好效果的是组合。

07-24 19:36