Jump to content

Двойной узор

В разработке программного обеспечения шаблон Twin — это шаблон проектирования программного обеспечения , который позволяет разработчикам моделировать множественное наследование в языках программирования, которые не поддерживают множественное наследование. Этот шаблон позволяет избежать многих проблем, связанных с множественным наследованием. [1]

Определение

[ редактировать ]

Вместо одного класса, производного от двух суперклассов, создайте два отдельных подкласса, каждый из которых происходит от одного из двух суперклассов. Эти два подкласса тесно связаны, поэтому оба можно рассматривать как объект-близнец, имеющий два конца. [1]

Применимость

[ редактировать ]

Двойной шаблон можно использовать:

  • для моделирования множественного наследования на языке, в котором множественное наследование не поддерживается
  • чтобы избежать некоторых проблем множественного наследования. [1]

Структура

[ редактировать ]

Будет два или более родительских класса, которые используются для наследования. Будут подклассы, каждый из которых является производным от одного из суперклассов. Подклассы взаимно связаны через поля, и каждый подкласс может переопределять методы, унаследованные от суперкласса. Новые методы и поля обычно объявляются в одном подклассе. [1]

На следующей диаграмме показана типичная структура множественного наследования:

Типичное множественное наследование
Typical multiple inheritance

[1]

На следующей диаграмме показана структура шаблона Twin после замены предыдущей структуры множественного наследования:

Двойной узор
Twin pattern

[1]

Сотрудничество

[ редактировать ]

Каждый дочерний класс отвечает за протокол, унаследованный от родительского класса. Он обрабатывает сообщения этого протокола и пересылает другие сообщения своему партнерскому классу. [1]

Клиенты шаблона-двойника ссылаются на один из объектов-двойников напрямую, а на другой — через его поле-двойник. [1]

Клиенты, использующие протоколы родительских классов, взаимодействуют с объектами соответствующего дочернего класса. [1]

Пример кода

[ редактировать ]

Следующий код представляет собой набросок реализации компьютерной игровой доски с движущимися шариками.

Класс игрового поля:

 
public class Gameboard extends Canvas {
    public int width, height;
    public GameItem firstItem;
    
}

[1]

Эскиз кода для класса GameItem:

public abstract class GameItem {
    Gameboard board;
    int posX, posY;
    GameItem next;
    public abstract void draw();
    public abstract void click (MouseEvent e);
    public abstract boolean intersects (GameItem other);
    public abstract void collideWith (GameItem other);

    public void check() {
        GameItem x;

        for (x = board.firstItem; x != null; x = x.next)
            if (intersects(x))
                collideWith(x);
    }

    public static BallItem newBall(int posX, int posY, int radius) { //method of GameBoard
        BallItem ballItem = new BallItem(posX, posY, radius);
        BallThread ballThread = new BallThread();
        ballItem.twin = ballThread;
        ballThread.twin = ballItem;

        return ballItem;
    }
}

[1]

Эскиз кода для класса BallItem:

public class BallItem extends GameItem {
    BallThread twin;
    int radius; int dx, dy;
    boolean suspended;

    public void draw() {
        board.getGraphics().drawOval(posX - radius, posY - radius, 2 * radius, 2 * radius);
    }

    public void move() { posX += dx; posY += dy; }

    public void click() {
        if (suspended)
            twin.resume();
        else
            twin.suspend();

        suspended = ! suspended;
    }

    public boolean intersects (GameItem other) {
        if (other instanceof Wall)
            return posX - radius <= other.posX
                && other.posX <= posX + radius
                || posY - radius <= other.posY
                && other.posY <= posY + radius;
        else
            return false;
    }

    public void collideWith (GameItem other) {
        Wall wall = (Wall) other;

        if (wall.isVertical)
            dx = - dx;
        else
            dy = - dy;
    }
}

[1]

Эскиз кода для класса BallThread:

public class BallThread extends Thread {
    BallItem twin;

    public void run() {
        while (true) {
            twin.draw();
            /*erase*/
            twin.move();
            twin.draw();
        }
    }
}

[1]

Реализация шаблона Twin

[ редактировать ]

Следует рассмотреть следующие вопросы:

  • Абстракция данных — классы-партнеры класса-близнеца должны быть тесно связаны, так как, вероятно, им необходим доступ к частным полям и методам друг друга. В Java этого можно достичь, поместив партнерские классы в общий пакет и обеспечив видимость пакета для необходимых полей и методов. В Модуле-3 и Обероне классы-партнеры могут быть размещены в общем модуле.
  • Эффективность. Поскольку шаблон Twin использует композицию, требующую пересылки сообщений, шаблон Twin может быть менее эффективным, чем наследование. Однако, поскольку множественное наследование в любом случае немного менее эффективно, чем одиночное, накладные расходы не будут серьезной проблемой. [1] [2]
  • Циклическая ссылка. Шаблон «Двойник» основан на том, что каждый двойник ссылается на другого двойника, что приводит к сценарию циклической ссылки. Некоторые языки могут требовать специальной обработки таких циклических ссылок во избежание утечки памяти . Например, может потребоваться сделать одну ссылку «слабой», чтобы позволить циклу разорваться.

См. также

[ редактировать ]
  1. ^ Перейти обратно: а б с д и ж г час я дж к л м н Мессенбёк, Х., «Твин — шаблон проектирования для моделирования множественного наследования» , Университет Линца, Институт системного программного обеспечения.
  2. ^ Страуструп, Б. (май 1989 г.), Множественное наследование для C++ , Хельсинки: материалы весенней конференции EUUG.
Arc.Ask3.Ru: конец переведенного документа.
Arc.Ask3.Ru
Номер скриншота №: cd40b5c593f53e65ad966d8774fe8173__1681380000
URL1:https://arc.ask3.ru/arc/aa/cd/73/cd40b5c593f53e65ad966d8774fe8173.html
Заголовок, (Title) документа по адресу, URL1:
Twin pattern - Wikipedia
Данный printscreen веб страницы (снимок веб страницы, скриншот веб страницы), визуально-программная копия документа расположенного по адресу URL1 и сохраненная в файл, имеет: квалифицированную, усовершенствованную (подтверждены: метки времени, валидность сертификата), открепленную ЭЦП (приложена к данному файлу), что может быть использовано для подтверждения содержания и факта существования документа в этот момент времени. Права на данный скриншот принадлежат администрации Ask3.ru, использование в качестве доказательства только с письменного разрешения правообладателя скриншота. Администрация Ask3.ru не несет ответственности за информацию размещенную на данном скриншоте. Права на прочие зарегистрированные элементы любого права, изображенные на снимках принадлежат их владельцам. Качество перевода предоставляется как есть. Любые претензии, иски не могут быть предъявлены. Если вы не согласны с любым пунктом перечисленным выше, вы не можете использовать данный сайт и информация размещенную на нем (сайте/странице), немедленно покиньте данный сайт. В случае нарушения любого пункта перечисленного выше, штраф 55! (Пятьдесят пять факториал, Денежную единицу (имеющую самостоятельную стоимость) можете выбрать самостоятельно, выплаичвается товарами в течение 7 дней с момента нарушения.)