GP Coder

Trang chia sẻ kiến thức lập trình Java

  • Java Core
    • Basic Java
    • OOP
    • Exception Handling
    • Multi-Thread
    • Java I/O
    • Networking
    • Reflection
    • Collection
    • Java 8
  • Design pattern
    • Creational Pattern
    • Structuaral Pattern
    • Behavior Pattern
  • Web Service
    • SOAP
    • REST
  • JPA
  • Java library
    • Report
    • Json
    • Unit Test
  • Message Queue
    • ActiveMQ
    • RabbitMQ
  • All
Trang chủ Design pattern Behavior Pattern Hướng dẫn Java Design Pattern – Interpreter

Hướng dẫn Java Design Pattern – Interpreter

Đăng vào 10/12/2018 . Được đăng bởi GP Coder . 16129 Lượt xem . Toàn màn hình

Nội dung

  • 1 Interpreter Pattern là gì?
  • 2 Cài đặt Interpreter Pattern như thế nào?
  • 3 Lợi ích của Interpreter Pattern là gì?
  • 4 Sử dụng Interpreter Pattern khi nào?

Interpreter Pattern là gì?

Given a language, define a representation for its grammar along with an interpreter that uses the representation to interpret sentences in the language.

Interpreter Pattern là một trong những Pattern thuộc nhóm hành vi (Behavior Pattern).

Interpreter nghĩa là thông dịch, mẫu này nói rằng “để xác định một biểu diễn ngữ pháp của một ngôn ngữ cụ thể, cùng với một thông dịch viên sử dụng biểu diễn này để diễn dịch các câu trong ngôn ngữ”.

Nói cho dễ hiểu, 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ả đó.

Metadata (mô tả) –> [Interpreter Pattern] –> Đối tượng tương ứng.

Interpreter Pattern có hạn chế về phạm vi áp dụng. Mẫu này thường được sử dụng để định nghĩa bộ ngữ pháp đơn giản (grammar), trong các công cụ quy tắc đơn giản (rule), …

Cài đặt Interpreter Pattern như thế nào?

Các thành phần tham gia mẫu Interpreter:

  • Context : là phần chứa thông tin biểu diễn mẫu chúng ta cần xây dựng.
  • Expression : là một interface hoặc abstract class, định nghĩa phương thức interpreter chung cho tất cả các node trong cấu trúc cây phân tích ngữ pháp. Expression được biểu diễn như một cấu trúc cây phân cấp, mỗi implement của Expression có thể gọi một node.
  • TerminalExpression (biểu thức đầu cuối): cài đặt các phương thức của Expression, là những biểu thức có thể được diễn giải trong một đối tượng duy nhất, chứa các xử lý logic để đưa thông tin của context thành đối tượng cụ thể.
  • NonTerminalExpression (biểu thức không đầu cuối): cài đặt các phương thức của Expression, biểu thức này chứa một hoặc nhiều biểu thức khác nhau, mỗi biểu thức có thể là biểu thức đầu cuối hoặc không phải là biểu thức đầu cuối. Khi một phương thức interpret() của lớp biểu thức không phải là đầu cuối được gọi, nó sẽ gọi đệ quy đến tất cả các biểu thức khác mà nó đang giữ.
  • Client : đại diện cho người dùng sử dụng lớp Interpreter Pattern. Client sẽ xây dựng cây biểu thức đại diện cho các lệnh được thực thi, gọi phương thức interpreter() của node trên cùng trong cây, có thể truyền context để thực thi tất cả các lệnh trong cây.

Ví dụ Interpreter Pattern trong ứng dụng calculator theo ngôn ngữ tự nhiên

Trong ví dụ bên dưới chúng ta sẽ xây dựng ứng dụng calculator theo ngôn ngữ tự nhiên. Ví dụ: 20 cộng 8 = 28 hay 10 trừ 4 = 6

Chương trình của chúng ta như sau:

InterpreterEngineContext.java


package com.gpcoder.patterns.behavioral.interpreter.math;

public class InterpreterEngineContext {

	public int add(String input) {
		String[] tokens = interpret(input);
		int num1 = Integer.parseInt(tokens[0]);
		int num2 = Integer.parseInt(tokens[1]);
		return (num1 + num2);
	}

	public int subtract(String input) {
		String[] tokens = interpret(input);
		int num1 = Integer.parseInt(tokens[0]);
		int num2 = Integer.parseInt(tokens[1]);
		return (num1 - num2);
	}

	private String[] interpret(String input) {
		String str = input.replaceAll("[^0-9]", " ");
		str = str.replaceAll("( )+", " ").trim();
		return str.split(" ");
	}
}

Expression.java


package com.gpcoder.patterns.behavioral.interpreter.math;

public interface Expression {
	int interpret(InterpreterEngineContext context);
}

AddExpression.java


package com.gpcoder.patterns.behavioral.interpreter.math;

public class AddExpression implements Expression {

	private String expression;

	public AddExpression(String expression) {
		this.expression = expression;
	}

	@Override
	public int interpret(InterpreterEngineContext context) {
		return context.add(expression);
	}
}

SubtractExpression.java


package com.gpcoder.patterns.behavioral.interpreter.math;

public class SubtractExpression implements Expression {

	private String expression;

	public SubtractExpression(String expression) {
		this.expression = expression;
	}

	@Override
	public int interpret(InterpreterEngineContext context) {
		return context.subtract(expression);
	}
}

Client.java


package com.gpcoder.patterns.behavioral.interpreter.math;

public class Client {

	public static void main(String args[]) {
		System.out.println("20 cộng 8 = " + interpret("20 cộng 8"));
		System.out.println("10 trừ 4 = " + interpret("10 trừ 4"));
	}

	private static int interpret(String input) {
		Expression exp = null;
		if (input.contains("cộng")) {
			exp = new AddExpression(input);
		} else if (input.contains("trừ")) {
			exp = new SubtractExpression(input);
		} else {
			throw new UnsupportedOperationException();
		}
		return exp.interpret(new InterpreterEngineContext());
	}
}

Output của chương trình:


20 cộng 8 = 28
10 trừ 4 = 6

Ví dụ sử dụng Interpreter để chuyển chữ cái La Mã sang số thập phân

Có bốn nguyên tắc cơ bản để đọc và viết chữ số La Mã:

  • Chữ số La Mã được thể hiện bằng chữ cái của bảng chữ cái: I=1;  V=5;  X=10;  L=50;  C=100;  D=500;  M=1000.
  • Một chữ cái có thể lặp lại giá trị của nó nhiều lần, tối đa ba lần. Ví dụ: XXX = 30, CC = 200,…
  • Nếu một hoặc nhiều chữ cái được đặt sau một chữ cái có giá trị lớn hơn, cộng số trước đó. Ví dụ:
    • VI = 6 (5 + 1 = 6)
    • LXX = 70 (50 + 10 + 10 = 70)
    • MCC = 1200 (1000 + 100 + 100 = 1200)
  • Nếu một chữ cái được đặt trước một chữ cái có giá trị lớn hơn, trừ đi số trước đó. Ví dụ:
    • IV = 4 (5 – 1 = 4)
    • XC = 90 (100 – 10 = 90)
    • CM = 900 (1000 – 100 = 900)

Chi tiết về chữ cái La Mã, các bạn xem thêm ở các link bên dưới:

  • https://en.wikipedia.org/wiki/Roman_numerals
  • https://www.factmonster.com/math/numbers/roman-numerals
  • https://www.artofmanliness.com/articles/even-when-not-in-romeyou-should-know-your-roman-numerals/

Chương trình của chúng ta như sau:

 

Context.java


package com.gpcoder.patterns.behavioral.interpreter.roman;

public class Context {
	private String input;
	private int output;

	public Context(String input) {
		this.input = input;
	}

	public void setInput(String input) {
		this.input = input;
	}

	public String getInput() {
		return input;
	}

	public int getOutput() {
		return output;
	}

	public void setOutput(int output) {
		this.output = output;
	}
}

Expression.java


package com.gpcoder.patterns.behavioral.interpreter.roman;

public abstract class Expression {

	public void interpret(Context context) {
		if (context.getInput().length() == 0) {
			return;
		}
		
		if (context.getInput().startsWith(nine())) {
			context.setOutput(context.getOutput() + 9 * multiplier());
			context.setInput(context.getInput().substring(2));
		} else if (context.getInput().startsWith(four())) {
			context.setOutput(context.getOutput() + 4 * multiplier());
			context.setInput(context.getInput().substring(2));
		} else if (context.getInput().startsWith(five())) {
			context.setOutput(context.getOutput() + 5 * multiplier());
			context.setInput(context.getInput().substring(1));
		}

		while (context.getInput().startsWith(one())) {
			context.setOutput(context.getOutput() + 1 * multiplier());
			context.setInput(context.getInput().substring(1));
		}
	}

	public abstract String one();

	public abstract String four();

	public abstract String five();

	public abstract String nine();

	public abstract int multiplier();
}

ThousandExpression.java


package com.gpcoder.patterns.behavioral.interpreter.roman;

public class ThousandExpression extends Expression {

	@Override
	public String one() {
		return "M";
	}

	@Override
	public String four() {
		return " ";
	}

	@Override
	public String five() {
		return " ";
	}

	@Override
	public String nine() {
		return " ";
	}

	@Override
	public int multiplier() {
		return 1000;
	}
}

HundredExpression.java


package com.gpcoder.patterns.behavioral.interpreter.roman;

public class HundredExpression extends Expression {

	@Override
	public String one() {
		return "C";
	}

	@Override
	public String four() {
		return "CD";
	}

	@Override
	public String five() {
		return "D";
	}

	@Override
	public String nine() {
		return "CM";
	}

	@Override
	public int multiplier() {
		return 100;
	}
}

TenExpression.java


package com.gpcoder.patterns.behavioral.interpreter.roman;

public class TenExpression extends Expression {

	@Override
	public String one() {
		return "X";
	}

	@Override
	public String four() {
		return "XL";
	}

	@Override
	public String five() {
		return "L";
	}

	@Override
	public String nine() {
		return "XC";
	}

	@Override
	public int multiplier() {
		return 10;
	}

}

OneExpression.java


package com.gpcoder.patterns.behavioral.interpreter.roman;

public class OneExpression extends Expression {

	@Override
	public String one() {
		return "I";
	}

	@Override
	public String four() {
		return "IV";
	}

	@Override
	public String five() {
		return "V";
	}

	@Override
	public String nine() {
		return "IX";
	}

	@Override
	public int multiplier() {
		return 1;
	}
}

Client.java


package com.gpcoder.patterns.behavioral.interpreter.roman;

import java.util.ArrayList;
import java.util.List;

public class Client {

	public static void main(String[] args) {
		String[] romans = { "IV", "XII", "CLIX", "MMXVIII", "MMMDLIV" };
		for (String roman : romans) {
			convertRomanToNumber(roman);
		}
	}

	private static void convertRomanToNumber(String roman) {
		List<Expression> tree = new ArrayList<>();
		tree.add(new ThousandExpression());
		tree.add(new HundredExpression());
		tree.add(new TenExpression());
		tree.add(new OneExpression());

		Context context = new Context(roman);
		for (Expression exp : tree) {
			exp.interpret(context);
		}
		System.out.println(roman + " = " + context.getOutput());
	}
}

Output của chương trình:


IV = 4
XII = 12
CLIX = 159
MMXVIII = 2018
MMMDLIV = 3554

Lợi ích của Interpreter Pattern là gì?

  • Dễ dàng thay đổi và mở rộng ngữ pháp. Vì mẫu này sử dụng các lớp để biểu diễn các quy tắc ngữ pháp, chúng ta có thể sử dụng thừa kế để thay đổi hoặc mở rộng ngữ pháp. Các biểu thức hiện tại có thể được sửa đổi theo từng bước và các biểu thức mới có thể được định nghĩa lại các thay đổi trên các biểu thức cũ.
  • Cài đặt và sử dụng ngữ pháp rất đơn giản. Các lớp xác định các nút trong cây cú pháp có các implement tương tự. Các lớp này dễ viết và các phân cấp con của chúng có thể được tự động hóa bằng trình biên dịch hoặc trình tạo trình phân tích cú pháp.

Sử dụng Interpreter Pattern khi nào?

Interpreter Pattern được sử dụng hiệu quả khi:

  • 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, …

Tài liệu tham khảo:

  • https://sourcemaking.com/design_patterns/interpreter
  • https://www.javatpoint.com/interpreter-pattern
  • https://www.tutorialspoint.com/design_pattern/interpreter_pattern.htm
  • https://www.journaldev.com/1635/interpreter-design-pattern-java
  • https://www.dineshonjava.com/interpreter-pattern-design-patterns-java/
  • https://www.javacodegeeks.com/2015/09/interpreter-design-pattern.html
  • https://www.opencodez.com/java/interpreter-design-pattern.htm
  • Design Patterns: Elements of Reusable Object-Oriented Software – GOF
