Kỹ thuật lập trình hướng đối tượng áp dụng đa hình

Sau đây xin trình bày kỹ thuật lập trình hướng đối tượng áp dụng đa hình trong việc tính lương các loại nhân viên

Bài toán dẫn nhập
Công ty ABC cần xây dựng một ứng dụng quản lý nhân sự và tính lương cho nhân viên trong công ty như sau:
1.  Quản lý thông tin về nhân viên: (Họ tên, ngày sinh, địa chỉ)
2.  Tính lương cho nhân viên
Hiện công ty có 3 loại nhân viên và cách tính lương tương ứng cho từng loại nhân viên như sau:
a.  Nhân viên sản xuất: số sản phẩm x 2000đ
b.  Nhân viên công nhật: số ngày công x 50.000đ
c.  Nhân viên quản lý: lương cơ bản x hệ số lương
Hãy viết chương trình quản lý và tính tổng lương các nhân viên của công ty ABC.
Trước tiên ta phác thảo sơ bộ các lớp cần xây dựng như sau:

NVSANXUAT(HOTEN,NGAYSINH,DIACHI,SOSANPHAM) ; NHAP();XUAT();TINHLUONG().
NVCONGNHAT(HOTEN,NGAYSINH,DIACHI,SONGAYCONG);NHAP();XUAT();TINHLUONG().
NVQUANLY(HOTEN,NGAYSINH,DIACHI,LUONGCOBAN,HESOLUONG);NHAP();XUAT();TINHLUONG().


Ba lớp đối tượng trên có những thuộc tính và phương thức giống nhau. Xây dựng lớp cha có tên là NhanVien chứa những phần giống nhau của 3 lớp trên. Ba lớp trên sẽ kế thừa từ lớp NhanVien.
NhanVien(HoTen,NgaySinh,DiaChi); Nhap();Xuat();TinhLuong().

Tuy nhiên do các công việc Nhập, Xuất, và Tính Lương là khác nhau cho từng loại nhân viên. Đến đây có 2 hướng giải quyết:
1.	 Không sử dụng cơ chế đa hình: 
Ở mỗi lớp con, định nghĩa lại (nạp chồng hàm) 3 phương thức trên.
class NhanVien
{
 private:
  string m_strHoTen;
  string m_strNgaySinh;
  string m_strDiaChi;
 public:
  void Nhap();
  void Xuat();
  float TinhLuong();
};

class NVSanXuat : public NhanVien
{
private:
 int m_iSoSanPham;
public:
 void Nhap();
 void Xuat();
 float TinhLuong();
};

class NVCongNhat : public NhanVien
{
private:
 int m_iSoNgayCong;
public:
 void Nhap();
 void Xuat();
 float TinhLuong();
};

class NVQuanLy : public NhanVien
{
private:
 float m_fHeSoLuong; 
float m_fLuongCoBan; 
public:
 void Nhap();
 void Xuat();
 float TinhLuong();
};



Cài đặt theo cách này, chúng ta cần quản lý 3 danh sách
vector  arrNVSX;
vector  arrNVCN;
vector   arrNVQL;
Trong thao tác nhập liệu cho toàn bộ nhân viên của công ty, tùy vào loại nhân viên sẽ gọi phương thức Nhập tương ứng:
cout <<  “Nhap loai nhan vien (1:NVSX, 2:NVCN, 3:NVQL);
cin >>  iLoai;
switch (iLoai)
{
case 1: 
	NVSanXuat nvSX;
	nvSX.Nhap();
arrNhanVien.push_back(nvSX);
case 2: 
	NVCongNhat nvCN;
	nvCN.Nhap();
arrNhanVien.push_back(nvCN);
case 3:
	NVQuanLy nvQL;
	nvQL.Nhap();
arrNhanVien.push_back(nvQL); 
}

Muốn tính tổng lương của cả danh sách, phải lần lượt tính tổng lương của mỗi danh sách.
float fTongLuong = 0;
for (int i = 0; i < arrNVSX.size(); i++)
		fTongLuong += arrNVSX[i].TinhLuong();

for (int j = 0; j < arrNVCN.size(); j++)
		fTongLuong += arrNVSX[j].TinhLuong();

for (int k = 0; k < arrNVQL.size(); k++)
		fTongLuong += arrNVQL[k].TinhLuong();

