在运行时修改类型层次结构

时间:2014-12-26 13:14:39

标签: c# multiple-inheritance

我甚至无法定义我要找的东西。

我正在编写一个应用来确定锦标赛中的获胜者。我希望我的基类能够根据有多少人正在改变它的继承,因为多重继承不是一种选择,并且我认为可能不会是一个非常好的基类。在它上面。

我看到了

的内容
class Base
{
   //Constructor receiving the quantity of players
   public Base (int quantityOfPlayers)
   {
      //Changes Base inheritance dynamically based on QuantityOfPlayers
      switch (quantityOfPlayers)
      {
         case 4: (Base : FourPlayers);
         case 5: (Base : FivePlayers);
      }
   }
}

但是,我当然无法找到动态改变继承的方法(如果有的话)。否则,我会使用更复杂的方法,尽管每个getter和setter函数都基本相同。


非常好的解决方案。让我补充一点,我使用GUI而不是控制台。

我必须考虑到这一点,工厂班级很好,但它让我确信我不会考虑我的方法。

3 个答案:

答案 0 :(得分:2)

对于这种情况,有一种名为strategy pattern的软件设计模式。

定义游戏策略的界面

public interface IGameStrategy
{
    // Things that depend on the number of players, go here...
}

正确的策略通过constructor injection

注入游戏
public class Game
{
    private IGameStrategy _strategy;

    // Constructor injection
    public Game(IGameStrategy strategy)
    {
        _strategy = strategy;
    }

    // Things common to all types of games go here...
}

定义一个factory方法,如下所示:

private IGameStrategy CreateGameStrategy(int numberOfPlayers)
    switch (numberOfPlayers)
    {
        case 4:
            return FourPlayersStrategy();
        case 5:
            return FivePlayersStrategy();
        default:
            throw new ArgumentException("Invalid number of players");
    }
}

然后创建一个这样的游戏:

var game = new Game(CreateGameStrategy(numberOfPlayers));

当然,策略类实现了接口。他们可以直接这样做,也可以继承实现接口的公共抽象基类。

游戏逻辑分为Game类中实现的所有类型游戏的通用内容,以及特定于策略类中实现的玩家数量的内容。

答案 1 :(得分:1)

您可以创建一个工厂类,根据玩家数量生成适当的类:

public class PlayerQtyFactory
{
    //You can add any other args you might need as well
    public BaseClass CreatePlayerQty(int numPlayers)
    {

      switch (numPlayers)
      {
          Case 2:
            return new TwoPlayers();

          Case 3:
            return new ThreePlayers();

      {
    }
}

如果不了解您正在尝试做什么,很难说这是否是最佳方法,但肯定是 A aproach。

答案 2 :(得分:1)

对于这种特殊情况,我会使用一个工厂(或只是计划工厂)解决方案

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Tester
{
    //declare common functionality
        public interface ISharedFunctionality 
        {
            //put all shared functionality here
            void SomeMethod();
            void SomeOtherMethod();

            void DifferentMethod();
            string Name {get;set;}
        }

        public interface ISinglePlayerFunctionality : ISharedFunctionality
        {
            //put single player functionality here
            void SomeOtherMethod();
            void SomeMethod();
        }

        public interface IMultiplePlayerFunctionality : ISharedFunctionality
        {
            //put multiplayer functionality here
            void DifferentMethod();
            void SomeMethod();
        }

        public class ImplementationBase : ISharedFunctionality
        {
            //shared implementation here
            public void SomeMethod()
            {
                //do stuff
                Console.WriteLine("In Base");
            }
            public void SomeOtherMethod()
            {
                //one you don't want to inherit in multiplayer
                Console.WriteLine("In Base");
            }
            public void DifferentMethod() 
            {
                Console.WriteLine("In Base");
            }


            public string Name
            {
                get;
                set;
            }


        }

        public class MultiPlayerImplementation : ImplementationBase, IMultiplePlayerFunctionality
        {
            //multiplay impl
            // you inherit some method but don't want to inherit 
            //SomeOtherMethod when cast to ISharedFunctionality
            void ISharedFunctionality.SomeMethod()
            {
                //when cast to ISharedFunctionality this method will execute not inherited
                Console.WriteLine("In MutilPlayImplementation");
            } 
        }

        public class SinglePlayerImplementation : ImplementationBase , ISinglePlayerFunctionality
        {
            //singleplay impl

            void ISharedFunctionality.SomeOtherMethod()
            {
                Console.WriteLine("In SinglePlayerImplementation" );
            }


        }

        public class Factory 
        {
            //logic to decide impl here
            public ISharedFunctionality Create(int numberOfPlayer)
            {
                if (numberOfPlayer == 1)
                {
                    return new SinglePlayerImplementation();
                }
                else if(numberOfPlayer > 1)
                {
                    return new MultiPlayerImplementation();
                }

                return null;
            }
        }

    class Program
    {
        static void Main(string[] args)
        {

            var factory = new Factory();
            var results = new[]{factory.Create(1) , factory.Create(2) };

            int j=0;
            foreach (var i in results) 
            {
                ///for single player will be base
                ///multiplaryer will be mutliplayer
                i.SomeMethod();
                //for single player will be single player
                // for multiplayer will be base
                i.SomeOtherMethod();
                i.DifferentMethod();
                i.Name = "Item-Number-" + j;
                Console.WriteLine();
            }

        }
    }
}

这样做的好处是双重的,你现在不再对调用什么方法有歧义,并且你有一个统一的地方来构建基于similair契约的未来实现(即三个玩家行为,不同的菜单行为,如果你想要完全相同的方法只是表现不同

,它可能甚至更少的代码