Bài tập thực hành môn Các mẫu thiết kế hướng đối tượng - Bài thực hành số 6.1: Xây dựng và kiểm thử hệ thống quản lý biểu thức

Trang 1  
MÔN : CÁC MẪU THIẾT KẾ HỚNG ỐI TỢNG  
Bài thực hành số .1 : Xây dựng và kiểm thử hệ thống qun lý biểu thức  
I. Mục tiêu :  
. Giúp SV làm quen với cách thức qun lý biểu thức i số. Giúp SV biết cách  
sử dụng các mẫu thiết kế Singleton, Apdater, Composite, Abstract Factory  
trong từng yêu cầu cụ thể.  
II. Nội dung :  
Xây dựng module qun lý biểu thức i số nh sau :  
1. biểu thức ợc xây dựng trên 4 phép toán hai ngôi +, -, *, /. Các biểu thức c  
bn có thể là hằng thực hay biến thực.  
2. mỗi biểu thức có 2 dịch vụ thiết yếu :  
-
-
tối gin mình.  
tính trị của mình.  
III. Chuẩn ầu ra :  
. Nắm vững tính chất, công dụng của các mẫu thiết kế Singleton, Adapter,  
Composite, Abstract Factory ể có thể dùng li các mẫu này trong bất kỳ vị  
trí nào của chng trình mới cần xây dựng.  
IV. Qui trình xây dựng chng trình  
1. Chy VS .Net, chọn menu File.New.Project ể hiển thị cửa sổ New Project.  
2. Mở rộng mục Visual C# trong TreeView "Project Types", chọn mục Window,  
chọn icon "Windows Form Application" trong listbox "Templates" bên phi,  
thiết lập th mục chứa Project trong listbox "Location", nhập tên Project vào  
textbox "Name:" (td. BaiTH ), click button OK ể to Project theo các thông  
số ã khai báo.  
3. Form ầu tiên của ứng dụng ã hiển thị trong cửa sổ thiết kế, việc thiết kế  
form là quá trình lặp 4 thao tác to mới/xóa/hiệu chỉnh thuộc tính/to hàm  
xử lý sự kiện cho từng ối tợng cần dùng trong form. Ta s thiết kế form ứng  
dụng sau. Bây giờ ta xây dựng hệ thống con chứa các thành phần miêu t biểu  
thức và to biểu thức.  
4. Dời chuột về gốc cây Project trong cửa sổ "Solution xplorer", ấn phi chuột  
trên phần tử gốc này, chọn option Add.New Folder, ặt tên cho folder mới là  
xpression.  
.
ể việc lấy số ngẫu nhiên của nhiều phần tử trong phần mềm ợc nhất quán,  
ta s to 1 ối tợng duy nhất chuyên phục vụ to số ngẫu nhiên. ể bo m  
phần tử to số ngẫu nhiên là duy nhất, ta dùng mẫu thiết kế Singleton. Hãy  
hiện thực ối tợng này có các dịch vụ sau :  
- to số nguyên ngẫu nhiên bất kỳ.  
- to số nguyên ngẫu nhiên nằm trong khong từ 0 tới n.  
- to số thực ngẫu nhiên nằm trong khong từ 0 tới 1.  
Trang 2  
Dời chuột về th mục xpression trong cửa sổ “Solution xplorer”, ấn phi  
chuột vào nó ể hiển thị menu lệnh, chọn chức nng Add.Class ể hiển thị  
cửa sổ “Add New Item”, chọn mục “Class”, hiệu chỉnh tên class là  
MyRandom.cs, chọn button Add ể máy to 1 class mới. Viết code cho class  
này nh sau :  
class MyRandom {  
//hàm khởi to private ể cấm bên ngoài to ối tợng MyRandom  
private MyRandom() { }  
//thông tin dùng chung trong class  
private static MyRandom myrnd = new MyRandom();  
public static MyRandom getInstance() { return myrnd; }  
//thông tin trong ối tợng  
private Random rnd = new Random();  
public int RndInt() { return rnd.Next(); }  
public int RndInt(int n) { return rnd.Next(n); }  
public double RndDouble() { return rnd.NextDouble(); }  
}
Lu ý rằng ta ã dùng mẫu Adapter ể xây dựng class MyRandom dựa trên  
class Random của .N T. Class MyRandom ở bài này cũng giống y nh class  
MyRandom ã ợc viết trong th viện GenLib ở bài thực hành .1.  
.
.
ể qun lý biểu thức, ta dùng mẫu thiết kế Composite ể ịnh nghĩa các  
thành phần cấu thành biểu thức bất kỳ theo lợc ồ class nh sau :  
Trớc hết, ịnh nghĩa interface chung cho các biểu thức : hằng, biến, biểu  
thức 2 ngôi có các dịch vụ sau :  
- tham kho biểu thức con bên trái.  
- tham kho biểu thức con bên phi.  
- tính trị biểu thức.  
- tối gin biểu thức.  
Dời chuột về th mục xpression trong cửa sổ “Solution xplorer”, ấn phi  
chuột vào nó ể hiển thị menu lệnh, chọn chức nng Add.New Item ể hiển  
thị cửa sổ “Add New Item”, chọn mục “Interface”, hiệu chỉnh tên interface là  
I xpression.cs, chọn button Add ể máy to 1 interface mới. Viết code cho  
interface này nh sau :  
interface IExpression {  
//hàm tính trị biểu thức  
double eval(IVarList e);  
//hàm tối gin biểu thức  
IExpression simplify();  
//ịnh nghĩa thuộc tính Left (chỉ ọc)  
IExpression Left {get;}  
//ịnh nghĩa thuộc tính Right (chỉ ọc)  
IExpression Right { get; }  
}
Trang 3  
8. Hiện thực class abstract chứa những thông tin chung mà các ối tợng biểu  
thức khác nhau (hằng, biến, biểu thức 2 ngôi) s dùng :  
- thuộc tính Left (vì hằng và biến không cần).  
- thuộc tính Right (vì hằng và biến không cần).  
Dời chuột về th mục xpression trong cửa sổ “Solution xplorer”, ấn phi  
chuột vào nó ể hiển thị menu lệnh, chọn chức nng Add.Class ể hiển thị  
cửa sổ “Add New Item”, chọn mục “Class”, hiệu chỉnh tên class là  
Abstract xpr.cs, chọn button Add ể máy to 1 class mới. Viết code cho class  
này nh sau :  
abstract class AbstractExpr : IExpression {  
//hàm tính trị biểu thức  
public abstract double eval(IVarList e);  
//hàm tối gin biểu thức  
public abstract IExpression simplify();  
//hiện thực thuộc tính Left (chỉ ọc)  
public virtual IExpression Left { get { return null; } }  
//hiện thực thuộc tính Right (chỉ ọc)  
public virtual IExpression Right { get { return null; } }  
}
.
Hiện thực class miêu t hằng số :  
Dời chuột về th mục xpression trong cửa sổ “Solution xplorer”, ấn phi  
chuột vào nó ể hiển thị menu lệnh, chọn chức nng Add.Class ể hiển thị  
cửa sổ “Add New Item”, chọn mục “Class”, hiệu chỉnh tên class là Constant.cs,  
chọn button Add ể máy to 1 class mới. Viết code cho class này nh sau :  
class Constant : AbstractExpr {  
//giá trị của hằng  
private double value;  
//hàm khởi to hằng có giá trị d xác ịnh  
public Constant(double d) {  
value = d;  
}
//hàm tính toán hằng  
public override double eval(IVarList e) {  
return value;  
}
//hiện thực thuộc tính Value (chỉ ọc)  
public double Value {  
get {  
return value;  
}
}
Trang 4  
//hàm gii mã hằng về chuỗi vn bn  
public override String ToString() {  
return String.Format("{0:f }", value);  
}
//hàm tối gin hằng  
public override IExpression simplify() {  
//không thể tối gin hn nữa  
return this;  
}
}
10. Hiện thực class miêu t biến, ta dùng cách ặc tên biến theo dng Xi, với i là  
chỉ số của biến từ 0 trở lên :  
Dời chuột về th mục xpression trong cửa sổ “Solution xplorer”, ấn phi  
chuột vào nó ể hiển thị menu lệnh, chọn chức nng Add.Class ể hiển thị  
cửa sổ “Add New Item”, chọn mục “Class”, hiệu chỉnh tên class là Variable.cs,  
chọn button Add ể máy to 1 class mới. Viết code cho class này nh sau :  
class Variable : AbstractExpr {  
//chỉ số của biến trong môi trờng tính toán  
private int rang;  
//hàm khởi to biến có chỉ số i  
public Variable(int i) {  
rang = i;  
}
//hàm tính trị của biến  
public override double eval(IVarList e) {  
return e[rang];  
}
//hàm gii mã biến thành dng chuỗi  
public override String ToString() {  
return "X" + rang;  
}
//hàm tối gin biến  
public override IExpression simplify() {  
//không thể tối gin hn nữa  
return this;  
}
}
11. Hiện thực kiểu enum miêu t mã các phép toán ợc dùng ể xây dựng biểu  
thức. Trong bài thực hành này ta hn chế chỉ dùng 3 toán tử 2 ngôi cộng, trừ,  
nhân ể xây dựng biểu thức. Ta không dùng phép chia ể hn chế lỗi chia 0  
trong quá trình tính biểu thức :  
Trang 5  
Dời chuột về th mục xpression trong cửa sổ “Solution xplorer”, ấn phi  
chuột vào nó ể hiển thị menu lệnh, chọn chức nng Add.Class ể hiển thị  
cửa sổ “Add New Item”, chọn mục “Class”, hiệu chỉnh tên class là Operator.cs,  
chọn button Add ể máy to 1 class mới. Viết code cho class này nh sau :  
enum Operator {  
//kiểu liệt kê các mã phép toán 2 ngôi ợc dùng  
PLUS,  
MINUS,  
MULT,  
DIV  
}
Lu ý phi ổi từ khóa từ class thành enum.  
12. Hiện thực class miêu t biểu thức dùng toán tử 2 ngôi :  
Dời chuột về th mục xpression trong cửa sổ “Solution xplorer”, ấn phi  
chuột vào nó ể hiển thị menu lệnh, chọn chức nng Add.Class ể hiển thị  
cửa sổ “Add New Item”, chọn mục “Class”, hiệu chỉnh tên class là  
BinOp xpr.cs, chọn button Add ể máy to 1 class mới. Viết code cho class  
này nh sau :  
class BinOpExpr : AbstractExpr {  
// toán hng trái  
private IExpression left;  
// toán hng phi  
private IExpression right;  
//mã toán tử 2 ngôi  
private Operator op;  
//hàm khởi to biểu thức dùng toán tử 2 ngôi op dùng 2 toán hng l và r  
public BinOpExpr(Operator op, IExpression l, IExpression r) {  
this.op = op;  
left = l;  
right = r;  
}
//hàm tính trị của biểu thức  
public override double eval(IVarList e) {  
switch (op) {  
case Operator.PLUS:  
return left.eval(e) + right.eval(e);  
case Operator.MINUS:  
return left.eval(e) - right.eval(e);  
case Operator.MULT:  
return left.eval(e) * right.eval(e);  
case Operator.DIV:  
return left.eval(e) / right.eval(e);  
}
return 0;  
}
Trang 6  
//hiện thực thuộc tính Left (chỉ ọc)  
public override IExpression Left {  
get { return left; }  
}
//hiện thực thuộc tính Right (chỉ ọc)  
public override IExpression Right {  
get { return right; }  
}
//hàm gii mã biểu thức thành chuỗi vn bn  
public override String ToString() {  
StringBuilder ret = new StringBuilder("(" + left);  
switch (op) {  
case Operator.PLUS:  
ret.Append(" + ");  
break;  
case Operator.MINUS:  
ret.Append(" - ");  
break;  
case Operator.MULT:  
ret.Append(" * ");  
break;  
default:  
ret.Append(" / ");  
break;  
}
ret.Append(right + ")");  
return ret.ToString();  
}
//hàm tối gin biểu thức  
public override IExpression simplify() {  
//tối gin biểu thức con bên trái  
IExpression ls = left.simplify();  
//tối gin biểu thức con bên phi  
IExpression rs = right.simplify();  
IExpressionFactory ef = new ExpressionFactory();  
if ((rs as Constant) == null || (ls as Constant) == null)  
return ef.createBinaryOp(op, ls, rs);  
//tính biểu thức hằng  
double ketqua;  
double l = ls.eval(null);  
double r = rs.eval(null);  
switch (op) {  
case Operator.PLUS:  
Trang 7  
ketqua = l + r;  
break;  
case Operator.MINUS:  
ketqua = l - r;  
break;  
case Operator.MULT:  
ketqua = l * r;  
break;  
default:  
ketqua = l / r;  
break;  
}
return ef.createConstant(ketqua);  
}
}
13. Ta cần ối tợng chuyên qun lý giá trị của các biến ể phục vụ tính toán biểu  
thức theo các biến. Trớc hết ta ịnh nghĩa interface tối thiểu cho ối tợng  
qun lý giá trị của các biến này.  
Dời chuột về th mục xpression trong cửa sổ “Solution xplorer”, ấn phi  
chuột vào nó ể hiển thị menu lệnh, chọn chức nng Add.New Item ể hiển  
thị cửa sổ “Add New Item”, chọn mục “Interface”, hiệu chỉnh tên interface là  
IVarList.cs, chọn button Add ể máy to 1 interface mới. Viết code cho  
interface này nh sau :  
interface IVarList {  
//ịnh nghĩa indexer  
double this [int i] {get; set; }  
}
14. Hiện thực ối tợng qun lý trị các biến nh sau :  
Dời chuột về th mục xpression trong cửa sổ “Solution xplorer”, ấn phi  
chuột vào nó ể hiển thị menu lệnh, chọn chức nng Add.Class ể hiển thị  
cửa sổ “Add New Item”, chọn mục “Class”, hiệu chỉnh tên class là VarList.cs,  
chọn button Add ể máy to 1 class mới. Viết code cho class này nh sau :  
class VarList : IVarList {  
//danh sách trị của các biến  
private double[] variables;  
//hàm khởi to môi trờng tính toán có size biến  
public VarList (int size) {  
variables = new double[size];  
}
//ịnh nghĩa indexer qun lý các biến  
public double this [int i] {  
get { return variables[i]; }  
set { variables[i] = value; }  
Trang 8  
}
//hàm gii mã biểu thức thành chuỗi vn bn  
public override String ToString() {  
String buf="[";  
for (int i = 0; i < variables.Length; i++)  
if (i == 0) buf += String.Format("{0:f }", this[i]);  
else buf += ", " + String.Format("{0:f }", this[i]);  
buf += "]";  
return buf;  
}
}
1 . Ta dùng mẫu Abstract Factory ể cung cấp dịch vụ to các ối tợng mà  
chng trình ứng dụng dùng. ối tợng Factory có kh nng nh sau :  
- to ợc ối tợng hằng số.  
- to ợc ối tợng biến.  
- to ợc ối tợng biểu thức nhị phân.  
- to ợc ối tợng biểu thức ngẫu nhiên.  
- to ợc ối tợng biểu thức ngẫu nhiên có tối a maxprof cấp lồng nhau.  
- to ợc ối tợng qun lý trị các biến ợc dùng ể tính biểu thức.  
Dời chuột về th mục xpression trong cửa sổ “Solution xplorer”, ấn phi  
chuột vào nó ể hiển thị menu lệnh, chọn chức nng Add.New Item ể hiển  
thị cửa sổ “Add New Item”, chọn mục “Interface”, hiệu chỉnh tên interface là  
I xpressionFactory.cs, chọn button Add ể máy to 1 interface mới. Viết code  
cho interface này nh sau :  
interface IExpressionFactory {  
//hàm to hằng có giá trị xác ịnh  
IExpression createConstant(double constant);  
//hàm to biến có chỉ số xác ịnh  
IExpression createVariable(int id);  
//hàm to biểu thức dùng toán tử 2 ngôi  
IExpression createBinaryOp(Operator op, IExpression left, IExpression right);  
//hàm to biểu thức ngẫu nhiên  
IExpression createRandomExpression();  
//hàm to biểu thức ngẫu nhiên có tối a maxProf cấp  
IExpression createRandomExpression(int maxProf);  
//hàm to ối tợng tính toán ngẫu nhiên  
IVarList createRandomVarList();  
}
Dời chuột về th mục xpression trong cửa sổ “Solution xplorer”, ấn phi  
chuột vào nó ể hiển thị menu lệnh, chọn chức nng Add.Class ể hiển thị  
cửa sổ “Add New Item”, chọn mục “Class”, hiệu chỉnh tên class là  
Trang 9  
xpressionFactory.cs, chọn button Add ể máy to 1 class mới. Viết code cho  
class này nh sau :  
class ExpressionFactory : IExpressionFactory {  
//số biến ợc dùng trong biểu thức  
private static int MAXVARIABLE = 2;  
//ối tợng to số ngẫu nhiên duy nhất dng Singleton  
private MyRandom rnd = MyRandom.getInstance();  
//hàm to biểu thức dùng toán tử 2 ngôi  
public IExpression createBinaryOp(Operator op, IExpression left, IExpression right) {  
return new BinOpExpr(op, left, right);  
}
//hàm to hằng có giá trị xác ịnh  
public IExpression createConstant(double constant) {  
return new Constant(constant);  
}
//hàm to biến có chỉ số xác ịnh  
public IExpression createVariable(int id) {  
if (id >= MAXVARIABLE)  
MAXVARIABLE = id + 1;  
return new Variable(id);  
}
//hàm to biểu thức ngẫu nhiên (có tối a 3 cấp lồng nhau)  
public IExpression createRandomExpression() {  
return createRandomExpression(3);  
}
//hàm to biểu thức ngẫu nhiên có tối a maxProf cấp lồng nhau  
public IExpression createRandomExpression(int maxProf) {  
int cat=0;  
if (maxProf == 0)  
cat = rnd.RndInt(2);  
else  
cat = rnd.RndInt(4);  
switch (cat) {  
case 0: //biểu thức hằng  
return createConstant(rnd.RndDouble());  
case 1: // biểu thức biến  
return createVariable(rnd.RndInt(MAXVARIABLE));  
}
// biểu thức 2 ngôi  
//to biểu thức con bên trái  
IExpression left = createRandomExpression(maxProf - 1);  
Trang 10  
//to biểu thức con bên phi  
IExpression right = createRandomExpression(maxProf - 1);  
//to biểu thức 2 ngôi  
return createBinaryOp((Operator)(rnd.RndInt(3)), left, right);  
}
//hàm to ối tợng tính toán ngẫu nhiên  
public IVarList createRandomVarList() {  
IVarList e = new VarList(MAXVARIABLE);  
for (int i = 0; i < MAXVARIABLE; i++) {  
e[i] = rnd.RndDouble();  
}
return e;  
}
}
1 . Duyệt tìm phần tử Form1 trong cửa sổ "Solution xplorer", ấn phi chuột vào  
mục này, chọn option "View Designer" ể hiển thị cửa sổ thiết kế Form1.  
1 . Nếu cửa sổ ToolBox cha hiển thị chi tiết, chọn menu View.Toolbox ể hiển  
thị nó (thờng nằm ở bên trái màn hình). Click chuột vào button  
(Auto  
Hide) nằm ở góc trên phi cửa sổ ToolBox ể chuyển nó về chế ộ hiển thị  
thờng trực.  
18. Duyệt tìm phần tử Button trong cửa sổ ToolBox, chọn nó và v nó ở góc trên  
trái của Form. Vào cửa sổ thuộc tính của Button và hiệu chỉnh li thuộc tính  
Text = "Start", thuộc tính (Name) = btnStart. To hàm xử lý sự kiện Click  
trên Button rồi viết on code kiểm thử hệ thống qun lý biểu thức nh sau :  
private void btnStart_Click(object sender, EventArgs e){  
//to ối tợng qun lý file ể ghi dữ liệu  
StreamWriter oFile = new StreamWriter("data.txt", true, Encoding.Unicode);  
//to ối tợng Factory qun lý việc to các biểu thức  
IExpressionFactory ef = new ExpressionFactory();  
//to biểu thức ngẫu nhiên có tối a 6 cấp lồng nhau  
IExpression e1 = ef.createRandomExpression(6);  
//to danh sách giá trị các biến ợc dùng trong tính toán biểu thức  
IVarList env = ef.createRandomVarList();  
oFile.WriteLine("Dùng danh sách giá trị các biến : "+ env.ToString());  
oFile.WriteLine("ể tính biểu thức:");  
oFile.WriteLine(e1.ToString());  
oFile.WriteLine(String.Format("Kết qu là : {0:f }", e1.eval(env)));  
oFile.WriteLine("Biểu thức có dng tối gin sau :");  
e1 = e1.simplify();  
oFile.WriteLine(e1.ToString());  
oFile.WriteLine(String.Format("Kết qu tính là : {0:f }", e1.eval(env)));  
oFile.WriteLine("===============================================");  
oFile.Close();  
}
Trang 11  
Lu ý thêm 2 lệnh using 2 namespace ợc dùng trong ứng dụng nh sau :  
using System.IO;  
using BaiTH .Expression;  
1 . Dịch và chy chng trình. Nếu có lỗi thì sửa, nếu hết lỗi thì chng trình s  
chy. Mỗi lần ngời dùng click chuột vào button, chng trình s to 1 biểu  
thức ngẫu nhiên, tính và xuất kết qu. Sau ó, chng trình tối gin biểu  
thức, tính trị và xuất kết qu ể so sánh. Thử click chuột vào button nhiều lần  
(30 lần) rồi dừng chng trình.  
20. Dùng trình WordPad mở file data.txt trong th mục chứa file kh thi của  
chng trình, quan sát xem từng biểu thức ợc to ra và xử lý bở chng  
trình xem có sai sót gì không ?  
pdf 11 trang myanh 24080 Free
Bạn đang xem tài liệu "Bài tập thực hành môn Các mẫu thiết kế hướng đối tượng - Bài thực hành số 6.1: Xây dựng và kiểm thử hệ thống quản lý biểu thức", để tải tài liệu gốc về máy hãy click vào nút Download ở trên

File đính kèm:

  • pdfbai_tap_thuc_hanh_mon_cac_mau_thiet_ke_huong_doi_tuong_bai_t.pdf