- vừa được xem lúc

Interpreter Design Pattern - Trợ thủ đắc lực của Developers

0 0 32

Người đăng: Hoàng Đinh

Theo Viblo Asia

1. Giới thiệu

  • Interpreter là một mẫu thiết kế thuộc nhóm hành vi (Behavioral Pattern).
  • Interpreter Pattern giúp người lập trình có thể “xây dựng” những đối tượng “động” bằng cách đọc mô tả về đối tượng rồi sau đó “xây dựng” đối tượng đúng theo mô tả đó.
  • Ví dụ, viết một chương trình cho phép người dùng nhập vào dòng lệnh (command) theo một cấu trúc xác định do ta quy định sẵn, chương trình sẽ nhận dạng Command dựa vào cấu trúc của nó và trả về kết quả phù hợp

2. Kiến trúc

Các thành phần trong mô hình:

  • AbstractionExpression: Khai báo một giao diện cho việc thực hiện một thao tác.
  • TerminalExpression: Cài đặt một thao tác thông dịch liên kết với những ký pháp đầu cuối, đóng vai trò một thể nghiệm được yêu cầu cho mọi ký pháp đầu cuối trong câu.
  • NonterminalExpression: Có thể chứa TerminalExpression bên trong và cũng có thể chứa một NonterminalExpression khác. Nó đóng vai trò như là “ngữ pháp” của ngôn ngữ đặc tả.
  • Context: Là đối tượng thông tin để thực hiện thông dịch. Đối tượng này là toàn cục đối với quá trình thông dịch (dùng chung giữa các node).

3. Ưu & nhược điểm

Ưu điểm

  • Giảm sự phục thuộc giữa abstraction và implementation (loose coupling).
  • Giảm số lượng những lớp con không cần thiết.
  • Code sẽ gọn gàn hơn và kích thước ứng dụng sẽ nhỏ hơn.
  • Dễ bảo trì hơn.
  • Dễ dàng mở rộng về sau.
  • Cho phép ẩn các chi tiết implement từ client.

Nhược điểm

  • Ngôn ngữ đặc tả được xây dựng đòi hỏi phải có cấu trúc ngữ pháp đơn giản.
  • Hiệu suất không đảm bảo

4. Khi nào thì sử dụng

Sử dụng Interpreter Patern khi chúng ta muốn:

  • Bộ ngữ pháp đơn giản. Pattern này cần xác định ít nhất một lớp cho mỗi quy tắc trong ngữ pháp. Do đó ngữ pháp có chứa nhiều quy tắc có thể khó quản lý và bảo trì.
  • Không quan tâm nhiều về hiệu suất. Do bộ ngữ pháp được phân tích trong cấu trúc phân cấp (cây) nên hiệu suất không được đảm bảo.
  • Interpreter Pattern thường được sử dụng trong trình biên dịch (compiler), định nghĩa các bộ ngữ pháp, rule, trình phân tích SQL, XML, …

5. Source code minh họa với C#

Bài toán: thực hiện chương trình để diễn giải thương hiệu, loại và số kiểu máy bay từ tên kiểu dịch vụ của nó.

Step 1: Tạo Context

class Context { private string ac_model = ""; private bool isAircraft = false; public Context(string _ac_model) { this.ac_model = _ac_model; } public string getModel() { return this.ac_model; } public int getLenght() { return this.ac_model.Length; } public string getLastChar() { return this.ac_model[this.ac_model.Length - 1].ToString(); } public string getFirstChar() { return this.ac_model[0].ToString(); } public void setIsAircraft(bool _isAircraft) { this.isAircraft = _isAircraft; } public bool getIsAircraft() { return this.isAircraft; } } 

Step 2: Tạo AbstractionExpression

interface Expression { void InterpretContext(Context context); }

Step 3: Tạo NonterminalExpression

 class CheckExpression : Expression { public void InterpretContext(Context context) { //We assume tthe aircraft models only start with A or B and contains 4 or 5 chars. string ac_model = context.getModel(); if (ac_model.StartsWith("A") || ac_model.StartsWith("B")) { if (ac_model.Length == 4 || ac_model.Length == 5) { context.setIsAircraft(true); Console.WriteLine(ac_model + " is an aircraft..."); } else { context.setIsAircraft(false); Console.WriteLine(ac_model + " is not aircraft..."); } } else { context.setIsAircraft(false); Console.WriteLine(ac_model + " is not aircraft..."); } } }

Step 4: Tạo TerminalExpression

 class BrandExpression : Expression { public void InterpretContext(Context context) { if (context.getIsAircraft() == true) { if (context.getFirstChar().Equals("A")) Console.WriteLine("Brand is Airbus"); else if (context.getFirstChar().Equals("B")) Console.WriteLine("Brand is Boeing"); } else Console.WriteLine("Brand could not be interpreted"); } } class ModelExpression : Expression { public void InterpretContext(Context context) { if (context.getIsAircraft() == true) { Console.WriteLine("Model is : " + context.getModel().Substring(1, 3)); } else Console.WriteLine("Model could not be interpreted"); } } class TypeExpression : Expression { public void InterpretContext(Context context) { if (context.getIsAircraft() == true) { string ac_model = context.getModel(); if (context.getLenght() == 5 && context.getLastChar().Equals("F"))//F-> Freighter { Console.WriteLine("Aircraft type is Cargo/Freighter"); } else Console.WriteLine("Aircraft type is Passenger Transportation"); } else Console.WriteLine("Type could not be interpreted"); } }

Step 5: Tạo Client

 class Program { static void Main(string[] args) { Console.Title = "Interpreter Design Pattern Example - TheCodeprogram"; List<Context> lstAircrafts = new List<Context>(); List<Expression> lstExpressions = new List<Expression>(); lstAircrafts.Add(new Context("A330")); lstAircrafts.Add(new Context("A330F")); lstAircrafts.Add(new Context("B777")); lstAircrafts.Add(new Context("B777F")); lstAircrafts.Add(new Context("TheCode")); lstExpressions.Add(new CheckExpression()); lstExpressions.Add(new BrandExpression()); lstExpressions.Add(new ModelExpression()); lstExpressions.Add(new TypeExpression()); for (int ac_index = 0; ac_index < lstAircrafts.Count; ac_index++) { for (int exp_index = 0; exp_index < lstExpressions.Count; exp_index++) { lstExpressions[exp_index].InterpretContext(lstAircrafts[ac_index]); } Console.WriteLine("-----------------------------------"); } Console.ReadLine(); } }

6. Design Pattern liên quan

  • Cây cú pháp trừu tượng là một thể nghiệm trong mẫu Composite.
  • Interpreter thường sử dụng một Iterator để duyệt cấu trúc.
  • Visitor có thể được sử dụng để duy trì hành vi trên mỗi nút trong cây cú pháp trừu tượng của lớp.

Bài viết của mình đến đây là kết thúc, cảm ơn các bạn đã theo dõi. Nếu các bạn thấy có ích có thể khám phá thêm Series Design Patterns - Trợ thủ đắc lực của Developers của mình!!

Tài liệu tham khảo

[1] Refactoring.Guru. https://refactoring.guru/design-patterns

[2] Design Patterns for Dummies, Steve Holzner, PhD

[3] Head First, Eric Freeman

[4] Gang of Four Design Patterns 4.0

[5] Dive into Design Pattern

Bình luận

Bài viết tương tự

- vừa được xem lúc

Tổng hợp các bài hướng dẫn về Design Pattern - 23 mẫu cơ bản của GoF

Link bài viết gốc: https://gpcoder.com/4164-gioi-thieu-design-patterns/. Design Patterns là gì. Design Patterns không phải là ngôn ngữ cụ thể nào cả.

0 0 277

- vừa được xem lúc

Giới thiệu về Builder Design Pattern

Nguồn: refactoring.guru. Builder. Ý đồ.

0 0 34

- vừa được xem lúc

Một ví dụ nhỏ về Factory method

Trong bài viết trước mình đã giới thiệu tới các bạn về Abstract Factory pattern, các bạn quan tâm có thể theo dõi lại tại đây. Để tiếp tục về chủ đề design pattern trong bài viết này mình sẽ trình bày những khái niệm, ưu nhược điểm và các sử dụng của một creational design pattern khác đó là Factory

0 0 27

- vừa được xem lúc

Tôi đã dùng Service Pattern trong NuxtJS như thế nào ?

Giới thiệu. Trong quá trình làm VueJS NuxtJS hay thậm chí là Laravel mình cũng hay áp dụng các pattern như Service hoặc Repository.

0 0 58

- vừa được xem lúc

Hướng dẫn Adapter Design Pattern

Trong bài viết này, chúng ta sẽ cùng tìm hiểu về Adapter Design Pattern qua cấu trúc, cánh triển khai, ví dụ, ưu điểm nhược điểm và ứng dụng của nó. Đây là bài viết đầu tiên của mình nên sẽ không trán

1 1 53

- vừa được xem lúc

Giới thiệu về Prototype Design Pattern

Ý đồ. Prototype là một creational design pattern cho phép bạn sao chép các object hiện có mà không làm cho code của bạn phụ thuộc vào các class của chúng.

0 0 44