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

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

пример:

class dragon
{
    ArrayList<head> = new ArrayList<head> Heads;
    tail Tail = new tail();
    body Body = new body();

    dragon()
    {
        theHead=new head();
        Heads.add(theHead);
    }

    void nod()
    {
        for (int i=0;i<Heads.size();i++)
        {
            heads.get(i).GoUpAndDown();
        }
    }
}

class firedragon extends dragon
{
}

class icedragon extends dragon
{
}

class lightningdragon extends dragon
{
}

// 10 other one-headed dragon declarations here


class hydra extends dragon
{
    hydra()
    {
        anotherHead=new head();
        for (int i=0;i<2;i++)
        {
            Heads.add(anotherHead);
        }
    }
}

class superhydra extends dragon
{
    superhydra()
    {
        anotherHead=new head();
        for (int i=0;i<4;i++)
        {
            Heads.add(anotherHead);
        }
    }
}

Править: (часть 2 вопроса)

Спасибо за ответы. Они были очень полезны. Я на самом деле столкнулся с этой ситуацией несколько раз, и я хотел бы дать второй пример, который не связан с наследованием. Это - на самом деле реальный пример, и хотя я решил, что мой текущий проект является достаточно мелким масштабом для сейфа с использованием векторов на основе ответов, это - понятие, что я предполагаю, что буду использовать в намного более широком масштабе в какой-то момент.

В создании механизма для моего текущего игрового проекта Android я считал необходимым создать объект Imagepoint, который является в основном рядом Координат xy, которые используются для отслеживания значительных частей изображения спрайта. Скажите, что Вам составили символ кости нескольких битовых массивов, полезно знать, где шея присоединяет к туловищу, предплечью к bicep, и т.д. Эти данные смещения xy используются позже для вычисления положения в различных целях, такой как, где расположить другие спрайты при помощи тригонометрических функций, чтобы найти, что xy смещают, учитывая текущий угол.

Большинству объектов спрайта будет нужна только одна точка изображения. bicep нужно один для предплечья, предплечью нужно один для руки, шее нужно один для головы и т.д. Туловища в моих моделях текущего символа являются исключением, и им нужны несколько для плеч, участков, шеи и любых съемных декоративных спрайтов.

Спрайт является объектом, который содержит imagepoint векторы, не будет никаких наследованных классов, потому что каждый: туловище, участок, и т.д. является просто экземпляром класса спрайта, который является строго графическим объектом, содержа указатель на битовый массив, эти imagepoints и различные данные положения/ориентации, и не будет использоваться ни в каких специализированных целях. Если бы я должен был использовать это понятие в крупном масштабе игра с крупными числами экземпляров, где большинство потребовало бы только единственного imagepoint с несколькими объектами, требующими нескольких или ни одного, и где не будет никаких особых случаев, заслуживающих использование наследования. Каковы Ваши мысли были бы?

5
задан casperOne 25 October 2012 в 11:37
поделиться

6 ответов

Да и нет.

Я имею в виду, что ваш вопрос действительно зависит от того, как вы собираетесь использовать эти объекты ... лично мне нравится разделять поведения и атрибуты как можно больше, чтобы «кластеризовать» их в соответствии с типом объекта, который они представляют, не заботясь о повторном использовании некоторых кода немного меньше по сравнению с настоящим подходом наследования, подобным тому, который вы предложили. Что-то вроде:

interface BigLizard
{
  void nod();
}

class Dragon implements BigLizard
{
  Head head;

  void nod() { head.upAndDown(); }
}

class ReallyScaryDragon extends Dragon { ... }

class Hydra implements BigLizard
{
  ArrayList<Head> heads;

  void nod() { for (Head h : heads) h.upAndDown(); }
}

И так далее. Этот подход похож на «иметь ровно то, что вам нужно для ваших объектов, не заставляя что-либо быть конкретным случаем».Конечно, это означает, что он будет иметь две разные реализации nod () , но когда вам не нужно оптимизировать (и вы должны заботиться об этом только в конце), просто придерживайтесь ваших личных предпочтений, предполагая что это не противоречит никаким общепринятым общепринятым стандартам.

