Генератор случайных ракеты и системы ПВО


Моя задача в C#:

  1. Случайная ракета генератора, вырабатывающего 2 типа ракет в секунду: ThermoNuclearBomb и FacetBomb

    • Ракеты имеют свойства серийный номер, тип
  2. Система ПВО, которая определяет 2 типа ракет и нейтрализует каждый из них с другим пистолетом (AntiThermoGun и AntiFacetGun)

    • Система ПВО имеет метод AcceptMissile что принимает Missile в качестве параметра
    • Каждый Gun есть способ Neutralize который принимает соответствующее Missile в качестве параметра и нейтрализует только таких типов ракет.
    • Система ПВО должна решать, какие ракеты будут нейтрализованы с помощью которого пистолет.

У меня есть два интерфейса:

public interface IMissile
    {
         int SerialNumber { get; set; }
         string Type { get; set; }

    }

public interface IGun
    {
         string Name { get; set; }
         void Neutrilize(IMissile missile);
    }

Конечно FacetBomb и ThermoNuclearBomb класс реализует этот интерфейс IMissile:

public class FacetBomb : IMissile
    {
        public int SerialNumber { get; set; }
        private string type;
        public string Type { get; set; }
    }

    public class ThermoNuclearBomb:IMissile
    {
        public int SerialNumber { get; set; }
        public string Type { get ; set ;  }

    }

Вот мои два класса AntiThermoGun и AntiFacetGun что реализовать IGun:

public class AntiThermoGun  : IGun
    {
        private string name;
        public string Name 
        {   get {return name;}
            set { name = "AntiThermoGun"; } 
        }
        public  void Neutrilize(ThermoNuclear gun)
        {
            Console.WriteLine(this.Name + "neutrilizes" + gun.Type);

        }
    }

   public class AntiFacetGun : IGun
    {
        private string name;
        public string Name
        {
            get { return name; }
            set { name = "AntiFacetGun"; }
        }
        public void Neutrilize(FacetBomb missile)
        {
            Console.WriteLine(this.Name + "neutrilizes" + missile.Type);
        }    
    }

Вот мой AirDefence класс, который принимает ракету и решает, какие ракеты будут нейтрализованы с помощью которого пистолет:

public class AirDefenceSystem
    {

        public void InterceptMissile(IMissile missile)
        {
            IGun igun = null;

            switch (missile.Type)
            {
                case "ThermoNuclear":

                    igun = new AntiThermoGun();
                    break;

                case "FacetBomb":
                    igun = new AntiFacetGun();
                    break;
            }
            igun.Neutrilize(missile);
        }
    }

В моей программе.в CS:

 static void Main(string[] args)
        {
            FacetBomb facetBomb = new FacetBomb { SerialNumber = 100, Type = "FacetBomb" };
            FacetBomb facetBomb2 = new FacetBomb { SerialNumber = 200, Type = "FacetBomb" };
            ThermoNuclear thermoBomb = new ThermoNuclear { SerialNumber = 500, Type = "ThermoNuclear" };

            IMissile[] objects = new IMissile[] { facetBomb, facetBomb2, thermoBomb };
            AirDefenceSystem system = new AirDefenceSystem();
            foreach (var item in objects)
            {
                system.InterceptMissile(item);

            }

        }


Комментарии
2 ответа

Рассмотрим ВАР

С помощью var сайта, когда правая сторона присваивания делает тип очевидные можете сократить ваш код и сделать изменение типа гораздо проще.

Ракета type не используется.

Вы используете Typeно не type. Удалить.

Использование конструкторов

Для двух типов ракет, свойства не меняются после того как они были установлены, так что пусть геттер-только свойства и установить их в ракетных конструкторов.

public interface IMissile
{
int SerialNumber { get; }
string Type { get; }
}

public class FacetBomb : IMissile
{
public int SerialNumber { get; private set; }
public string Type { get; private set; }

public FacetBomb(string type, int serialNumber)
{
Type = type;
SerialNumber = serialNumber;
}
}

Избегайте использования строк для сведений о типе

Это типы для того, чтобы удалить тип недвижимости. Когда вам нужно проверить тип, вы можете использовать проверку типа.

public void InterceptMissile(IMissile missile)
{
IGun igun = null;

if(missile is ThermoNuclearBomb)
{
igun = new AntiThermoGun();
}
else if(missile is FacetBomb)
{
igun = new AntiFacetGun();
}

igun.Neutrilize(missile);
}

