Design patterns 面向对象编程中的多对多关系

Design patterns 面向对象编程中的多对多关系,design-patterns,oop,Design Patterns,Oop,建立多对多关系模型的最佳方法是什么 假设我们有两个班,团队和球员 任何给定的玩家都可以在多个团队中 任何团队都可以拥有任意数量的球员 我喜欢调用这样的方法 playerX.getTeamList()获取他/她所在的所有团队的列表 teamY.getPlayerList()获取团队中所有玩家的列表 (或者有其他有效的方法) 我可以想出两种方法,但它们感觉不是很好的oop模式。 你能想出什么好办法,也许是一种设计模式吗?很好,Player有一个Team的集合,Team有一个Player的集合

建立多对多关系模型的最佳方法是什么

假设我们有两个班,团队球员

  • 任何给定的玩家都可以在多个团队中
  • 任何团队都可以拥有任意数量的球员
我喜欢调用这样的方法

  • playerX.getTeamList()
    获取他/她所在的所有团队的列表
  • teamY.getPlayerList()
    获取团队中所有玩家的列表
(或者有其他有效的方法)

我可以想出两种方法,但它们感觉不是很好的oop模式。
你能想出什么好办法,也许是一种设计模式吗?

很好,
Player
有一个
Team
的集合,
Team
有一个
Player
的集合。您需要注意添加/删除操作的完整性,因为它们不是“原子的”


完全合理

区分API感觉和实际实现是值得的

虽然这两个类公开这样一个集合(例如get*List())是有意义的,但它们不必持有集合的实例


我建议你创建一个
联盟
类或类似的类,它包含某种私人球员团队映射字典。通过团队/玩家实例添加到这些“集合”中,应该调用
League
实例上的内部方法来更新映射。通过这种方式,您可以保持更新的原子性(正如Andrey所建议的那样)和无错误性。

IMHO您所描述的是OO的“自然”方式。您的XXX.getXXXList()是类的接口。对于数量有限的类来说,这是正确的方法

假设有1000个类可以“互连”。有一些ManyToManyManager插入一个对象,将另一个对象添加到一个对象的相关对象中,并检索与另一个对象相关的所有对象的列表,这可能会更有趣。这将是某种形式的授权与实施


舒尔如果您将多对多委托给另一个实例,您的对象模型将不再反映多对多关系。

威尔的回答是正确的。然而,要处理同步,我可能会从。让关系的一方成为“主控”,跟踪另一方的添加/删除并处理同步


但是,请注意,如果一个对象订阅另一个对象上的事件,则这是一个强引用,将阻止垃圾收集。他们很可能同时离开比赛场地,所以这不是问题,但需要注意。

球员和球队之间的关系。 期待评论(和否决票?)!我是乌德·努伯

    class MyPlayer
    {
        public string Name { get; set; }

        public MyPlayer(string n)
        {
            Name = n;
        }
    }

    class MyTeam
    {
        public string Name { get; set; }

        public MyTeam(string n)
        {
            Name = n;
        }
    }

    class PlayerTeamPair
    {
        public MyPlayer Player { get; set; }
        public MyTeam Team { get; set; }

        public PlayerTeamPair(MyPlayer p,MyTeam t)
        {
            Player = p;
            Team  = t;
        }
    }

    class PlayerTeamBipartiteGraph
    {
        public List<PlayerTeamPair> Edges { get; set; }

        public PlayerTeamBipartiteGraph()
        {
            Edges = new List<PlayerTeamPair>();
        }

        public void AddPlayerAndTeam(MyPlayer p, MyTeam t)
        {
            Edges.Add(new PlayerTeamPair(p, t));
        }

        public List<MyTeam> GetTeamList(MyPlayer p)
        {
            var teams = from e in Edges where e.Player == p select e.Team;
            return teams.ToList<MyTeam>();
        }

        public List<MyPlayer> GetPlayerList(MyTeam t)
        {
            var players = from e in Edges where e.Team == t select e.Player;
            return players.ToList<MyPlayer>();
        }

    }


    class Program
    {
        static void Main(string[] args)
        {
            var G = new PlayerTeamBipartiteGraph();

            MyPlayer a = new MyPlayer("A");
            MyPlayer b = new MyPlayer("B");
            MyPlayer c = new MyPlayer("C");
            MyPlayer d = new MyPlayer("D");

            MyTeam t1 = new MyTeam("T1");
            MyTeam t2 = new MyTeam("T2");

            G.AddPlayerAndTeam(a, t1);
            G.AddPlayerAndTeam(b, t1);
            G.AddPlayerAndTeam(c, t1);
            G.AddPlayerAndTeam(b, t2);
            G.AddPlayerAndTeam(d, t2);

            G.GetTeamList(b).ForEach(t => Console.Write(" {0} ",t.Name));
            Console.WriteLine();
            G.GetPlayerList(t2).ForEach(p => Console.Write(" {0} ",p.Name));
            Console.WriteLine();
        }
    }
