繁体   English   中英

C#消除各个领域方法的歧义

[英]C# Disambiguation of methods for various fields

不知道问题是否足够精确,因此请在阅读完我的问题的解释后纠正我。

控制台应用程序。 简单的游戏。 因此,我有9个燃油泵,每个都将维修车辆。 现在-我需要使用计时器加油的方法(或仅使用基于主游戏计时器的普通vars)。

我的问题是最好的解决方法是什么? 要么为每个泵创建一个单独的方法,要么有一种方法为每个泵使用一个方法(消除变量等)。

先感谢您。

编辑: http : //pastebin.com/JFVZHU41

这似乎是一个广泛的问题,所以我将给您一些想法。 您已用OOP标记问题。 如果您询问“面向对象”的实现方法,则其中一种方法可能是使用方法加油创建类Pump。 然后,您将创建类Pump的实例(每个泵9次)。 如果泵具有不同的属性(例如加油时间),则可以将其作为公共属性。 这只是给您一个想法:

public class Pump
{
    public int RefuellingTimeSeconds { get; set; }
    public void Refuel(Vehicle vehicle)
    {
       //refuelling code here
    }
}

然后,您可以实例化每个泵:

var firstPump = new Pump { RefuellingTimeSeconds = 120 };
var secondPump = new Pump { RefuellingTimeSeconds = 90 };

以上假设所有泵都具有相同的加油程序,只是在某些可以从外部设置的参数上有所不同。

另一方面,如果您有不同类型的泵,并且它们共享的只是加油接口,则可以创建具有不同泵实现的泵接口:

public interface IPump
{
    void Refuel(Vehicle vehicle)
}

public class SlowRefuelPump
{
    public void Refuel(Vehicle vehicle)
    {
       //slow refuelling
    }
}

public class FastRefuelPump
{
    public void Refuel(Vehicle vehicle)
    {
       //fast refuelling
    }
}

然后,您可以根据需要创建泵,并在应用程序中使用它们的接口:

var pumps = new List<IPump> { new SlowRefuelPump(), new FastRefuelPump() };

并将它们用作:

pumps[0].Refuel(_vehicle);
pumps[1].Refuel(_vehicle);

这完全取决于您的情况...

我将创建一个Pump类,其中包含为Car实例加油的逻辑。

这些泵实例中的每一个在泵送时都会引用汽车。 Pump类可以具有一种基于游戏循环增加汽车燃油的方法。

就像是:

public class Pump
{
    private int _fuelRate;
    public Car ServicingCar { get; set; }

    public Pump(int fuelRate = 10)
    {
        _fuelRate = fuelRate;
    }

    public void IncreaseFuel()
    {
        if (ServicingCar == null) return;

        ServicingCar.Fuel += _fuelRate;
    }
}

然后在游戏的某个地方初始化泵:

var pump1 = new Pump();
var pump2 = new Pump(20); // this one is faster

等等...

当您想给汽车加油时,只需分配ServicingCar属性即可。

pump1.ServicingCar = car1;

您可以检查其他汽车是否已经在加油,等等。这将是您要解决的任务。

在您的游戏循环中,您将为每个泵调用“ IncreaseFuel燃料”。

这是最好的方法吗? 由于您的问题的详细程度较低,因此这是非常主观的且难以回答。 但是,这是一种简单的方法。

您无需忘记编写代码和编程,而是先确定需求,然后将其放入简单明了的英语句子中。 这将帮助您设想要解决的问题,并提出更好的心理模型。 现在我不知道您的要求,但我会尝试做一些假设。 例如,以下是编写要求的方法:

  1. 创建一个游戏
  2. 游戏将包括水泵 泵将分配有编号。
  3. 玩家会选择通过输入代表泵数量的
  4. 当玩家选择打气筒时 ,它将被占用一段时间。 之后,泵将可用。
  5. 要启动泵,必须要有车辆在泵旁。

基于这些要求,不要太花哨,使用OO概念,您可以找到名词,这些名词将成为您的类(还有其他一些高级方法,但是从头开始这确实很棒)。 所有粗体均为名词,因此您需要以下类:

  1. 游戏(而不是将其称为“程序”,而将其称为“游戏”。这是整个过程的开始。)
  2. 泵-这将是所有泵的列表
  3. 玩家-玩游戏的玩家。 但是,如果您不跟踪玩家,并且假定只有一位玩家在玩,则可能不需要此功能。
  4. 泵-一台单独的泵。
  5. 车辆

现在让我们集中讨论Pump项。

现在,仔细查看以下措辞:“泵将被占用”,这意味着我们的Pump类将需要一个属性来存储它。 “它将占据一段时间”,这意味着还需要一些东西来跟踪时间。 “要启动泵,将需要车辆”,这意味着我们需要“启动”属性,但这听起来不正确。 属性是一个属性,听起来像一个动作。 因此,“开始”应该是一种方法。

