0
0
Lập trình
Thaycacac
Thaycacac thaycacac

Thiết Kế Mẫu với Flutter: Tập 6 - Mẫu Chiến Lược (Strategy) Tối Ưu Hóa Tính Linh Hoạt

Đăng vào 3 tuần trước

• 5 phút đọc

Giới thiệu Mẫu thiết kế Strategy trong lập trình là một công cụ mạnh mẽ giúp chúng ta quản lý và thay đổi các thuật toán một cách linh hoạt trong quá trình thực thi. Nếu bạn muốn tránh việc kiểm soát luồng chương trình bằng các câu lệnh điều kiện kiểu if-else hoặc switch-case phức tạp, hoặc muốn tuân thủ nguyên lý SOLID trong thiết kế phần mềm, thì Strategy chính là giải pháp cho bạn. ### Mẫu Chiến Lược (Strategy) Là Gì? Mẫu thiết kế Strategy thuộc nhóm mẫu thiết kế hành vi (behavioural patterns), cho phép chúng ta định nghĩa một loạt các thuật toán và dễ dàng hoán đổi giữa chúng mà không cần thay đổi mã nguồn của lớp sử dụng. Mẫu này giúp giảm thiểu độ phức tạp của mã nguồn và tăng tính bảo trì và mở rộng cho hệ thống. ### Tại Sao Nên Sử Dụng Mẫu Chiến Lược? Mẫu chiến lược tồn tại với ba mục tiêu chính: 1. Xác định tập hợp các đối tượng tương ứng với các thuật toán cần thực hiện, thường là các đối tượng phức tạp. 2. Cho phép thay đổi linh hoạt các thuật toán mà không cần thay đổi mã nguồn của lớp sử dụng. 3. Tuân thủ các nguyên tắc SOLID: * S: Tách biệt thuật toán để mỗi lớp chỉ đảm nhận một trách nhiệm duy nhất. * O: Dễ dàng thêm thuật toán mới mà không cần sửa mã nguồn hiện có. * L: Các thuật toán có thể dễ dàng hoán đổi mà không làm thay đổi tính đúng đắn của chương trình. ### Sơ Đồ Lớp Model Mẫu thiết kế Strategy thường được mô tả qua sơ đồ lớp với ba thành phần chính: * Strategy: Giao diện hoặc lớp trừu tượng đại diện cho một lớp thuật toán, định nghĩa các phương thức chung cho các thuật toán. * ConcreteStrategies: Những lớp cụ thể kế thừa Strategy, đại diện cho các thuật toán cụ thể mà lớp Context sử dụng. * Context: Lớp tham chiếu đến giao diện Strategy và thực hiện các thuật toán thông qua các ConcreteStrategies. ### Ứng Dụng Của Mẫu Chiến Lược Mẫu thiết kế Strategy rất hữu ích khi bạn muốn đóng gói các thuật toán và có khả năng hoán đổi chúng mà không cần chỉnh sửa lại mã nguồn cũ. Nếu bạn nhận thấy rằng có nhiều hành vi khác nhau trong một lớp mà sử dụng các cấu trúc điều kiện thì đó chính là dấu hiệu cho thấy bạn nên xem xét việc áp dụng mẫu thiết kế Strategy để tách biệt các logic xử lý vào trong các lớp thuật toán riêng biệt. ### Thực Hành Tạo Hiệu Ứng Chuyển Trang Với Mẫu Chiến Lược Giả sử bạn có nhiều màn hình khác nhau trong ứng dụng của mình và bạn muốn có một hiệu ứng chuyển trang. Nếu một ngày khách hàng yêu cầu có những hiệu ứng khác nhau cho từng màn hình, bạn cần phải có giải pháp linh hoạt để đáp ứng yêu cầu đó. Ví dụ cụ thể, bạn có thể tạo ra hai hiệu ứng chuyển trang: FadeTransitionSlideTransition và áp dụng mẫu chiến lược để thực hiện điều này. Bước đầu tiên, chúng ta sẽ tạo một giao diện chiến lược có tên là PageTransitionStrategy, với phương thức routeTransitionsBuilder() để các lớp cụ thể có thể kế thừa và thực hiện logic riêng của chúng. abstract class PageTransitionStrategy { RouteTransitionsBuilder routeTransitionsBuilder(); } Sau đó, định nghĩa RouteTransitionsBuilder như sau: typedef RouteTransitionsBuilder = Widget Function(BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation, Widget child); Tiếp theo, triển khai các lớp cụ thể cho từng chiến lược hiệu ứng chuyển trang. Dưới đây là ví dụ cho lớp FadeTransitionStrategy: class FadeTransitionStrategy implements PageTransitionStrategy { @override RouteTransitionsBuilder routeTransitionsBuilder() { return (context, animation, secondaryAnimation, child) { return FadeTransition( opacity: animation, child: child, ); }; } } Và lớp SlideTransitionStrategy: class SlideTransitionStrategy implements PageTransitionStrategy { @override RouteTransitionsBuilder routeTransitionsBuilder() { return (context, animation, secondaryAnimation, child) { return SlideTransition( position: Tween<Offset>( begin: const Offset(1.0, 0.0), end: Offset.zero, ).animate(animation), child: child, ); }; } } Ngoài việc định nghĩa chiến lược, chúng ta cũng cần một lớp context để sử dụng chiến lược: class RouteTypeContext { final PageTransitionStrategy transitionStrategy; RouteTypeContext({ required this.transitionStrategy, }); RouteType routeType() { return RouteType.custom( transitionsBuilder: ((context, animation, secondaryAnimation, child) => transitionStrategy.routeTransitionsBuilder()( context, animation, secondaryAnimation, child, )), ); } } Khai báo các hiệu ứng chuyển trang cho từng context: final fadeTransition = RouteTypeContext(transitionStrategy: FadeTransitionStrategy()); final slideTransition = RouteTypeContext(transitionStrategy: SlideTransitionStrategy()); Cuối cùng, sử dụng các context này trong cấu hình AutoRoute: AutoRoute( page: StrategyRoute.page, children: [ AutoRoute( type: fadeTransition.routeType(), page: FadeTransitionStrategyRoute.page, initial: true, ), AutoRoute( type: slideTransition.routeType(), page: SlideTransitionStrategyRoute.page, ), ], ), Phần hiển thị cho phép người dùng chọn các hiệu ứng chuyển trang: class StrategyPage extends StatelessWidget { const StrategyPage({super.key}); @override Widget build(BuildContext context) { return Scaffold( appBar: const PrimaryAppBar( title: 'Strategy', ), body: SafeArea( child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ ElevatedButton( onPressed: () { context.router.push(const FadeTransitionStrategyRoute()); }, child: const Text('Fade Transition'), ), const SizedBox(height: 30), ElevatedButton( onPressed: () { context.router.push(const SlideTransitionStrategyRoute()); }, child: const Text('Slide Transition'), ), const SizedBox( height: 300, child: AutoRouter(), ), ], ), ), ); } } ### Kết Luận Với mẫu thiết kế Strategy, chúng ta đã tạo ra hai hiệu ứng chuyển trang khác nhau mà không làm ảnh hưởng đến mã nguồn hiện hữu. Việc thêm hiệu ứng trong tương lai sẽ trở nên dễ dàng hơn mà không làm rối phức tạp mã nguồn cũ. Sử dụng thư viện auto_route sẽ giúp việc điều hướng trở nên dễ dàng hơn. Bạn có thể xem mã nguồn trên GitHub để tham khảo thêm. ### Tổng Kết Như vậy, chúng ta đã cùng nhau tìm hiểu về mẫu thiết kế Strategy trong lập trình Flutter. Từ bài học này, hy vọng bạn sẽ cảm thấy thú vị hơn với các mẫu thiết kế và ứng dụng của chúng vào trong dự án của mình. Xin mời bạn đón chờ tập tiếp theo của series "Thiết Kế Mẫu với Flutter": Tập 7 - Mẫu State - "Siêu Nhân Biến Hình".

source: viblo

Nội dung bài viết

Gợi ý câu hỏi phỏng vấn
Không có dữ liệu

Không có dữ liệu

Bài viết được đề xuất
Bài viết cùng tác giả

Bình luận

Chưa có bình luận nào

Chưa có bình luận nào