Đây là bài viết thứ 2 của tôi thực hiện mô phỏng tính nhẩm một phép nhân. Bài viết trước là Mô phỏng phương pháp tính nhanh nhân 2 số có cùng hàng chục. Trước khi đi vào chạy mô phỏng phép tính nhân 2 số bé hơn và gần bằng 100 tôi muốn chia sẻ với các bạn về design pattern
được sử dụng trong mô phỏng của cả 2 bài viết.
Design pattern
ở được sử dụng là Strategy pattern
(Mô hình chiến lược).
Strategy pattern
Strategy pattern
định nghĩa một tập các thuật toán được đóng gói và tùy theo từng trường hợp được sử dụng mà client sẽ sử dụng thuật toán cần thiết
Các class và objects được định nghĩa trong pattern
Strategy: Định nghĩa phương thức mà các thuật toán cần phải có.
ConcreteStrategy: Kế thừa tới Strategy và viết lại phương thức cho thuật toán
Context: Tham chiếu tới Strategy và gọi phương thức của Strategy
Tôi thì hay quen gọi pattern
này là Hero Pattern vì tôi liên tưởng tới một siêu anh hùng lúc thì cầm búa, lúc cầm chùy, lúc cầm giáo, súng mà đánh tới tấp vào quái vật. Kiểu như này
public abstract class Weapon { public abstract int GetDamage(); } public class Gun : Weapon { public override int GetDamage() { return 10000; } } public class Sword : Weapon { public override int GetDamage() { return 200; } } public class Hero { public Weapon Weapon { private set; get; } public void UseWeapon<TWeapon>() where TWeapon: Weapon, new() { Weapon = new TWeapon(); } public void Attack() { Weapon.GetDamage(); } } var son20Hero = new Hero(); // Cầm kiếm mà đánh son20Hero.UseWeapon<Sword>(); son20Hero.Attack(); // Cầm súng mà bắn son20Hero.UseWeapon<Gun>(); son20Hero.Attack();
Vậy cái Hero Pattern này áp dụng để viết 2 mô phỏng phép nhân như thế nào . Nhưng chạy demo trước đã, vì chủ đề bài viết này là mô phỏng phép tính nhân 2 số bé hơn và gần bằng 100 cơ mà
Tạo ngẫu nhiên 2 số bé hơn và gần bằng 100
Các bạn có thể xem lại Mô phỏng phương pháp tính nhanh nhân 2 số có cùng hàng chục.
Như các bạn thấy, 2 mô phỏng là giống nhau, có cái khác nhau ở đây là phương pháp, thuật toán nhân 2 số khác nhau. Vì thế trong trường hợp này sử dụng Hero pattern là hoàn toàn hợp lý.
Cụ thể các class
như sau:
function MathX() { // Định nghĩa phương thức tạo 2 số cần thực hiện nhân this.onCreateNumber = function () { }; // Định nghĩa phương thức tạo kịch bản của phép nhân this.onCreateScripts = function (scripts) { }; // ...... }
Đây chính là Strategy. các bạn có thể xem cụ thể MathX.js tại đây
function PageMathX() { this.mathX; // Tham chiếu tới Strategy MathX this.start = function() { // sẽ thực hiện gọi phương thức onCreateNumber để tạo 2 số cần nhân // sẽ thực hiện gọi phương thức onCreateScripts để lấy kịch bản nhân } }
Đây chính là Context. Cũng được khai báo trong file MathX.js. Tại PageMathX
tôi đã bao gồm khai báo toàn bộ sự kiện trên giao diện như sự kiện bấm tạo số, bấm thực hiện phép tính và trượt chọn tốc độ
Đã xong, cuối cùng chúng ta chỉ việc viết thuật toán của phép nhân, khởi tạo ConcreteStrategy và gán vào this.mathX
.
var ABxCD = function () { $.extend(this, new MathX()); this.onCreateNumber = function () { this.number1 = Core.random(100); while (this.number1 < 80) this.number1 = Core.random(100); this.number2 = Core.random(100); while (this.number2 < 80) this.number2 = Core.random(100); n1 = 100 - this.number1; lengthN1 = (n1 + "").length - 1; n2 = 100 - this.number2; lengthN2 = (n2 + "").length - 1; number1_n2 = this.number1 - n2; lengthNumber1_n2 = (number1_n2 + "").length; n1xn2 = n1 * n2; lengthN1xN2 = (n1xn2 + "").length; if (n1xn2 >= 100) { f_n1xn2 = parseInt((n1xn2 + "").charAt(0)); length_f_n1xn2 = (f_n1xn2 + "").length; number1_n2_plus_f = number1_n2 + f_n1xn2; length_number1_n2_plus_f = (number1_n2_plus_f + "").length; n1xn2_b = n1xn2 - f_n1xn2 * 100; } } this.onCreateScripts = function (scripts) { scripts.push(this.createScript0()); scripts.push(this.createScript01()); scripts.push(this.createScript1()); scripts.push(this.createScript2()); scripts.push(this.createScript3()); scripts.push(this.createScript31()); scripts.push(this.createScript4()); scripts.push(this.createScript5()); scripts.push(this.createScript6()); scripts.push(this.createScript61()); scripts.push(this.createScript7()); scripts.push(this.createScript8()); scripts.push(this.createScript9()); scripts.push(this.createScript10()); scripts.push(this.createScript101()); scripts.push(this.createScript11()); scripts.push(this.createScript12()); if (n1xn2 >= 100) { scripts.push(this.createScript14()); scripts.push(this.createScript141()); scripts.push(this.createScript15()); scripts.push(this.createScript16()); scripts.push(this.createScript17()); scripts.push(this.createScript18()); return; } scripts.push(this.createScript13()); } }
ABxCD
ở đây chính là một ConcreteStrategy. Các bạn có thể xem chi tiết tại đây
Và cuối cùng thực hiện khởi tạo Context PageMathX
và gán một khởi tạo ABxCD
cho thuộc tính this.mathX
var pageMathX = new PageMathX(); pageMathX.mathX = new ABxCD(); pageMathX.start();
Như vậy với việc sử dụng Strategy (Hero) pattern. Tôi có thể xây dựng một loạt các mô phỏng phép nhân trong thời gian tới. Mà tôi chỉ việc xử lý về thuật toán, các bước mô phỏng mà ko cần quan tâm tới giao diện nữa (Giao diện lúc này đã có đủ chức năng bấm tạo số, bấm thực hiện phép tính, thanh trượt chọn tốc độ).
Nếu biết sử dụng design pattern các bạn sẽ là một coder thực chiến thực thụ
Sơn 20