Jump to content

Слуга (шаблон проектирования)

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

Описание и простой пример

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

Слуга используется для предоставления некоторого поведения группе классов. Вместо определения этого поведения в каждом классе (или когда мы не можем выделить это поведение в общем родительском классе) оно определяется один раз в Servant.

Например: у нас есть несколько классов, представляющих геометрические объекты (прямоугольник, эллипс и треугольник). Мы можем нарисовать эти объекты на каком-нибудь холсте. Когда нам нужно предоставить метод «перемещения» для этих объектов, мы можем реализовать этот метод в каждом классе или мы можем определить интерфейс, который они реализуют, а затем предложить функциональность «перемещения» в серванте. Интерфейс определяется так, чтобы гарантировать, что обслуживаемые классы имеют методы, необходимые служащему для обеспечения желаемого поведения. Если мы продолжим наш пример, мы определим интерфейс «Movable», указав, что каждый класс, реализующий этот интерфейс, должен реализовать методы «getPosition» и «setPosition». Первый метод получает положение объекта на холсте, а второй устанавливает положение объекта и рисует его на холсте. Затем мы определяем класс-слуга «MoveServant», который имеет два метода «moveTo(Movable movingObject, Positionwhere)» и moveBy(Movable movingObject, int dx, int dy). Класс Servant теперь можно использовать для перемещения любого объекта, реализующего Movable. Таким образом, «перемещающийся» код появляется только в одном классе, который соблюдает правило «разделения ответственности».

Два способа реализации

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

Существует два способа реализации этого шаблона проектирования.

Рисунок 1. Пользователь использует сервант для достижения некоторой функциональности и передает обслуживаемые объекты в качестве параметров.
  1. Пользователь знает серванта (в этом случае ему не нужно знать обслуживаемые классы) и отправляет сообщения со своими запросами экземплярам серванта, передавая обслуживаемые объекты в качестве параметров.
  2. Обслуживаемые классы (геометрические объекты из нашего примера) не знают о слуге, но реализуют интерфейс «IServiced». Пользовательский класс просто вызывает метод служащего и передает обслуживаемые объекты в качестве параметров. Эта ситуация показана на рисунке 1.
Рисунок 2. Пользователь запрашивает операции у обслуживаемых экземпляров, которые затем просят слугу сделать это за них.
  1. Обслуживаемые экземпляры знают слугу, и пользователь отправляет им сообщения со своими запросами (в этом случае ей не обязательно знать слугу). Затем обслуживаемые экземпляры отправляют сообщения экземплярам-слугам с запросом на обслуживание.
  2. На рисунке 2 показана противоположная ситуация, когда пользователь не знает о классе слуг и вызывает непосредственно обслуживаемые классы. Обслуживаемые классы затем запрашивают у слуг достижение желаемой функциональности.

Как реализовать Слугу

[ редактировать ]
  1. Проанализируйте, о каком поведении слуге следует позаботиться. Укажите, какие методы будет определять слуга и что этим методам потребуется от обслуживаемого параметра. Другими словами, что должен предоставить обслуживаемый экземпляр, чтобы методы служащих могли достичь своих целей.
  2. Проанализируйте, какими способностями должны обладать обслуживаемые классы, чтобы их можно было правильно обслуживать.
  3. Мы определяем интерфейс, который будет обеспечивать реализацию объявленных методов.
  4. Определите интерфейс, определяющий запрошенное поведение обслуживаемых объектов. Если какой-то экземпляр хочет, чтобы его обслуживал слуга, он должен реализовать этот интерфейс.
  5. Определить (или каким-то образом приобрести) указанного слугу (его класс).
  6. Реализуйте определенный интерфейс с обслуживаемыми классами.

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

// Servant class, offering its functionality to classes implementing
// Movable Interface
public class MoveServant {
	// Method, which will move Movable implementing class to position where
	public void moveTo(Movable serviced, Position where) {
		// Do some other stuff to ensure it moves smoothly and nicely, this is
		// the place to offer the functionality
		serviced.setPosition(where);
	}

	// Method, which will move Movable implementing class by dx and dy
	public void moveBy(Movable serviced, int dx, int dy) {
		// this is the place to offer the functionality
		dx += serviced.getPosition().xPosition;
		dy += serviced.getPosition().yPosition;
		serviced.setPosition(new Position(dx, dy));
	}
}

// Interface specifying what serviced classes needs to implement, to be
// serviced by servant.
public interface Movable {
	public void setPosition(Position p);