classmyplayer
{
公共字符串名称{get;set;}
公共MyPlayer(字符串n)
{
Name=n;
}
}
班级小组
{
公共字符串名称{get;set;}
公共MyTeam(字符串n)
{
Name=n;
}
}
班对
{
公共MyPlayer播放器{get;set;}
公共MyTeam团队{get;set;}
公共玩家团队对(我的玩家p,我的团队t)
{
玩家=p;
团队=t;
}
}
类PlayerTeamBipartiteGraph
{
公共列表边{get;set;}
public PlayerTeamBipartiteGraph()
{
边=新列表();
}
公共无效添加玩家团队(我的玩家p,我的团队t)
{
添加(新的PlayerTeamPair(p,t));
}
公共列表GetTeamList(MyPlayer p)
{
var teams=从边中的e开始,其中e.Player==p选择e.teams;
返回团队。ToList();
}
公共列表GetPlayerList(MyT团队)
{
var players=来自e的边,其中e.Team==t选择e.Player;
return players.ToList();
}
}
班级计划
{
静态void Main(字符串[]参数)
{
var G=新的playerTeamBiPartItemGraph();
MyPlayer a=新的MyPlayer(“a”);
MyPlayer b=新的MyPlayer(“b”);
MyPlayer c=新的MyPlayer(“c”);
MyPlayer d=新MyPlayer(“d”);
MyTeam t1=新的MyTeam(“t1”);
MyTeam t2=新的MyTeam(“t2”);
G.addplayeranteam(a,t1);
G.addplayeranteam(b,t1);
G.AddPlayerAndTeam(c,t1);
G.addplayeranteam(b,t2);
G.AddPlayerAndTeam(d,t2);
GetTeamList(b).ForEach(t=>Console.Write(“{0}”,t.Name));
Console.WriteLine();
GetPlayerList(t2).ForEach(p=>Console.Write(“{0}”,p.Name));
Console.WriteLine();
}
}

将多对多关系拆分为两个一对多关系。使一切变得简单。

您忽略了真正的问题,即需要保持内容同步。保证这一点的一个方法是在另一个方面实现一个。@rein谁说这是“真正的问题”?除非我们知道他的申请书是怎么写的,否则我们无法判断问题是什么。他没有具体说明它们是模型(装满数据并在途中发送的无逻辑无人机)还是实体(具有支持延迟加载和其他存储模式的丰富框架的类)或其他什么。最简单的模型是由存储库或某种存储层实例化这些类型,存储层负责影响团队和玩家的所有操作。。。我们以前在哪里见过这个问题:)你得到了你的-1。这实际上是伪装成OOP的函数式编程。我甚至不确定二部图是否是一种设计模式。
    class MyPlayer
    {
        public string Name { get; set; }

        public MyPlayer(string n)
        {
            Name = n;
        }
    }

    class MyTeam
    {
        public string Name { get; set; }

        public MyTeam(string n)
        {
            Name = n;
        }
    }

    class PlayerTeamPair
    {
        public MyPlayer Player { get; set; }
        public MyTeam Team { get; set; }

        public PlayerTeamPair(MyPlayer p,MyTeam t)
        {
            Player = p;
            Team  = t;
        }
    }

    class PlayerTeamBipartiteGraph
    {
        public List<PlayerTeamPair> Edges { get; set; }

        public PlayerTeamBipartiteGraph()
        {
            Edges = new List<PlayerTeamPair>();
        }

        public void AddPlayerAndTeam(MyPlayer p, MyTeam t)
        {
            Edges.Add(new PlayerTeamPair(p, t));
        }

        public List<MyTeam> GetTeamList(MyPlayer p)
        {
            var teams = from e in Edges where e.Player == p select e.Team;
            return teams.ToList<MyTeam>();
        }

        public List<MyPlayer> GetPlayerList(MyTeam t)
        {
            var players = from e in Edges where e.Team == t select e.Player;
            return players.ToList<MyPlayer>();
        }

    }


    class Program
    {
        static void Main(string[] args)
        {
            var G = new PlayerTeamBipartiteGraph();

            MyPlayer a = new MyPlayer("A");
            MyPlayer b = new MyPlayer("B");
            MyPlayer c = new MyPlayer("C");
            MyPlayer d = new MyPlayer("D");

            MyTeam t1 = new MyTeam("T1");
            MyTeam t2 = new MyTeam("T2");

            G.AddPlayerAndTeam(a, t1);
            G.AddPlayerAndTeam(b, t1);
            G.AddPlayerAndTeam(c, t1);
            G.AddPlayerAndTeam(b, t2);
            G.AddPlayerAndTeam(d, t2);

            G.GetTeamList(b).ForEach(t => Console.Write(" {0} ",t.Name));
            Console.WriteLine();
            G.GetPlayerList(t2).ForEach(p => Console.Write(" {0} ",p.Name));
            Console.WriteLine();
        }
    }