---
title: Servant
category: Behavioral
language: es
tag:
- Decoupling
---

## Propósito
Servant se utiliza para proporcionar algún comportamiento a un grupo de clases.
En lugar de definir ese comportamiento en cada clase - o cuando no podemos factorizar
este comportamiento en la clase padre común - se define una vez en el Servant.

## Explicación

Ejemplo del mundo real

> El Rey, la Reina y otros miembros reales de palacio necesitan sirvientes que les den de comer,
> organizar bebidas, etc.

En otras palabras

> Garantiza que un objeto servidor preste determinados servicios a un grupo de clases atendidas.

Wikipedia dice

> En ingeniería de software, el patrón Servant define un objeto utilizado para ofrecer alguna funcionalidad
> a un grupo de clases sin definir esa funcionalidad en cada una de ellas. Un Servant es una clase
> cuya instancia (o incluso sólo clase) proporciona métodos que se encargan de un servicio deseado, mientras que
> los objetos para los que (o con los que) el Servant hace algo, se toman como parámetros.

**Ejemplo programático**

La clase Servant puede prestar servicios a otros miembros reales de palacio.

```java
/**
 * Servant.
 */
public class Servant {

  public String name;

  /**
   * Constructor.
   */
  public Servant(String name) {
    this.name = name;
  }

  public void feed(Royalty r) {
    r.getFed();
  }

  public void giveWine(Royalty r) {
    r.getDrink();
  }

  public void giveCompliments(Royalty r) {
    r.receiveCompliments();
  }

  /**
   * Check if we will be hanged.
   */
  public boolean checkIfYouWillBeHanged(List<Royalty> tableGuests) {
    return tableGuests.stream().allMatch(Royalty::getMood);
  }
}
```

Royalty es una interfaz. Es implementada por las clases King, y Queen para obtener servicios de servant.

```java
interface Royalty {

    void getFed();

    void getDrink();

    void changeMood();

    void receiveCompliments();

    boolean getMood();
}
```
La clase King implementa la interfaz Royalty.
```java
public class King implements Royalty {

    private boolean isDrunk;
    private boolean isHungry = true;
    private boolean isHappy;
    private boolean complimentReceived;

    @Override
    public void getFed() {
        isHungry = false;
    }

    @Override
    public void getDrink() {
        isDrunk = true;
    }

    public void receiveCompliments() {
        complimentReceived = true;
    }

    @Override
    public void changeMood() {
        if (!isHungry && isDrunk) {
            isHappy = true;
        }
        if (complimentReceived) {
            isHappy = false;
        }
    }

    @Override
    public boolean getMood() {
        return isHappy;
    }
}
```
La clase Queen implementa la interfaz Royalty.
```java
public class Queen implements Royalty {

    private boolean isDrunk = true;
    private boolean isHungry;
    private boolean isHappy;
    private boolean isFlirty = true;
    private boolean complimentReceived;

    @Override
    public void getFed() {
        isHungry = false;
    }

    @Override
    public void getDrink() {
        isDrunk = true;
    }

    public void receiveCompliments() {
        complimentReceived = true;
    }

    @Override
    public void changeMood() {
        if (complimentReceived && isFlirty && isDrunk && !isHungry) {
            isHappy = true;
        }
    }

    @Override
    public boolean getMood() {
        return isHappy;
    }

    public void setFlirtiness(boolean f) {
        this.isFlirty = f;
    }

}
```

Luego:

```java
public class App {

    private static final Servant jenkins = new Servant("Jenkins");
    private static final Servant travis = new Servant("Travis");

    /**
     * Program entry point.
     */
    public static void main(String[] args) {
        scenario(jenkins, 1);
        scenario(travis, 0);
    }

    /**
     * Can add a List with enum Actions for variable scenarios.
     */
    public static void scenario(Servant servant, int compliment) {
        var k = new King();
        var q = new Queen();

        var guests = List.of(k, q);

        // feed
        servant.feed(k);
        servant.feed(q);
        // serve drinks
        servant.giveWine(k);
        servant.giveWine(q);
        // compliment
        servant.giveCompliments(guests.get(compliment));

        // outcome of the night
        guests.forEach(Royalty::changeMood);

        // check your luck
        if (servant.checkIfYouWillBeHanged(guests)) {
            LOGGER.info("{} will live another day", servant.name);
        } else {
            LOGGER.info("Poor {}. His days are numbered", servant.name);
        }
    }
}
```

La salida de la consola

```
Jenkins will live another day
Poor Travis. His days are numbered
```


## Diagrama de clases
![alt text](./etc/servant-pattern.png "Servant")

## Aplicabilidad
Utiliza el patrón Servant cuando

* Cuando queremos que algunos objetos realicen una acción común y no queremos definir esta acción como un método en cada clase.

## Créditos

* [Let's Modify the Objects-First Approach into Design-Patterns-First](http://edu.pecinovsky.cz/papers/2006_ITiCSE_Design_Patterns_First.pdf)
