zoukankan      html  css  js  c++  java
  • 设计模式--行为模式--模板方法

    行为模型:模板方法

    设计一个系统时知道了算法所需的关键步骤,而且确定了这些步骤的执行顺序,但某些步骤的具体实现还未知,或者说某些步骤的实现与具体的环境相关 如:去银行办理业务一般要经过以下4个流程:取号、排队、办理具体业务、对银行工作人员进行评分等,其中取号、排队和对银行工作人员进行评分的业务对每个客户是一样的,可以在父类中实现,但是办理具体业务却因人而异,它可能是存款、取款或者转账等,可以延迟到子类中实现

    模式定义与特点

    • 该模式的主要优点
      1. 它封装了不变部分,扩展可变部分。它把认为是不变部分的算法封装到父类中实现,而把可变部分算法由子类继承实现,便于子类继续扩展。
      2. 它在父类中提取了公共的部分代码,便于代码复用。
      3. 部分方法是由子类实现的,因此子类可以通过扩展方式增加相应的功能,符合开闭原则。
    • 该模式主要缺点
      1. 对每个不同的实现都需要定义一个子类,这会导致类的个数增加,系统更加庞大,设计也更加抽象,间接地增加了系统实现的复杂度。
      2. 父类中的抽象方法由子类实现,子类执行的结果会影响父类的结果,这导致一种反向的控制结构,它提高了代码阅读的难度
      3. 由于继承关系自身的缺点,如果父类添加新的抽象方法,则所有子类都要改一遍。

    模式的应用实例

    • 如下代码,根据业务需求,手机号注册以及账密注册两种方式,注册流程都相同,现业务的区别之处在于存储redis的namespace不同,因此封装了不变部分,扩展可变部分,实现模板方法模式
    import com.dadi01.scrm.foundation.model.error.ErrorEnum;
    import com.dadi01.scrm.foundation.model.exception.ScrmException;
    import com.dadi01.scrm.foundation.utils.date.DateRelatedUtils;
    import com.dadi01.scrm.service.member.api.dto.request.AbstractRegisterRq;
    import com.dadi01.scrm.service.member.provider.domain.MemberDomain;
    import com.dadi01.scrm.service.member.provider.factory.AuthenticatorFactory;
    import com.dadi01.scrm.service.member.provider.service.base.IBaseMemberService;
    import com.dadi01.scrm.service.member.provider.util.CheckModelUtils;
    import com.dadi01.scrm.service.member.provider.util.KeyGenerateUtil;
    import org.apache.commons.lang3.StringUtils;
    import org.springframework.beans.BeanUtils;
    import org.springframework.stereotype.Component;
    
    import java.text.DateFormat;
    import java.text.ParseException;
    import java.text.SimpleDateFormat;
    import java.util.HashMap;
    import java.util.Map;
    
    /**
     * @author lviter
     */
    @Component
    public abstract class RegisterTemplate {
    
        private final AuthenticatorFactory authenticatorFactory;
        private final IBaseMemberService baseMemberService;
        private final KeyGenerateUtil keyGenerateUtil;
    
        public RegisterTemplate(AuthenticatorFactory authenticatorFactory, IBaseMemberService baseMemberService, KeyGenerateUtil keyGenerateUtil) {
            this.authenticatorFactory = authenticatorFactory;
            this.baseMemberService = baseMemberService;
            this.keyGenerateUtil = keyGenerateUtil;
        }
    
        /**
         * 注册统一模板方法
         *
         * @param tenantId
         * @param account
         * @param abstractRegisterRq
         */
        public void registerTemplate(Integer tenantId, String account, AbstractRegisterRq abstractRegisterRq) {
            Long cacheSize = getCache(tenantId, account);
            if (null == cacheSize || cacheSize <= 0) {
                //创建账号
                Long id = generateKey();
                saveMember(id, abstractRegisterRq);
                //放入缓存
                saveCache(abstractRegisterRq.getTenantId(), account, id);
            } else {
                registerMemberDomainValidate(cacheSize, tenantId);
            }
    
        }
    
    
        /**
         * 生成分布式主键
         *
         * @return
         */
        public Long generateKey() {
            return keyGenerateUtil.generate();
        }
    
    
        /**
         * 获取缓存内手机号/账号对应的id
         *
         * @param tenantId
         */
        public Long getCache(Integer tenantId, String account) {
            return (Long) getLoginUserFromCache(tenantId).get(account);
        }
    
        /**
         * 结果存入缓存
         *
         * @param tenantId
         * @param account
         * @param id
         */
        public void saveCache(Integer tenantId, String account, Long id) {
            Map<String, Object> cache = new HashMap<>(2);
            cache.put(account, id);
            saveLoginUserToCache(tenantId, cache);
        }
    
    
        /**
         * 从缓存内获取hash集合
         *
         * @param tenantId
         * @return
         */
        public abstract Map<Object, Object> getLoginUserFromCache(Integer tenantId);
    
        /**
         * 存储缓存
         *
         * @param tenantId
         * @param cache
         */
        public abstract void saveLoginUserToCache(Integer tenantId, Map<String, Object> cache);
    
        /**
         * 保存会员信息
         *
         * @param id
         * @param abstractRegisterRq
         */
        public void saveMember(Long id, AbstractRegisterRq abstractRegisterRq) {
            MemberDomain memberDomain = new MemberDomain(id);
            BeanUtils.copyProperties(abstractRegisterRq, memberDomain);
            CheckModelUtils.checkField(memberDomain);
            if (StringUtils.isNotBlank(abstractRegisterRq.getBirth())) {
                DateFormat fmt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                DateRelatedUtils.convertStringToLongDateString(abstractRegisterRq.getBirth());
                try {
                    memberDomain.setBirth(fmt.parse(abstractRegisterRq.getBirth()));
                } catch (ParseException e) {
                    throw new ScrmException(ErrorEnum.MEMBER_DATE_FORMAT_ERROR.build());
                }
            }
            baseMemberService.save(memberDomain);
        }
    
    
        /**
         * 校验账户
         *
         * @param id
         * @param tenantId
         */
        public void registerMemberDomainValidate(Long id, Integer tenantId) {
            authenticatorFactory.registerMemberDomainValidate(id, tenantId);
        }
    }
    import com.dadi01.scrm.foundation.model.constant.RedisConstant;
    import com.dadi01.scrm.service.member.provider.factory.AuthenticatorFactory;
    import com.dadi01.scrm.service.member.provider.service.base.IBaseMemberService;
    import com.dadi01.scrm.service.member.provider.util.KeyGenerateUtil;
    import com.dadi01.scrm.service.member.provider.util.RedisUtil;
    import org.springframework.stereotype.Component;
    
    import java.util.Map;
    
    /**
     * @author lviter
     */
    @Component
    public class PasswordRegister extends RegisterTemplate {
    
        private final RedisUtil redisUtils;
    
        public PasswordRegister(AuthenticatorFactory authenticatorFactory, IBaseMemberService baseMemberService, KeyGenerateUtil keyGenerateUtil, RedisUtil redisUtils) {
            super(authenticatorFactory, baseMemberService, keyGenerateUtil);
            this.redisUtils = redisUtils;
        }
    
        /**
         * 获取登录账户从缓存中是否存在
         *
         * @param tenantId
         * @return
         */
        @Override
        public Map<Object, Object> getLoginUserFromCache(Integer tenantId) {
            return redisUtils.hmget(RedisConstant.REDIS_PASSWORD_NAMESPACE.concat(String.valueOf(tenantId)));
        }
    
    
        /**
         * 保存账户到缓存内
         *
         * @param tenantId
         * @param memberPhoneCache
         */
        @Override
        public void saveLoginUserToCache(Integer tenantId, Map<String, Object> memberPhoneCache) {
            redisUtils.hmset(RedisConstant.REDIS_PASSWORD_NAMESPACE.concat(String.valueOf(tenantId)), memberPhoneCache);
        }
    }
    import com.dadi01.scrm.foundation.model.constant.RedisConstant;
    import com.dadi01.scrm.service.member.provider.factory.AuthenticatorFactory;
    import com.dadi01.scrm.service.member.provider.service.base.IBaseMemberService;
    import com.dadi01.scrm.service.member.provider.util.KeyGenerateUtil;
    import com.dadi01.scrm.service.member.provider.util.RedisUtil;
    import org.springframework.stereotype.Component;
    
    import java.util.Map;
    
    /**
     * @author lviter
     */
    @Component
    public class SmsRegister extends RegisterTemplate {
        private final RedisUtil redisUtils;
    
        public SmsRegister(AuthenticatorFactory authenticatorFactory, IBaseMemberService baseMemberService, KeyGenerateUtil keyGenerateUtil, RedisUtil redisUtils) {
            super(authenticatorFactory, baseMemberService, keyGenerateUtil);
            this.redisUtils = redisUtils;
        }
    
        @Override
        public Map<Object, Object> getLoginUserFromCache(Integer tenantId) {
            return redisUtils.hmget(RedisConstant.REDIS_PHONE_NAMESPACE.concat(String.valueOf(tenantId)));
        }
    
        @Override
        public void saveLoginUserToCache(Integer tenantId, Map<String, Object> cache) {
            redisUtils.hmset(RedisConstant.REDIS_PHONE_NAMESPACE.concat(String.valueOf(tenantId)), cache);
        }
    
    }
    llh
  • 相关阅读:
    python--模块导入与执行
    python--re模块
    python--递归函数
    CSRF攻击与防御
    XSS跨站脚本攻击
    HTTP协议详解以及URL具体访问过程
    Git服务器搭建
    浅谈PHP异常处理
    常用的几个PHP加密函数
    PHP将数据导出Excel表中(投机型)
  • 原文地址:https://www.cnblogs.com/javallh/p/14344206.html
Copyright © 2011-2022 走看看