模拟实现任务分配(模板模式)

在实际应用中有这样一个场景:有m台服务器,有n个任务,需要把这n个任务按一定策略分配给m台服务器来执行,请按以下要求实现该场景:
1、使用List列表代表服务器(列表中每个元素为一个IP地址);
2、使用List列表代表任务(列表中每个元素为任务ID);
3、分配的过程就是把IP地址与任务ID映射上的过程;
4、策略要支持多个,如按IP地址随机、按任务数量平分等,策略需要支持可扩展(扩展时不用修改已经实现好的策略);

1、实体类定义:

//服务器实体类
public class Service {
	private String IP;
	private String serviceName;

}

//任务实体类
public class Task {
	private Integer taskId;
	private String taskName;
}

2、抽象父类定义(所有的策略实现都需要继承该类)

public abstract class AbstractTaskAllocation {

	/**
	 * 具体的整个过程 在这里定义操作实现的步骤
	 */
	protected void doTaskAllocation(List<Service> serverList, List<Task> taskList) {
		// 1、准备阶段,可以进行一些数据初始化的操作
		this.preparation(serverList, taskList);
		// 2、把IP地址与任务ID映射上阶段
		Map<Object, String> serviceTaskMapping = this.setMapping(serverList, taskList);
		// 3、结果返回阶段
		this.getResult(serviceTaskMapping);
	}

	/**
	 * 1、准备阶段
	 */
	public abstract void preparation(List<Service> serverList, List<Task> taskList);

	/**
	 * 2、把IP地址与任务ID映射上阶段
	 * 
	 * @param taskList
	 * @param serverList
	 */
	public abstract Map<Object, String> setMapping(List<Service> serverList, List<Task> taskList);

	/**
	 * 3、结果返回阶段,分配完后续处理
	 */
	public void getResult(Map<Object, String> serviceTaskMapping){
		// 分配状态查询
		for (Entry<Object, String> entrySet : serviceTaskMapping.entrySet()) {
			System.out.println("服务器IP: " + entrySet.getValue() + " === 任务ID: " + entrySet.getKey());
		}
	}
}

3、平均分配策略:

public class AverageTaskAllocation extends AbstractTaskAllocation {

	// 进行一些参数校验之类的
	@Override
	public void preparation(List<Service> serverList, List<Task> taskList) {
		if (serverList == null || serverList.size() < 1) {
			System.out.println("没有可用的服务器!");
		}
		if (taskList == null || taskList.size() < 1) {
			System.out.println("暂无需要处理的任务!");
		}
	}

	// 设置服务器和任务之间的隐射关系
	@Override
	public Map<Object, String> setMapping(List<Service> serverList, List<Task> taskList) {
		// map key_value 的形式存储服务器和任务的映射关系 id : ip
		//Map<Object, String> serviceTaskMapping = new HashMap<Object, String>();
		Map<Object, String> serviceTaskMapping = new TreeMap<>();
		// 任务平均分配 参考HashMap 的分配原理
		int serverCount = serverList.size();

		for (int i = 0; i < taskList.size(); i++) {
			int taskAddress = i % serverCount;
			serviceTaskMapping.put(taskList.get(i).getTaskId(), serverList.get(taskAddress).getIP());
			//serviceTaskMapping.put(taskList.get(i).getTaskName(), serverList.get(taskAddress).getServiceName());
		}

		return serviceTaskMapping;
	}

	/*@Override
	public void getResult(Map<Object, String> serviceTaskMapping) {
		// 分配状态查询
		for (Entry<Object, String> entrySet : serviceTaskMapping.entrySet()) {
			System.out.println("服务器IP: " + entrySet.getValue() + " === 任务ID: " + entrySet.getKey());
		}
	}*/
}

4、随机分配策略:

public class RandomTaskAllocation extends AbstractTaskAllocation {

	// 进行一些参数校验之类的
	@Override
	public void preparation(List<Service> serverList, List<Task> taskList) {
		if (serverList == null || serverList.size() < 1) {
			System.out.println("没有可用的服务器!");
		}
		if (taskList == null || taskList.size() < 1) {
			System.out.println("暂无需要处理的任务!");
		}
	}

	// 设置服务器和任务之间的隐射关系
	@Override
	public Map<Object, String> setMapping(List<Service> serverList, List<Task> taskList) {

		// map key_value 的形式存储服务器和任务的映射关系 id : ip
		Map<Object, String> serviceTaskMapping = new HashMap<Object, String>();
		// 设置的是随机事件 0或者1 各50%,保证随机分配性
		// 服务器的数量,就是任务分配的概率
		int serverCount = serverList.size();
		Random r = new Random();
		for (int i = 0; i < taskList.size(); i++) {
			Integer serverId = r.nextInt(serverCount);
			serviceTaskMapping.put(taskList.get(i).getTaskId(), serverList.get(serverId).getIP());
		}

		return serviceTaskMapping;
	}
	@Override
	public void getResult(Map<Object, String> serviceTaskMapping) {
		// 可以覆盖父类,进行一些子类特殊操作
	}
}

5、测试类:

public class TaskAllocationTest {

	public static void main(String[] args) {
		List<Service> serverList = new ArrayList<>();
		List<Task> taskList = new ArrayList<>();

		// 添加服务器
		for (int i = 1; i < 11; i++) {
			Service service = new Service();
			service.setIP("10.1.10.3" + i);
			service.setServiceName("我是第"+i+"台服务器");
			serverList.add(service);
		}
		// 添加任务
		for (int i = 0; i < 500; i++) {
			Task task = new Task();
			task.setTaskId(i + 1);
			task.setTaskName("我是第"+i+"个任务");
			taskList.add(task);
		}

		// 随机分配策略:
		AbstractTaskAllocation randomTaskAllocation = new RandomTaskAllocation();
		randomTaskAllocation.doTaskAllocation(serverList, taskList);

		// 平均分配任务策略
		AbstractTaskAllocation averageTaskAllocation = new AverageTaskAllocation();
		averageTaskAllocation.doTaskAllocation(serverList, taskList);

	}
}

6、模板模式要点(不熟悉可以去看设计模式那节)

  • 模版方法定义了算法的步骤,把这些步骤的实现延迟到了子类。
  • 模版方法模式为我们提供了一种代码复用的重要技巧。
  • 模版方法的抽象类可以定义具体方法、抽象方法和钩子。
  • 抽象方法由子类实现。
  • 为了防止子类改变模版方法中的算法,可以将模版方法声明为final
  • 模版方法和策略模式都封装了算法,一个用组合(策略模式),一个用继承(模版方法)。

 

每天努力一点,每天都在进步。

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

powerfuler

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值