Вам не нужно наследовать что-либо от одного объекта, просто настройте иерархию по своему усмотрению .. также составное решение (как уже было предложено) было бы решением, даже если концепция «головной части» не является то же самое для вашего Dragon и для вашей Hydra ..

Третьим решением для вашего конкретного случая может быть использование LinkedList вместо ArrayList . В этом случае всякий раз, когда у вас есть только одна голова, вы не будете тратить место (кроме создания экземпляра списка), и у вас будет только указатель next головы (списка: D), указывающий в никуда. .

2
ответ дан 14 December 2019 в 13:26
поделиться

В этом конкретном случае, вероятно, было бы лучше переопределить nod () для ваших многоголовых драконов. Есть ли у них 1 голова или 5 - это деталь, о которой действительно не стоит беспокоиться в базовом классе (который должен быть настолько простым, насколько вы можете разумно это сделать).

Вы не хотите учитывать каждую возможность, которая может понадобиться каждому из пользователей вашего кода (даже вам) в любой момент времени. В противном случае вам придется учитывать двухголовых собак (которые намного реальнее, чем даже одноголовые драконы). Люди, расширяющие ваши классы, тоже будут разработчиками; позвольте им поработать над более экзотическими / причудливыми случаями, если они в этом нуждаются.

1
ответ дан 14 December 2019 в 13:26
поделиться

Я не думаю, что есть однозначный ответ на этот вопрос. Мне кажется, что это будет зависеть от приложения. Если приложение представляет собой относительно легкую симуляцию дракона, которая никогда не будет иметь дело с более чем несколькими тысячами драконов одновременно, то, вероятно, не составит большого труда использовать вектор. Если, однако, это игра, в которой задействованы миллионы драконов, то, возможно, имеет смысл немного оптимизировать ее и, возможно, сэкономить немного памяти и, возможно, сократить время доступа. Но даже это, вероятно, зависит от реализации базового класса. Вполне возможно, что используемый вами векторный класс может быть оптимизирован для обработки одного элемента без дополнительных накладных расходов.

1
ответ дан 14 December 2019 в 13:26
поделиться

Вы можете изменить реализацию Head на составной тип . Таким образом, каждое расширение Dragon требует только один экземпляр Head , а Head заботится о GoUpAndDown () .

0
ответ дан 14 December 2019 в 13:26
поделиться

Я бы реализовал такие возможности в производных классах. Чтобы это поведение работало, вы должны иметь возможность переопределять методы (в вашем случае метод nod ()). Базовый класс не должен охватывать все возможности, он должен представлять базовый вариант, который может быть расширен. Просто сделайте подходящие методы переопределяемыми, чтобы производные классы могли реализовать конкретное поведение, и все будет работать нормально.

0
ответ дан 14 December 2019 в 13:26
поделиться

Если заголовок общедоступен, он должен быть доступен в виде массива / списка / коллекции, чтобы потребители могли иметь дело с этим.

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

say("Dragon, would you like a yummy princess?");
if(dragon.Stomach.Contents.IsEmpty)
{
    dragon.Nod();
}

по сравнению с:

say("Dragon, would you like a yummy princess?");
dragon.offerFood(princess);

// in dragon class
void offerFood(Food yummyFood)
{
   if(Stomach.Contents.Empty)
   {
        head.Nod(); // can be overridden by subclasses.
   }
}

Во втором примере потребитель класса дракон не заявляет о своих полномочиях заставлять дракона делать что-то ... все, что делает потребитель, - это то, что (говорит что-то, предлагает принцессу) у него есть полномочия делать - дракон должен решать, хочет ли он кивать головой или нет (что имеет смысл. Я сомневаюсь, что я смогу заставить дракона кивать головой, если он не хотел!)

Я называю это «поведенческим», потому что интерфейсы фокусируются на взаимодействиях между объектами (драконом и всем, что предлагает вкусная принцесса), а не на состоянии дракона (его головы).

2
ответ дан 14 December 2019 в 13:26
поделиться
Другие вопросы по тегам:

Похожие вопросы: