创建代表雇员集合的类



我有抽象类AbstractEmployee和两个具体子类FixedSalaryEmployeePerHourSalaryEmployee,它们继承AbstractEmployee并覆盖其抽象getSalary方法,并正确实现给定的雇员类型。

首次实现FixedSalaryEmployee-固定工资员工。其中平均月薪等于员工在JSON数据中的工资值。

第二个实现PerHourSalaryEmployee-员工按小时工资。当小时率等于JSON数据中的工资值时,工作日为8小时,月平均为20.88个工作日。

并创建能够处理不同类型员工的Collection类。

主要问题是如何创建代表雇员集合的EmployeeCollection类:

  • 构造函数应该接受JSON文件中的数据,并根据type字段创建相应类的实例。
    • id应以id<number>格式生成,例如(id0,id1等,用于收集中的每个项目)
  • 收集项应按以下规则排序:
    • 按月平均工资降序排序。
    • 如果员工月平均工资相等,则使用员工名称。

需要使用ES5!

//AbstractEmployee.js
var AbstractEmployee = function(id, name, salary) {
if (this.constructor === AbstractEmployee) {
throw new Error("Can't instantiate abstract class!");
}
this.id = id;
this.name = name;
this.salary = salary; 
if(typeof(object.id) !== 'string' || typeof(object.name) !== 'string' || typeof(object.salary) !== 'number'){
throw new Error("Wrong param passed!");
}
};
AbstractEmployee.prototype.getSalary = function() {
throw new Error('Method getSalary() must be implemented');
}
//PerHourSalaryEmployee.js
var AbstractEmployee = require('./AbstractEmployee.js')
var PerHourSalaryEmployee = function(id, name, salary) { 
AbstractEmployee.apply(this, arguments)
this.id = 'id' + id;
this.name = name;
this.salary = salary * 20.88 * 8; 
};
PerHourSalaryEmployee.prototype.getSalary = function() {
return this.salary;
}
module.exports = PerHourSalaryEmployee
//FixedSalaryEmployee.js
var AbstractEmployee = require('./AbstractEmployee.js')
var FixedSalaryEmployee = function(id, name, salary) {
AbstractEmployee.apply(this, arguments);
this.id = 'id' + id;
this.name = name;
this.salary = salary; 
};
FixedSalaryEmployee.prototype.getSalary = function() {
return this.salary;
}
module.exports = FixedSalaryEmployee

employees-collection.json

[{
"type": "per-hour",
"salary": 10,
"name": "Anna"
},
{
"type": "per-hour",
"salary": 8,
"name": "Bob"
},
{
"type": "fixed",
"salary": 8000,
"name": "Dany"
},
{
"type": "fixed",
"salary": 8000,
"name": "Clara"
},
{
"type": "fixed",
"salary": 1000,
"name": "Egor"
}]

正如已经评论过的,一个半成品的AbstractEmployee函数仅仅作为一个基于mixin的函数使用是没有真正意义的。

一个纯粹的老派(它被要求/限制在es5语法中)继承方法更适合。

实际上甚至不需要BaseEmployee构造函数,因为FixedSalaryEmployee类型的功能与BaseEmployee类型的功能完全相同,而PerHourSalaryEmployee类型仅在其salary属性的内部/初始计算中有所不同(但人们永远不知道未来可能会带来什么)…

function orderBySalaryDescendingAndNameAscending(a, b) {
return (b.salary - a.salary) || a.name.localeCompare(b.name);
}
// employee factory.
function createTypeDependedEmployeeVariant(rawData, idx) {
const { type, name, salary } = rawData;
const employee = (type === 'per-hour')
? new PerHourSalaryEmployee(String(idx), name, salary)
: new FixedSalaryEmployee(String(idx), name, salary)
// employee.type = type;
return employee;
}
// employee list factory.
function createOrderedListOfVariousEmployeeInstances(arr) {
return arr
.map(createTypeDependedEmployeeVariant)
.sort(orderBySalaryDescendingAndNameAscending);
}
const jsonDataList = [{
"type": "per-hour",
"salary": 10,
"name": "Anna"
}, {
"type": "per-hour",
"salary": 8,
"name": "Bob"
}, {
"type": "fixed",
"salary": 8000,
"name": "Dany"
}, {
"type": "fixed",
"salary": 8000,
"name": "Clara"
}, {
"type": "fixed",
"salary": 1000,
"name": "Egor"
}];
console.log(
createOrderedListOfVariousEmployeeInstances(jsonDataList)
.map(({ id, name, salary }) => ({ id, name, salary }))
);
console.log(
createOrderedListOfVariousEmployeeInstances(jsonDataList)
.map(item => item.getSalary())
);
console.log(
createOrderedListOfVariousEmployeeInstances(jsonDataList)
);
.as-console-wrapper { min-height: 100%!important; top: 0; }
<script>
function BaseEmployee(id, name, salary) {
if (
(typeof id !== 'string') ||
(typeof name !== 'string') ||
(typeof salary !== 'number') ||
!Number.isFinite(salary)
) {
throw new TypeError('Wrong parameter(s) passed!');
}
this.id = 'id' + id;
this.name = name;
this.salary = salary;
}
BaseEmployee.prototype.getSalary = function() {
return this.salary;
}
</script>
<script>
function PerHourSalaryEmployee (id, name, salary) {
// super call.
BaseEmployee.apply(this, arguments);
this.salary = (salary * 20.88 * 8);
};
// extend superclass.
PerHourSalaryEmployee.prototype = Object.create(BaseEmployee.prototype);
// prevent super constructor from being the sub-classed constructor.
PerHourSalaryEmployee.prototype.constructor = PerHourSalaryEmployee;
</script>
<script>
function FixedSalaryEmployee(id, name, salary) {
// super call.
BaseEmployee.apply(this, arguments);
};
// extend superclass.
FixedSalaryEmployee.prototype = Object.create(BaseEmployee.prototype);
// prevent super constructor from being the sub-classed constructor.
FixedSalaryEmployee.prototype.constructor = FixedSalaryEmployee;
</script>

最优化的Employee类代码库看起来像下面提供的代码。与上面提供的工厂相比,上面的代码库具有额外的BaseEmployee

function checkEmployeeArguments(id, name, salary) {
if (
(typeof id !== 'string') ||
(typeof name !== 'string') ||
(typeof salary !== 'number') ||
!Number.isFinite(salary)
) {
throw new TypeError('Wrong parameter(s) passed!');
}
}
function FixedSalaryEmployee(id, name, salary) {
checkEmployeeArguments(id, name, salary);
this.id = 'id' + id;
this.name = name;
this.salary = salary;
}
FixedSalaryEmployee.prototype.getSalary = function() {
return this.salary;
}
function PerHourSalaryEmployee (id, name, salary) {
// super call.
FixedSalaryEmployee.apply(this, arguments);
this.salary = (salary * 20.88 * 8);
};
// extend superclass.
PerHourSalaryEmployee.prototype = Object.create(FixedSalaryEmployee.prototype);
// prevent super constructor from being the sub-classed prototype constructor.
PerHourSalaryEmployee.prototype.constructor = PerHourSalaryEmployee;

最新更新