0
点赞
收藏
分享

微信扫一扫

Prompts(一)

米小格儿 03-05 17:30 阅读 5

模板方法模式

文章目录

1.简介

# 模板方法模式
	属于23种设计模式中的行为型模式。在抽象类中公开定义了执行的方法,子类可以按需重写其方法,但是要以抽象类中定义的方式调用方法。
	总结起来就是:定义一个操作的算法结构,而将一些步骤延迟到子类中。在不改变算法结构的情况下,子类能重定义该算法的特定步骤
# 优点
	1.封装不变的逻辑,扩展差异化的逻辑;
	2.抽取公共代码,提高代码的复用性;
	3.父类控制行为,子类实现细节。

# 缺点
	1.不同的实现都需要一个子类去维护,会导致子类的个数不断增加,造成系统更加庞大。

# 总结:将公用的方法抽取到父类,在父类中预留可变的方法,最后子类去实现可变的方法。
# 案例
	需要给不同的管理人员计算各种不同的津贴,如区域总监有区域管理津贴、佣金、培养育成津贴等等。通过分析,每种不用类型的津贴,都是需要金额x比例x系数,比例每种津贴都有不同的计算方式,系数也是。所以,大致的想法就是:金额x比例x系数这个计算方式设置为统一的方法,系数和比例让具体的津贴子类去实现。

2.类图

在这里插入图片描述

3.具体实现

3.1.抽象类(定义统一计算方法)

package com.hrfan.java_se_base.pattern.template_pattern;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.math.BigDecimal;
import java.util.Objects;

/**
 * 需要给不同的管理人员计算各种不同的津贴,如区域总监有区域管理津贴、佣金、培养育成津贴等等。
 * 通过分析,每种不用类型的津贴,都是需要金额x比例x系数,比例每种津贴都有不同的计算方式,系数也是。
 * 所以,大致的想法就是:金额x比例x系数这个计算方式设置为统一的方法,系数和比例让具体的津贴子类去实现。
 * 父类提供具体的计算逻辑
 *  子类继承父类 父类计算逻辑中的值 进行替换(相当于替换文本中的字符)
 *  主管工资计算
 */
public abstract class AbstractManageAllowanceCalService {

	private final Logger logger = LoggerFactory.getLogger(AbstractManageAllowanceCalService.class);
	public BigDecimal calAmount(BigDecimal amount){
		// 如果传入对象为空 那么返回空
		if (Objects.isNull(amount)){
			return BigDecimal.ZERO;
		}
		BigDecimal ratio = getRatio();
		BigDecimal coefficient = getCoefficient();
		logger.error("金额 {}, 系数 {} 比例 {}",amount,coefficient,ratio );
		return amount.multiply(coefficient).multiply(ratio);

	}

	/**
	 * 获取比例
	 */
	protected abstract BigDecimal getRatio();

	/**
	 * 获取系数
	 */
	protected abstract BigDecimal getCoefficient();
}

3.2.定义主管的计算方法

package com.hrfan.java_se_base.pattern.template_pattern;

import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.math.RoundingMode;
/**
 * 主管公司计算类
 * 工人
 */
@Service
public class SupervisorSalaryCalculationService extends AbstractManageAllowanceCalService{

	/**
	 * 主管工资比例
	 * @return
	 */
	@Override
	protected BigDecimal getRatio() {
		return new BigDecimal("0.45").setScale(2, RoundingMode.HALF_UP);
	}

	/**
	 * 主管工资系数
	 * @return
	 */
	@Override
	protected BigDecimal getCoefficient() {
		return new BigDecimal("0.88").setScale(2, RoundingMode.HALF_UP);
	}
}

3.3.定义工人的计算方法

package com.hrfan.java_se_base.pattern.template_pattern;

import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.math.RoundingMode;

/**
 * 工人计算薪资方法
 */
@Service
public class WorkerSalaryCalculationService extends AbstractManageAllowanceCalService{
	/**
	 * 主管工资比例
	 * @return
	 */
	@Override
	protected BigDecimal getRatio() {
		return new BigDecimal("0.45").setScale(2, RoundingMode.HALF_UP);
	}

	/**
	 * 主管工资系数
	 * @return
	 */
	@Override
	protected BigDecimal getCoefficient() {
		return new BigDecimal("0.66").setScale(2, RoundingMode.HALF_UP);
	}
}

4.测试类

package com.hrfan.java_se_base.pattern.template_pattern;

import com.hrfan.java_se_base.config.ResultObject;
import com.hrfan.java_se_base.pattern.template_pattern.params.SalaryParams;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Objects;

/**
 * 薪资计算测试类
 * 实现了扩展applicationContextAware接口,解决静态方法无法获取bean实例调用其方法的问题?
 * 我们发现在静态的Test方法中调用注入的bean直接报错,
 *      这里解释一下:归功于类的加载机制与加载顺序,静态属性与静态代码块最先加载(static静态优先),这里加载静态方法是没有bean实例给你用的,自然会报错。
 */
@RestController
@RequestMapping("/v1/client")
public class SalaryController implements ApplicationContextAware {
	/**
	 * 将上下文静态设置,在初始化组件时就进行静态上下文的覆盖(这个覆盖是将远spring容器的上下文对象引用加到我们预定设置)
	 * 不使用静态方式 可以使用@Service 方式进行注入
	 *
	 * @Resource
	 * private  ApplicationContext applicationContext;
	 * 可实现同等效果 且不用实现任何类 该继承方法适合注入ApplicationContext 为静态类的时候
	 *
	 */
	private static ApplicationContext applicationContext = null;


	@PostMapping("/getSalary")
	public ResultObject getSalary(@RequestBody SalaryParams salaryParams){
		ResultObject instance = ResultObject.createInstance(true);
		AbstractManageAllowanceCalService service = null;
		if ("ZG".equals(salaryParams.getType())){
			// 主管
			service = (SupervisorSalaryCalculationService)applicationContext.getBean("supervisorSalaryCalculationService");
		}else if ("YG".equals(salaryParams.getType())){
			service = (WorkerSalaryCalculationService) applicationContext.getBean("workerSalaryCalculationService");
		}
		if (Objects.nonNull(service)){
			BigDecimal amount = service.calAmount(salaryParams.getAmount());
			instance.setData(amount);
			instance.setSuccess(true);
			instance.setMessage("计算成功!");
			return instance;
		}
		instance.setCode(500);
		instance.setSuccess(false);
		instance.setMessage("未匹配到对应计算方法!");
		return instance;

	}

	@Override
	public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
		SalaryController.applicationContext = applicationContext;
	}
}

测试结果

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

举报

相关推荐

0 条评论