	public Position getPosition();
}

// One of geometric classes
public class Triangle implements Movable {
	// Position of the geometric object on some canvas
	private Position p;

        // Method, which sets position of geometric object
	public void setPosition(Position p) {
		this.p = p;
	}

	// Method, which returns position of geometric object
	public Position getPosition() {
		return this.p;
	}
}

// One of geometric classes
public class Ellipse implements Movable {
	// Position of the geometric object on some canvas
	private Position p;

	// Method, which sets position of geometric object
	public void setPosition(Position p) {
		this.p = p;
	}

	// Method, which returns position of geometric object
	public Position getPosition() {
		return this.p;
	}
}

// One of geometric classes
public class Rectangle implements Movable {
	// Position of the geometric object on some canvas
	private Position p;

	// Method, which sets position of geometric object
	public void setPosition(Position p) {
		this.p = p;
	}

	// Method, which returns position of geometric object
	public Position getPosition() {
		return this.p;
	}
}

// Just a very simple container class for position.
public class Position {
	public int xPosition;
	public int yPosition;

	public Position(int dx, int dy) {
		xPosition = dx;
		yPosition = dy;
	}
}

Подобный шаблон проектирования: команда

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

Шаблоны проектирования Command и Servant очень похожи, и их реализации часто практически одинаковы. Разница между ними заключается в подходе к проблеме.

  • Для шаблона «Слуга» у нас есть несколько объектов, которым мы хотим предложить некоторую функциональность. Мы создаем класс, экземпляры которого предлагают эту функциональность и который определяет интерфейс, который должны реализовать обслуживаемые объекты. Обслуживаемые экземпляры затем передаются в качестве параметров слуге.
  • Для шаблона «Команда» у нас есть несколько объектов, которые мы хотим изменить, придав им некоторую функциональность. Итак, мы определяем интерфейс, команды которого и желаемая функциональность должны быть реализованы. Экземпляры этих команд затем передаются исходным объектам в качестве параметров их методов.

Несмотря на то, что шаблоны проектирования Command и Servant похожи, это не значит, что так всегда. Существует ряд ситуаций, когда использование шаблона проектирования Команда не относится к шаблону проектирования Слуга. В таких ситуациях нам обычно нужно передать вызываемым методам просто ссылку на другой метод, который понадобится ему для достижения своей цели. Поскольку мы не можем передавать ссылки на методы во многих языках, нам необходимо передать объект, реализующий интерфейс, который объявляет сигнатуру переданного метода.

См. также

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

Печиновский, Рудольф; Ярмила Павличкова; Любош Павличек (июнь 2006 г.). Давайте сначала изменим подход «Сначала объекты» на шаблоны проектирования (PDF) . Одиннадцатая ежегодная конференция по инновациям и технологиям в области компьютерных наук, Болонский университет .

Arc.Ask3.Ru: конец переведенного документа.
Arc.Ask3.Ru
Номер скриншота №: d9d239317ca68fc0e91dfdaecc1b4689__1623007020
URL1:https://arc.ask3.ru/arc/aa/d9/89/d9d239317ca68fc0e91dfdaecc1b4689.html
Заголовок, (Title) документа по адресу, URL1:
Servant (design pattern) - Wikipedia
Данный printscreen веб страницы (снимок веб страницы, скриншот веб страницы), визуально-программная копия документа расположенного по адресу URL1 и сохраненная в файл, имеет: квалифицированную, усовершенствованную (подтверждены: метки времени, валидность сертификата), открепленную ЭЦП (приложена к данному файлу), что может быть использовано для подтверждения содержания и факта существования документа в этот момент времени. Права на данный скриншот принадлежат администрации Ask3.ru, использование в качестве доказательства только с письменного разрешения правообладателя скриншота. Администрация Ask3.ru не несет ответственности за информацию размещенную на данном скриншоте. Права на прочие зарегистрированные элементы любого права, изображенные на снимках принадлежат их владельцам. Качество перевода предоставляется как есть. Любые претензии, иски не могут быть предъявлены. Если вы не согласны с любым пунктом перечисленным выше, вы не можете использовать данный сайт и информация размещенную на нем (сайте/странице), немедленно покиньте данный сайт. В случае нарушения любого пункта перечисленного выше, штраф 55! (Пятьдесят пять факториал, Денежную единицу (имеющую самостоятельную стоимость) можете выбрать самостоятельно, выплаичвается товарами в течение 7 дней с момента нарушения.)