5.0
11
Nếu bạn thấy hay thì hãy chia sẻ bài viết cho mọi người nhé! Và Donate tác giả

Shares

Chuyên mục: Behavior Pattern, Design pattern Được gắn thẻ: Behavior Pattern, Design pattern

Hướng dẫn Java Design Pattern – Command
Hướng dẫn Java Design Pattern – Iterator

Có thể bạn muốn xem:

  • Hướng dẫn Java Design Pattern – Memento (25/12/2018)
  • Hướng dẫn Java Design Pattern – Abstract Factory (15/09/2018)
  • Hướng dẫn Java Design Pattern – Composite (02/11/2018)
  • Hướng dẫn Java Design Pattern – State (31/12/2018)
  • Hướng dẫn Java Design Pattern – Singleton (08/09/2018)

Bình luận

bình luận

Tìm kiếm

Bài viết mới

  • Clean code 13/01/2024
  • Giới thiệu CloudAMQP – Một RabbitMQ server trên Cloud 02/10/2020
  • Kết nối RabbitMQ sử dụng Web STOMP Plugin 19/06/2020
  • Sử dụng publisher confirm trong RabbitMQ 16/06/2020
  • Sử dụng Dead Letter Exchange trong RabbitMQ 13/06/2020

Xem nhiều

  • Hướng dẫn Java Design Pattern – Factory Method (97289 lượt xem)
  • Hướng dẫn Java Design Pattern – Singleton (96926 lượt xem)
  • Giới thiệu Design Patterns (86558 lượt xem)
  • Lập trình đa luồng trong Java (Java Multi-threading) (85378 lượt xem)
  • Giới thiệu về Stream API trong Java 8 (82946 lượt xem)

Nội dung bài viết

  • 1 Interpreter Pattern là gì?
  • 2 Cài đặt Interpreter Pattern như thế nào?
  • 3 Lợi ích của Interpreter Pattern là gì?
  • 4 Sử dụng Interpreter Pattern khi nào?

Lưu trữ

Thẻ đánh dấu

Annotation Authentication Basic Java Behavior Pattern Collection Creational Design Pattern Cấu trúc điều khiển Database Dependency Injection Design pattern Eclipse Exception Executor Service Google Guice Gson Hibernate How to Interceptor IO Jackson Java 8 Java Core JDBC JDK Jersey JMS JPA json JUnit JWT Message Queue Mockito Multithreading OOP PowerMockito RabbitMQ Reflection Report REST SOAP Structuaral Pattern Swagger Thread Pool Unit Test Webservice

Liên kết

  • Clean Code
  • JavaTpoint
  • Refactoring Guru
  • Source Making
  • TutorialsPoint
  • W3Schools Online Web Tutorials

Giới thiệu

GP Coder là trang web cá nhân, được thành lập với mục đích lưu trữ, chia sẽ kiến thức đã học và làm việc của tôi. Các bài viết trên trang này chủ yếu về ngôn ngữ Java và các công nghệ có liên quan đến Java như: Spring, JSF, Web Services, Unit Test, Hibernate, SQL, ...
Hi vọng góp được chút ít công sức cho sự phát triển cộng đồng Coder Việt.

Donate tác giả

Tìm kiếm các bài viết của GP Coder với Google Search

Liên hệ

Các bạn có thể liên hệ với tôi thông qua:
  • Trang liên hệ
  • Linkedin: gpcoder
  • Email: contact@gpcoder.com
  • Skype: ptgiang56it

Follow me

Copyright 2025 © GP Coder · All Rights Reserved · Giới thiệu · Chính sách · Điều khoản · Liên hệ ·

Share

Blogger
Delicious
Digg
Email
Facebook
Facebook messenger
Flipboard
Google
Hacker News
Line
LinkedIn
Mastodon
Mix
Odnoklassniki
PDF
Pinterest
Pocket
Print
Reddit
Renren
Short link
SMS
Skype
Telegram
Tumblr
Twitter
VKontakte
wechat
Weibo
WhatsApp
X
Xing
Yahoo! Mail

Copy short link

Copy link