likes
comments
collection
share

外观模式

作者站长头像
站长
· 阅读数 20

背景

使用Facade 可以为互相关联在一起的错综复杂的类整理出高层接口(API),其中Facade角色可以让系统对外只有一个简单的接口(API),而且Facade 角色还会考虑到系统内部各个类之间的责任关系和依赖关系,按照正确的顺序调用各个类。

登场角色

Facade 窗口

Facade 角色是代表构成系统的许多其他角色的“简单窗口”。Facade 角色向系统外部提供高层接口(API);

构成系统的许多其他角色

这些角色各自完成自己的工作,它们并不知道Facade 角色。Facade 角色调用其他角色进行工作,但是其他角色不会调用Facade 角色;

Client

负责调用 Facade 角色

类图

外观模式

示例代码

用户点赞之后的一系列操作可封装成一个Facade

LikeServiceImpl 点赞服务

public class LikeServiceImpl extends ServiceImpl<LikeMapper, Like>
        implements LikeService {

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;  // 这里的类型要和config下的redis配置一致

    @Autowired
    private LikeFacade likeFacade;

    @Override
    public BaseResponse<Object> likeResponse(LikeRequest likeRequest) {
        // 是否已经被点赞
        Boolean isLiked = likeRequest.getIsLiked();
        // 资源类型
        Long type = likeRequest.getType();
        // 资源id
        Long ownerId = likeRequest.getOwnerId();
        // 点赞的用户
        Long userId = likeRequest.getUserId();

        // 存储点赞用户集合的key
        String userKey = LIKE_USER_KEY + type + ":" + ownerId;
        // 在hash集合中存储点赞数量的key
        String numsKey = LIKE_NUMS_KEY + type + ":" + ownerId;

        // 获取指定的hashKey
        String hashKey = LikeConstant.hashMap.get(type);
        if (StringUtils.isBlank(hashKey)) {
            hashKey = LIKE_DEFAULT_NUMS_HASH_KEY;
        }

        if (!isLiked) {
            // 添加点赞用户
            redisTemplate.opsForSet().add(userKey, userId);

            // 点赞数量加1
            Boolean aBoolean = redisTemplate.opsForHash().putIfAbsent(hashKey, numsKey, 1);
            // 已经存在了,直接加1即可
            if (!aBoolean) {
                redisTemplate.opsForHash().increment(hashKey, numsKey, 1);
            }

            // 统一处理点赞的后续操作
            likeFacade.executeFacade(String.valueOf(userId), ownerId, type);

            return ResultUtils.success(SuccessCode.LIKE_SUCCESS);
        } else {
            redisTemplate.opsForSet().remove(userKey, userId);
            // 点赞数量减1
            redisTemplate.opsForHash().increment(hashKey, numsKey, -1);
            return ResultUtils.success(SuccessCode.LIKE_CANCEL);
        }
    }
}

LikeFacade 点赞之后的操作

@Component
public class LikeFacade {

    @Autowired
    private ArticleMapper articleMapper;

    @Autowired
    private CommentMapper commentMapper;

    @Autowired
    private MessagePushService messagePushService;

    @Autowired
    private HotRankSender hotRankSender;

    // 执行
    public void executeFacade(String fromId, Long ownerId, Long type) {
        String userId = getUserIdByOwnerId(ownerId, type);

        int messageType = 0;
        if (type.equals(LIKE_ARTICLE_TYPE)) {
            messageType = MESSAGE_LIKE_ARTICLE_TYPE;
        }

        if (type.equals(LIKE_COMMENT_TYPE)) {
            messageType = MESSAGE_LIKE_COMMENT_TYPE;
        }

        // 发送信息
        messagePushService.sendRedDotReminder(fromId, userId, "", ownerId, messageType);


        // 热榜的内容
        if (LIKE_ARTICLE_TYPE.equals(type)) {
            HotRankMessage hotRankMessage = new HotRankMessage();
            hotRankMessage.setHotRank(HotRank.HOT_LIKE);
            hotRankMessage.setOwnerId(ownerId);
            hotRankSender.sendHotRankMessage(hotRankMessage);
        }
    }


    private String getUserIdByOwnerId(Long ownerId, Long type) {
        int userId = -1;
        if (Objects.equals(type, LIKE_ARTICLE_TYPE)) {
            userId = articleMapper.selectUserIdByArticleId(ownerId);
        }

        if (Objects.equals(type, LIKE_COMMENT_TYPE)) {
            userId = commentMapper.selectToIdByOwnerId(ownerId);
        }

        return String.valueOf(userId);
    }
}

功能分析

  1. Facade 模式可以让复杂的东西看起来很简单,接口(API)变少了,但注意不要让类和方法的调用顺序弄错;