Это "обезвредить" или "нейтрализовать"

Именования

Ваш интерфейс IMissile но ваши конкретные типы все закончится Bomb. У вас есть переменная с именем igun которая указывает на его тип. Если вы измените тип, то вам придется идти вокруг меняется имя переменной тоже. Вместо того, чтобы рассмотреть имя переменной, которая определяет ее цель, не ее тип.

Что такое серийный номер?

Он никогда не используется, насколько я могу сказать.

Использовать геттер возвращает определенное значение, а не сеттер

Это не имеет большого смыслового значения.

    private string name;
public string Name
{
get {return name;}
set { name = "AntiThermoGun"; }
}

Если я называю .Name = "foo" .Name будет очередное возвращение "AntiThermoGun". Вместо того, чтобы остановить меня от создания .Name на всех:

    public string Name 
{
get {return "AntiThermoGun";}
}

5
ответ дан 5 февраля 2018 в 09:02 Источник Поделиться

Когда я впервые посмотрел на ваш код, я думал, что это не плохое начало для новичка.
Но после того, как внимательно смотрит на него так много ошибок здесь и там, что я больше не могу так сказать, так что простите меня за мою беспощадность.

Большинство из этих ошибок произошло с вашим свойствах, давайте посмотрим на пример:


public class AntiFacetGun : IGun
{
private string name;
public string Name
{
get { return name; }
set { name = "AntiFacetGun"; }
}
}

Единственная причина я могу думать, вы написали, что это потому, что вы не полностью знаете, как свойства работы.
Когда вы создаете свой AntiFacetGun С var gun = new AntiFacetGun()пистолет имя будет иметь значение null.
Когда Вы, наконец, установили пушку имя gun.Name = "thisName" имя будет AntiFacetGun.
Конечный результат будет печальным программист, думая о том, почему gun.Name не "этуназвание".

Лучшим подходом было бы иметь все свойства только для чтения.

public class AntiFacetGun : IGun
{
public string Name
{
get { return "AntiFacetGun"; }
}
}

Это не только решает проблему описывал раньше, но и не дает свойства орудия должны быть изменены.
Это особое отношение к вашему AirDefenceSystem.
Если я создаю FacetBomb С Type отличается от FacetBomb ваш
InterceptMissile будут бросать NullReferenceException положив миллионы жизней в опасности.

В FacetBomb класс Вы тоже оставили на поле type там не используется нигде.

Последнее, но не менее у вас нет способа узнать, если вы успешно перехватила ракету или нет.
Если новый тип ракет появится NullReferenceException будут брошены, как описано раньше.
Это происходит потому, что switch заявление не имеет default дело игнорируя все другие возможные орудия.

Было бы неплохо, чтобы извлечь логику создания пистолета в отдельный метод из-за одного шаблона ответственности.

Это будет результирующий код, если бы вы применили все, что я сказал.

public interface IMissile
{
int SerialNumber { get; }
string Type { get; }
}

public interface IGun
{
string Name { get; }
void Neutrilize(IMissile missile);
}

public class FacetBomb : IMissile
{
public FacetBomb(string serialNumber){
SerialNumber = serialNumber;
}

public int SerialNumber { get; private set; }
public string Type { get { return "FacetBomb"; } }
}

public class ThermoNuclearBomb : IMissile
{
public FacetBomb(string serialNumber){
SerialNumber = serialNumber;
}

public string Type { get { return "ThermoNuclearBomb"; } }
}

public class AntiThermoGun : IGun
{
public string Name { get { return "AntiThermoGun"; } }

public void Neutrilize(ThermoNuclear gun)
{
Console.WriteLine(this.Name + "neutrilizes" + gun.Type);
}
}

public class AntiFacetGun : IGun
{
public string Name { get { return "AntiFacetGun"; } }

public void Neutrilize(FacetBomb missile)
{
Console.WriteLine(this.Name + "neutrilizes" + missile.Type);
}
}

public class AirDefenceSystem
{
private IGun GetGun(IMissile missile)
{
switch (missile.Type)
{
case "ThermoNuclear":
return new AntiThermoGun();
case "FacetBomb":
return new AntiFacetGun();
default:
return null;
}
}

public bool InterceptMissile(IMissile missile)
{
var gun = GetGun(missile);
if(gun == null){
return false;
}
igun.Neutrilize(missile);
return true;
}
}

3
ответ дан 5 февраля 2018 в 09:02 Источник Поделиться