对于属性,请始终考虑“形容词”,例如身高,体重等。对于方法,请始终考虑“动词”,尤其是动作动词,例如“开始”,“停止”,“行走”等。

设计

好的,让我们设计Pump类。 但是在我们这样做之前,让我们澄清一下设计目标。 我们班级的设计应该使我们班级的用户永远不能将泵置于不良状态。 例如,如果水泵已被占用,我们将无法接受其他车辆。 此类用户不应启动泵并为其提供车辆,还应说泵是自由的。 泵将需要某种信号来指示它是空的还是已占用的。

好的,足够的理论,现在有一些代码:

class Pump
{
    public event EventHandler<PumpEventArgs> StatusChanged;
    private System.Timers.Timer timer;
    private Vehicle vehicle;

    public Pump(string name)
    {
        if (string.IsNullOrWhiteSpace(name))
        {
            throw new ArgumentException("The name for the pump is not valid. It cannot be null or empty.");
        }

        this.Name = name;

        this.timer = new System.Timers.Timer();
        this.timer.Elapsed += Timer_Elapsed;
        this.timer.Interval = 100;
        this.timer.AutoReset = true;
    }

    public string Name { get; private set; }

    private void Timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
    {
        // If the pump is not occupied, we do nothing
        if (!this.IsOccupied)
        {
            return;
        }

        // Looks like the pump was occupied and
        // the timer went off so lets make the pump available by setting the
        // vehicle at this pump to null
        this.Vehicle = null;
    }

    // Private set so the only way to set this is to call the start method
    public Vehicle Vehicle
    {
        get
        {
            return this.vehicle;
        }
        private set
        {
            this.vehicle = value;
            if (value == null)
            {
                this.IsOccupied = false;
            }
            else
            {
                this.IsOccupied = true;
            }

            // If anyone has subscribed to the pump change event, notify them and send them the status
            if (this.StatusChanged != null)
            {
                this.StatusChanged(this, new PumpEventArgs { Status = this.Status });
            }
        }
    }

    // private set so the only way a pump is occupied if start has been called.
    // Other classes should not be able to set IsOccupied to false if there is a vehicle at the 
    // pump.
    public bool IsOccupied { get; private set; }

    // This is a read-only property. It depends on the IsOccupied property.
    public string Status
    {
        get
        {
            if (this.IsOccupied)
            {
                return "Occupied";
            }

            return "Free";
        }
    }

    public void Start(Vehicle vehicle)
    {
        // This object should take care of its own rules. If someone calls Start
        // and the pump is busy and they call start again, do not allow it.
        if (this.IsOccupied)
        {
            throw new InvalidOperationException("This pump is already occupied.");
        }

        // Set using property so the property can carry out the other rules
        this.Vehicle = vehicle;

        // Start the pump timer as well
        this.timer.Start();
    }
}

请注意,该类没有Console.WriteLine或其他控制台引用。 此类独立于所有这些。 在泵可用时或一旦被占用等情况下,班级用户可以决定在哪里写消息。也许用户想写到控制台,或者也许用户想显示一个对话框(窗口),或者用户想要将信号发送到真实的灯光并将其变为绿色等。它还应确保确保其始终处于良好状态:如果被占用,则不会返回“自由”状态。 另外,不允许其他人将状态设置为免费。

当泵被占用或空闲时,该类还公开一个事件。 如果班级用户感兴趣,他们将订阅该活动并做他们需要的任何事情。

因此,有Pump类,它应该为您提供有关如何创建良好封装的良好类的许多想法。

这是Vehicle类,但显然还没有结束。

class Vehicle
{

}

这是Game类的方式,但是您需要对其进行更改并向其中添加更多代码。 例如,当水泵被占用时,您可能需要做一些事情。 免费时,您可能还需要其他东西。 我只是在向控制台写一条消息。

class Program
{
    static void Main(string[] args)
    {
        while (true)
        {
            Pump p1 = new Pump("Pump1");

            // Lets make sure to subscribe to StatusChanged event before you start the pump
            // with a new vehicle.
            p1.StatusChanged += StatusChanged;

            p1.Start(new Vehicle());

            Pump p2 = new Pump("Pump2");
            p2.StatusChanged += StatusChanged;
            p2.Start(new Vehicle());

            //Console.Write("Finished...");
            Console.ReadLine();
        }

    }

    // we can use the same handler for all pumps and we can do different things 
    // depending on who the sender is.
    // Or if you prefer, you can have different event handlers
    private static void StatusChanged(object sender, PumpEventArgs e)
    {
        var pump = sender as Pump;
        Console.WriteLine("{0} status changed to {1}.", pump.Name, e.Status);
    }
}

祝好运!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM