Bài tập 1, học cách vận dụng tính đóng gói + đa hình
Câu hỏi: Viết chương trình mô phỏng mượn sách trong thư viện, mỗi user chỉ được mượn tối đa 3 quyển sách, riêng vip user được mượn 10 quyển sách.
Biết cấu trúc Class hiện tại đang như sau, làm ở các phần có chữ .. điền code vào đây
và bổ sung class VipUser thể hiện được mượn 10 quyển sách
<?php
class Book
{
public int $id; // mã sách, unique
public string $title; // tên sách
private bool $borrowed = false; // đã được mượn hay chưa
public function borrow(): void
{
if ($this->borrowed) {
throw new Exception("Sách '{$this->title}' đã được mượn!");
}
$this->borrowed = true;
}
public function giveBack(): void
{
$this->borrowed = false;
}
}
class User
{
protected string $name;
private array $borrowedBooks = [];
public function __construct(string $name)
{
$this->name = $name;
}
public function borrowBook(Book $book): void
{
//.. điền code vào đây
}
public function returnBook(Book $book): void
{
foreach ($this->borrowedBooks as $key => $b) {
if ($b === $book) {
unset($this->borrowedBooks[$key]);
$book->giveBack();
return;
}
}
throw new Exception("{$this->name} không mượn sách này!");
}
}
class Library
{
private array $books = [];
public function addBook(Book $book): void
{
$this->books[] = $book;
}
public function borrow(string $title, User $user): void
{
foreach ($this->books as $book) {
if ($book->getTitle() === $title) {
//.. điền code vào đây
return;
}
}
throw new Exception("Không tìm thấy sách '$title' trong thư viện!");
}
}
Gợi ý: class VipUser extends class User để reuse code càng nhiều càng tốt, chỉ nên sai khác nhau số 3 và số 10 (số lượng sách được mượn).
Bài tập 2, thiết kế hệ thống Log
Câu hỏi: Điền code còn thiếu vào chương trình ghi log, yêu cầu như sau:
- Tất cả class viết ra phải extends Abstract class Logger quy định sẵn
- Code các lớp viết ra không được trùng nhau
- Không cho phép Class con thay đổi flow (ghi đè code class Cha)
- Chỉ cho phép có method write() và create() cho trước, có thể bổ sung hàm __construct nếu cần
<?php
abstract class Logger
{
abstract public function write(): void;
}
class FileLogger extends Logger
{
public function write(): void
{
echo "Đây là log vào file";
}
}
class SlackLogger extends Logger
{
public function write(): void
{
// viết code ở đây
}
public static function create(): SlackLogger
{
// viết code ở đây
}
}
$slackLogger = SlackLogger::create();
$slackLogger->write(); // in ra màn hình Đây là log vào file và Đây là log vào slack.
Gợi ý: sử dụng OOP Design Pattern tên là Decorator Pattern.
Bài tập 3, Chương trình tính phí mua hàng
Câu hỏi: Giả định mỗi món hàng ở Mỹ được ship về Việt Nam sẽ bao gồm phí như sau:
- Phí cân nặng: $11/ kg
- Phí kích cỡ: $11/m3
Phí ship = max(phí cân nặng, phí kích cỡ)
Biết rằng mỗi món hàng có 4 thuộc tính: dài (m), cao (m), rộng (m), nặng (kg)
Viết chương trình tính phí dựa trên code bên dưới.
Yêu cầu: sau này bổ sung thêm thuộc tính productType và phí loại product thì không được sửa các hàm tính phí đang có, cho phép viết thêm code mới, nhưng không được sửa các hàm tính phí khác.
<?php
class Item
{
public float $length;
public float $width;
public float $height;
public float $weight;
public static function create(
float $length, float $width, float $height, float $weight
) {
$item = new Item();
$item->length = $length;
$item->width = $width;
$item->height = $height;
$item->weight = $weight;
return $item;
}
}
class ShippingFeeCalculator
{
public function getWeightFeeRate(): int
{
return 11;
}
public function volumeFeeRate(): int
{
return 11;
}
public function calculate(Item $item): float
{
// viết code ở đây
}
}
//có thể bổ sung các class khác
Gợi ý: sử dụng OOP Design Pattern Strategy, sau này thêm ProductType thì bổ sung thêm class ProductTypeFee vào vòng loop tìm max là xong.