2.	Áp dụng kỹ thuật đa hình
class NhanVien
{
private:
 string m_strHoTen;
 string m_strNgaySinh;
 string m_strDiaChi;
public:
 virtual void Nhap() = 0;
 void Xuat() = 0;
 float TinhLuong() = 0;
};

class NVSanXuat : public NhanVien
{
private:
 int SoSanPham;
public:
 void Nhap();
 void Xuat();
 float TinhLuong();
};

class NVCongNhat : public NhanVien
{
private:
 int SoNgayCong;
public:
 void Nhap();
 void Xuat();
 float TinhLuong();

};

class NVQuanLy : public NhanVien
{
private:
 float HeSoLuong; 
 float LuongCoBan; 
public:
 void Nhap();
 void Xuat();
 long TinhLuong();
};

Lúc này chỉ cần một danh sách nhân viên duy nhất để quản lý toàn bộ nhân viên của công ty:
vector arrNhanVien;

//Nhập 1 nhân viên mới
cout << ”Nhap loai nhan vien (1:NVSX, 2:NVCN, 3:NVQL);
cin >> iLoai;
switch(iLoai)
{
 case 1: arrNhanVien.push_back(new NVSanXuat);	break;
 case 2: arrNhanVien.push_back(new NVCongNhat); 	break;
 case 3: arrNhanVien.push_back(new NVQuanLy);	break;
}

arrNhanVien[arrNhanVien.size() – 1].Nhap();

//Tính tổng lương nhân viên
float fTongLuong = 0;
for (i = 0; i < arrNhanVien.size(); i++)
		fTongLuong += arrNhanVien[i].TinhLuong();

Cơ chế đa xạ cho phép gọi đúng những phương thức của đối tượng mà không cần biết trước kiểu dữ liệu của đối tượng đó nhờ vào một con trỏ ảo (virtual pointer) bên trong đối tượng. Con trỏ này giữ địa chỉ của một bảng ảo (virtual table) trong đó chứa thông tin về kiểu dữ liệu và địa chỉ các phương thức tương ứng của đối tượng. Đây được xem là điểm then chốt của cơ chế đa xạ.

Có thể khai báo lớp DanhSachNhanVien để xử lý các nghiệp vụ công ty như sau.
class DanhSachNhanVien
{
private:
 vector arrNhanVien;
public:
 void NhapDanhSach();
 void XuatDanhSach();
 void XuatBangLuong();
 CNhanVien* TimNhanVienLuongCaoNhat();
 CNhanVien* TimNhanVienLuongThapNhat();
 float TongLuong();
…………………………………………………..
};
Áp dụng kỹ thuật tạo đối tượng mẫu
Trong cả 2 giải pháp trên, trong thao tác nhập danh sách nhân viên đều dùng đến bảng chọn (1:NVSX, 2:NVCN, 3:NVQL) và các câu lệnh switch. Bảng chọn trên là khá cứng nhắc, Giả sử có nhu cầu thay đổi thứ tự trên hoặc thêm một loại nhân viên mới, đều phải thay đổi bảng chọn này.
Để giải quyết vấn đề trên, có thể áp dụng kỹ thuật tạo mẫu đối tượng.

class NhanVien
{
	……………………………………………
public:
			virtual NhanVien*  TaoDoiTuong() = 0;
			…………………………………..
};

class NVSanXuat()
{
	……………………………………………
public:
		NhanVien* TaoDoiTuong()
		{
			NhanVien* nv = new NVSanXuat();
			return nv;
		}
		
string TenLop()
		{
			return “NVSanXuat”;
		}
………………………………………….
};

vector  arrDoiTuongMau;
arrDoiTuongMau.push_back(new NVSanXuat);
arrDoiTuongMau.push_back(new NVCongNhat);
arrDoiTuongMau.push_back(new NVQuanLy);

//Nhập 1 nhân viên mới
for (int i = 0; i < arrDoiTuongMau.size(); i++)
 		cout << i + 1 << “:“ << arrDoiTuongMau[i]->TenLop() << endl;
int iLoai;
cin >> iLoai;
arrNhanVien.push_back(arrDoiTuongMau[id-1]->TaoDoiTuong());
Chủ đề liên quan
Kỹ thuật lập trình hướng đối tượng áp dụng đa hình

Cùng chuyên mục

Xem nhiều hôm nay