【发布时间】:2016-01-25 20:25:03
【问题描述】:
代码示例使用 PHP,但问题与语言无关。
情况
我正在尝试找出将服务层分成多个定义明确的层的最佳方法。
在下面的示例中,我上传了一个 base64 编码的用户头像,并展示了它如何通过图层。我正在使用装饰器模式来模拟图层。
重要:
传递到每一层的数据通常会在传递到下一层之前以某种方式进行更改,这正是我正在寻找的。我不喜欢的一件事是,为了更新头像,您必须首先与ValidatedProfile 对象交谈,而不是说Profile 对象。它看起来很奇怪,但我总是可以拥有一个 Profile 对象,它将调用委托给 ValidatedProfile。
层次
- 验证: 这是您验证数据的地方。在下面的示例中,您可以检查 $avatar 字符串的格式并确保它是有效的图像资源。在验证过程中,通常会创建实体对象和资源,然后将其传递到下一层。
- 验证: 执行检查,例如验证提供的 ID 是否真实。如下例所示,我在这里检查提供的用户 ID 是否实际上是用户的真实 ID。
- 指挥官: 要执行的操作发生在哪里。当到达这一层时,数据被认为是完全验证和验证的,不需要对其进行进一步的检查。指挥官将操作委托给其他服务(通常是实体服务),也可以调用其他服务执行更多操作。
- 实体: 该层处理要对实体和/或其关系执行的操作。
验证配置文件
class ValidatedProfile
{
private $verifiedProfile;
/**
* @param string $avatar Example: data:image/png;base64,AAAFBfj42Pj4
*/
public function updateAvatar($userId, $avatar)
{
$pattern = '/^data:image\/(png|jpeg|gif);base64,([a-zA-Z0-9=\+\/]+)$/';
if (!preg_match($pattern, $avatar, $matches)) {
// error
}
$type = $matches[1]; // Type of image
$data = $matches[2]; // Base64 encoded image data
$image = imagecreatefromstring(base64_decode($data));
// Check if the image is valid etc...
// Everything went okay
$this->verifiedProfile->updateAvatar($userId, $image);
}
}
已验证个人资料
class VerifiedProfile
{
private $profileCommander;
public function updateAvatar($userId, $image)
{
$user = // get user from persistence
if ($user === null) {
// error
}
// User does exist
$this->profileCommander->updateAvatar($user, $image);
}
}
档案指挥官
class ProfileCommander
{
private $userService;
public function updateAvatar($user, $image)
{
$this->userService->updateAvatar($user, $image);
// If any processes need to be run after an avatar is updated
// you can invoke them here.
}
用户服务
class UserService
{
private $persistence;
public function updateAvatar($user, $image)
{
$fileName = // generate file name
// Save the image to disk.
$user->setAvatar($fileName);
$this->persistence->persist($user);
$this->persistence->flush($user);
}
}
然后你可以有一个Profile 类,如下所示:
class Profile
{
private $validatedProfile;
public function updateAvatar($userId, $avatar)
{
return $this->validatedProfile->updateAvatar($userId, $avatar);
}
}
这样你只需与Profile 的实例交谈,而不是ValidatedProfile,我认为这更有意义。
有没有更好和更广泛接受的方法来实现我在这里尝试做的事情?
【问题讨论】:
标签: java php oop model-view-controller service-layer