+9

Kiến trúc hệ thống trên Laravel – phần 7

Các bài viết trong series

Kiến trúc hệ thống trên Laravel – phần 1 : Tại sao phải áp dụng architect vào trong Laravel Kiến trúc hệ thống trên Laravel – phần 2 : OOP, Interface, Dependency Injection, IoC Kiến trúc hệ thống trên Laravel – phần 3 : Phân tích sâu vào việc sử dụng interface Kiến trúc hệ thống trên Laravel – phần 4 : Design Pattern – Decorator Kiến trúc hệ thống trên Laravel – phần 5 : Design Pattern – Adapter Kiến trúc hệ thống trên Laravel – phần 6 : Design Pattern – Repository Kiến trúc hệ thống trên Laravel – phần 7 : Design Pattern – Factory Kiến trúc hệ thống trên Laravel – phần 8 : Advance component trong Laravel Kiến trúc hệ thống trên Laravel – phần 9 : Mô hình kiến trúc cụ thể Part 1 Kiến trúc hệ thống trên Laravel – phần 10 : Mô hình kiến trúc cụ thể Part 2

Xin chào các bạn. Mình vào nghề lập trình cũng đã lâu, cũng có 1 số hiểu biết coi như là nâng cao về framework Laravel. Nên hôm nay mình xin chia sẻ 1 chút về kiến trúc hệ thống của mình được xây dựng trên Laravel như thế nào. Mong rằng có thể giúp ích cho các bạn 😃.


Hôm nay chúng ta đi vào factory nhé.

Thực ra với Factory Design Pattern chúng ta có 2 dạng (ít nhất là mình biết thế) nhưng mình sẽ diễn đạt cách mình nhìn nhận và sử dụng factory như thế nào nhé (không theo sách vở đâu >.<)

Factory là cái nhà máy sản xuất ra các object theo các điều kiện có sẵn ^^.

Đặc điểm để mình nghĩ đến factory là các điều kiện if-else / switch-case giống nhau được lặp lại ở nhiều chỗ 😃.

Đi vào ví dụ cái cho nó dễ hiểu nhá ^^.

Các hãng máy bay bây giờ đều có kiểu đánh level khách hàng thân thiết: hạng bạch kim, hàng vàng, hạng bạc, hạng đồng … -> với mỗi hạng thì chiết khấu vé khác nhau và tặng dặm bay khác nhau -> bài toán khá cơ bản nhở, thế chúng ta thường triển khai như thế nào?

Thường thường, chúng ta sẽ có 1 object $user để trỏ tới khách hàng và $user->type chỉ hạng khách hàng. If-else / hoặc switch-case để check điều kiện là xong:

<?php

class OrderController
{
    /**
     * Store price information when booking ticket
     */
    public function calculatePrice()
    {
        // Xử lý chính phần mình muốn nói ở đây, các phần khác bỏ qua nhá ...
        $type = $user->type;
        switch ($type) {
            case 'bach kim':
                $chiet_khau = 0.1;
                break;
            case 'vang':
                $chiet_khau = 0.07;
                break;
            case 'bac':
                $chiet_khau = 0.05;
                break;
            case 'dong':
                $chiet_khau = 0.03;
                break;
        }
        $price = $base_price - $base_price * $chiet_khau;
    }

    public function calculateBonus()
    {
        // Xử lý chính phần mình muốn nói ở đây, các phần khác bỏ qua nhá ...
        $type = $user->type;
        switch ($type) {
            case 'bach kim':
                $bonus = 1000;
                break;
            case 'vang':
                $bonus = 700;
                break;
            case 'bac':
                $bonus = 500;
                break;
            case 'dong':
                $bonus = 300;
                break;
        }
    }
}

Các bạn thấy đấy, 1 chuỗi điều kiện sẽ được lặp đi lặp lại ở rất nhiều chỗ dẫn đến việc follow logic của bài toán rất khó (ví dụ để kiếm tất cả benefit mà ông bạch kim nhận được thì phải tra rất nhiều controller khác nhau) -> nếu gom nhóm được những xử lý theo từng hạng thì việc quản lý logic, chỉnh sửa hệ thống về sau sẽ dễ dàng hơn rất nhiều rồi.

Làm như thế nào

1. Tập trung xử lý phần điều kiện trong if-else vào các object riêng biệt

Class BachKim
{
    public function discount()
    {
        return 0.1;
    }
    public function bonus()
    {
        return 1000;
    }
}

Class Vang
{
    public function discount()
    {
        return 0.07;
    }
    public function bonus()
    {
        return 700;
    }
}

Class Bac
{
    public function discount()
    {
        return 0.05;
    }
    public function bonus()
    {
        return 500;
    }
}

Class Dong
{
    public function discount()
    {
        return 0.03;
    }
    public function bonus()
    {
        return 300;
    }
}

2. Sinh object theo điều kiện đầu vào

class UserFactory
{
    public static function make($type)
    {
        switch ($type) {
            case 'bach kim':
                return new BachKim;
                break;
            case 'vang':
                return new Vang;
                break;
            case 'bac':
                return new Bac;
                break;
            case 'dong':
                return new Dong;
                break;
        }
    }
}

3. Sử dụng trong client

class OrderController
{
    /**
     * Store price information when booking ticket
     */
    public function calculatePrice()
    {
        // Xử lý chính phần mình muốn nói ở đây, các phần khác bỏ qua nhá ...
        $type = $user->type;
        $customer = UserFactory::make($type);
        $base_price = $customer->discount();
        $price = $base_price - $base_price * $chiet_khau;
    }

    public function calculateBonus()
    {
        // Xử lý chính phần mình muốn nói ở đây, các phần khác bỏ qua nhá ...
        $type = $user->type;
        $customer = UserFactory::make($type);
        $bonus = $customer->bonus();
    }
}

Vâng, rất nhiều class mới được sinh ra để xử lý 1 vấn đề khá là đơn giản (và thường gặp nữa), nhưng bù lại thì logic của các phần đã được tập trung lại, việc xem xét, chỉnh sửa logic của bài toán bây giờ đơn giản hơn rất nhiều.

Xin cám ơn các bạn đã kiên nhẫn follow mình trong series này 😃.


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí