Mapper (Распределитель)

Паттерн проектирования Mapper

Паттерн проектирования Mapper

Описание Mapper

Объект, который управляет сообщением между независимыми друг от друга объектами.

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

Примеры реализации

// Mapper Pattern in JavaScript
class User {
    constructor(id, name, email) {
        this.id = id;
        this.name = name;
        this.email = email;
    }
}

class UserDTO {
    constructor(id, fullName, emailAddress) {
        this.id = id;
        this.fullName = fullName;
        this.emailAddress = emailAddress;
    }
}

class UserMapper {
    static toDTO(user) {
        return new UserDTO(
            user.id,
            user.name,
            user.email
        );
    }
    
    static toEntity(dto) {
        return new User(
            dto.id,
            dto.fullName,
            dto.emailAddress
        );
    }
    
    static mapArray(users) {
        return users.map(user => UserMapper.toDTO(user));
    }
}

class NotificationService {
    constructor() {
        this.mapper = UserMapper;
    }
    
    sendWelcomeEmail(user) {
        const userDTO = this.mapper.toDTO(user);
        console.log(`Sending welcome email to ${userDTO.fullName} at ${userDTO.emailAddress}`);
        return { success: true, messageId: `msg_${Date.now()}` };
    }
}

// Usage
const user = new User(1, 'John Doe', 'john@example.com');
const notificationService = new NotificationService();
const result = notificationService.sendWelcomeEmail(user);
console.log('Notification result:', result);
<?php
// Mapper Pattern in PHP
class User {
    private $id;
    private $name;
    private $email;
    
    public function __construct($id, $name, $email) {
        $this->id = $id;
        $this->name = $name;
        $this->email = $email;
    }
    
    public function getId() { return $this->id; }
    public function getName() { return $this->name; }
    public function getEmail() { return $this->email; }
}

class UserDTO {
    private $id;
    private $fullName;
    private $emailAddress;
    
    public function __construct($id, $fullName, $emailAddress) {
        $this->id = $id;
        $this->fullName = $fullName;
        $this->emailAddress = $emailAddress;
    }
    
    public function getId() { return $this->id; }
    public function getFullName() { return $this->fullName; }
    public function getEmailAddress() { return $this->emailAddress; }
}

class UserMapper {
    public static function toDTO($user) {
        return new UserDTO(
            $user->getId(),
            $user->getName(),
            $user->getEmail()
        );
    }
    
    public static function toEntity($dto) {
        return new User(
            $dto->getId(),
            $dto->getFullName(),
            $dto->getEmailAddress()
        );
    }
    
    public static function mapArray($users) {
        return array_map(function($user) {
            return UserMapper::toDTO($user);
        }, $users);
    }
}

class NotificationService {
    private $mapper;
    
    public function __construct() {
        $this->mapper = UserMapper::class;
    }
    
    public function sendWelcomeEmail($user) {
        $userDTO = UserMapper::toDTO($user);
        echo "Sending welcome email to {$userDTO->getFullName()} at {$userDTO->getEmailAddress()}\n";
        return ['success' => true, 'messageId' => 'msg_' . time()];
    }
}

// Usage
$user = new User(1, 'John Doe', 'john@example.com');
$notificationService = new NotificationService();
$result = $notificationService->sendWelcomeEmail($user);
echo "Notification result: " . json_encode($result) . "\n";
?>
// Mapper Pattern in Go
package main

import (
    "fmt"
    "time"
)

type User struct {
    ID    int
    Name  string
    Email string
}

type UserDTO struct {
    ID          int
    FullName    string
    EmailAddress string
}

type UserMapper struct{}

func (um UserMapper) ToDTO(user User) UserDTO {
    return UserDTO{
        ID:          user.ID,
        FullName:    user.Name,
        EmailAddress: user.Email,
    }
}

func (um UserMapper) ToEntity(dto UserDTO) User {
    return User{
        ID:    dto.ID,
        Name:  dto.FullName,
        Email: dto.EmailAddress,
    }
}

func (um UserMapper) MapArray(users []User) []UserDTO {
    dtos := make([]UserDTO, len(users))
    for i, user := range users {
        dtos[i] = um.ToDTO(user)
    }
    return dtos
}

type NotificationService struct {
    mapper UserMapper
}

func NewNotificationService() *NotificationService {
    return &NotificationService{
        mapper: UserMapper{},
    }
}

func (ns *NotificationService) SendWelcomeEmail(user User) map[string]interface{} {
    userDTO := ns.mapper.ToDTO(user)
    fmt.Printf("Sending welcome email to %s at %s\n", userDTO.FullName, userDTO.EmailAddress)
    return map[string]interface{}{
        "success":   true,
        "messageId": fmt.Sprintf("msg_%d", time.Now().Unix()),
    }
}

// Usage
func main() {
    user := User{ID: 1, Name: "John Doe", Email: "john@example.com"}
    notificationService := NewNotificationService()
    result := notificationService.SendWelcomeEmail(user)
    fmt.Printf("Notification result: %+v\n", result)
}

Использована иллюстрация с сайта Мартина Фаулера.

Источник