Microsoft Word Bai 6 1 docx Trang 1 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 qun lý biểu thức I Mục tiêu Giúp SV làm quen với cách thức qun lý biểu t[.]
Trang 1MÔ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 qun lý biểu thức
I Mục tiêu :
Giúp SV làm quen với cách thức qun 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 qun 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 bn 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 gin 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 li các mẫu này trong bất kỳ vị trí nào của chng trình mới cần xây dựng
IV Qui trình xây dựng chng trình
chọn icon "Windows Form Application" trong listbox "Templates" bên phi, thiết lập th mục chứa Project trong listbox "Location", nhập tên Project vào textbox "Name:" (td BaiTH7), click button OK ể to Project theo các thông
số ã khai báo
form là quá trình lặp 4 thao tác to mới/xóa/hiệu chỉnh thuộc tính/to 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à to biểu thức
trên phần tử gốc này, chọn option Add.New Folder, ặt tên cho folder mới là Expression
ta s to 1 ối tợng duy nhất chuyên phục vụ to số ngẫu nhiên ể bo m phần tử to 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 :
- to số nguyên ngẫu nhiên bất kỳ
- to số nguyên ngẫu nhiên nằm trong khong từ 0 tới n
- to số thực ngẫu nhiên nằm trong khong từ 0 tới 1
Trang 2Dời chuột về th mục Expression trong cửa sổ “Solution Explorer”, ấn phi chuột vào nó ể hiển thị menu lệnh, chọn chức nng 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 to 1 class mới Viết code cho class này nh sau :
classMyRandom {
//hàm khởi to private ể cấm bên ngoài to ối tợng MyRandom
private MyRandom() { }
//thông tin dùng chung trong class
privatestaticMyRandom myrnd = newMyRandom();
publicstaticMyRandom getInstance() { return myrnd; }
//thông tin trong ối tợng
privateRandom rnd = newRandom();
publicint RndInt() { return rnd.Next(); }
publicint RndInt(int n) { return rnd.Next(n); }
publicdouble RndDouble() { return rnd.NextDouble(); }
}
Lu ý rằng ta ã dùng mẫu Adapter ể xây dựng class MyRandom dựa trên class Random của NET 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 5.1
thành phần cấu thành biểu thức bất kỳ theo lợc ồ class nh sau :
thức 2 ngôi có các dịch vụ sau :
- tham kho biểu thức con bên trái
- tham kho biểu thức con bên phi
- tính trị biểu thức
- tối gin biểu thức
Dời chuột về th mục Expression trong cửa sổ “Solution Explorer”, ấn phi chuột vào nó ể hiển thị menu lệnh, chọn chức nng 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à IExpression.cs, chọn button Add ể máy to 1 interface mới Viết code cho interface này nh sau :
interfaceIExpression {
//hàm tính trị biểu thức
double eval(IVarList e);
//hàm tối gin 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 38 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)
chuột vào nó ể hiển thị menu lệnh, chọn chức nng Add.Class ể hiển thị cửa sổ “Add New Item”, chọn mục “Class”, hiệu chỉnh tên class là AbstractExpr.cs, chọn button Add ể máy to 1 class mới Viết code cho class này nh sau :
abstractclassAbstractExpr : IExpression {
//hàm tính trị biểu thức
publicabstractdouble eval(IVarList e);
//hàm tối gin biểu thức
publicabstractIExpression simplify();
//hiện thực thuộc tính Left (chỉ ọc)
publicvirtualIExpression Left { get { returnnull; } }
//hiện thực thuộc tính Right (chỉ ọc)
publicvirtualIExpression Right { get { returnnull; } }
}
chuột vào nó ể hiển thị menu lệnh, chọn chức nng 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 to 1 class mới Viết code cho class này nh sau : classConstant : AbstractExpr {
//giá trị của hằng
privatedouble value;
//hàm khởi to hằng có giá trị d xác ịnh
public Constant(double d) {
value = d;
}
//hàm tính toán hằng
publicoverridedouble eval(IVarList e) {
return value;
}
//hiện thực thuộc tính Value (chỉ ọc)
publicdouble Value {
get {
return value;
}
}
Trang 4//hàm gii mã hằng về chuỗi vn bn
publicoverrideString ToString() {
returnString.Format("{0:f5}", value);
}
//hàm tối gin hằng
publicoverrideIExpression simplify() {
//không thể tối gin hn nữa
returnthis;
}
}
10 Hiện thực class miêu t biến, ta dùng cách ặc tên biến theo dng Xi, với i là chỉ số của biến từ 0 trở lên :
chuột vào nó ể hiển thị menu lệnh, chọn chức nng 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 to 1 class mới Viết code cho class này nh sau : classVariable : AbstractExpr {
//chỉ số của biến trong môi trờng tính toán
privateint rang;
//hàm khởi to biến có chỉ số i
public Variable(int i) {
rang = i;
}
//hàm tính trị của biến
publicoverridedouble eval(IVarList e) {
return e[rang];
}
//hàm gii mã biến thành dng chuỗi
publicoverrideString ToString() {
return"X" + rang;
}
//hàm tối gin biến
publicoverrideIExpression simplify() {
//không thể tối gin hn nữa
returnthis;
}
}
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 hn 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 ể hn chế lỗi chia 0 trong quá trình tính biểu thức :
Trang 5Dời chuột về th mục Expression trong cửa sổ “Solution Explorer”, ấn phi chuột vào nó ể hiển thị menu lệnh, chọn chức nng 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 to 1 class mới Viết code cho class này nh sau : enumOperator { //kiểu liệt kê các mã phép toán 2 ngôi ợc dùng
PLUS,
MINUS,
MULT,
DIV
}
12 Hiện thực class miêu t biểu thức dùng toán tử 2 ngôi :
chuột vào nó ể hiển thị menu lệnh, chọn chức nng Add.Class ể hiển thị cửa sổ “Add New Item”, chọn mục “Class”, hiệu chỉnh tên class là BinOpExpr.cs, chọn button Add ể máy to 1 class mới Viết code cho class này nh sau :
classBinOpExpr : AbstractExpr {
// toán hng trái
privateIExpression left;
// toán hng phi
privateIExpression right;
//mã toán tử 2 ngôi
privateOperator op;
//hàm khởi to biểu thức dùng toán tử 2 ngôi op dùng 2 toán hng 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
publicoverridedouble eval(IVarList e) {
switch (op) {
caseOperator.PLUS:
return left.eval(e) + right.eval(e);
caseOperator.MINUS:
return left.eval(e) - right.eval(e);
caseOperator.MULT:
return left.eval(e) * right.eval(e);
caseOperator.DIV:
return left.eval(e) / right.eval(e);
}
return 0;
}
Trang 6//hiện thực thuộc tính Left (chỉ ọc)
publicoverrideIExpression Left {
get { return left; }
}
//hiện thực thuộc tính Right (chỉ ọc)
publicoverrideIExpression Right {
get { return right; }
}
//hàm gii mã biểu thức thành chuỗi vn bn
publicoverrideString ToString() {
StringBuilder ret = newStringBuilder("(" + left); switch (op) {
caseOperator.PLUS:
ret.Append(" + ");
break;
caseOperator.MINUS:
ret.Append(" - ");
break;
caseOperator.MULT:
ret.Append(" * ");
break;
default:
ret.Append(" / ");
break;
}
ret.Append(right + ")");
return ret.ToString();
}
//hàm tối gin biểu thức
publicoverrideIExpression simplify() {
//tối gin biểu thức con bên trái
IExpression ls = left.simplify();
//tối gin biểu thức con bên phi
IExpression rs = right.simplify();
IExpressionFactory ef = newExpressionFactory();
if ((rs asConstant) == null || (ls asConstant) == 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) {
caseOperator.PLUS:
Trang 7ketqua = l + r;
break;
caseOperator.MINUS:
ketqua = l - r;
break;
caseOperator.MULT:
ketqua = l * r;
break;
default:
ketqua = l / r;
break;
}
return ef.createConstant(ketqua);
}
}
13 Ta cần ối tợng chuyên qun 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 qun lý giá trị của các biến này
Dời chuột về th mục Expression trong cửa sổ “Solution Explorer”, ấn phi chuột vào nó ể hiển thị menu lệnh, chọn chức nng 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 to 1 interface mới Viết code cho interface này nh sau :
interfaceIVarList {
//ịnh nghĩa indexer
double this [int i] {get; set; }
}
14 Hiện thực ối tợng qun lý trị các biến nh sau :
chuột vào nó ể hiển thị menu lệnh, chọn chức nng 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 to 1 class mới Viết code cho class này nh sau : classVarList : IVarList {
//danh sách trị của các biến
privatedouble[] variables;
//hàm khởi to môi trờng tính toán có size biến
publicVarList (int size) {
variables = newdouble[size];
}
//ịnh nghĩa indexer qun lý các biến
public double this [int i] {
get { return variables[i]; }
set { variables[i] = value; }
Trang 8}
//hàm gii mã biểu thức thành chuỗi vn bn
publicoverrideString ToString() {
String buf="[";
for (int i = 0; i < variables.Length; i++)
if (i == 0) buf += String.Format( "{0:f5}" , this [i]);
else buf += ", " + String.Format( "{0:f5}" , this [i]);
buf += "]";
return buf;
}
}
15 Ta dùng mẫu Abstract Factory ể cung cấp dịch vụ to các ối tợng mà chng trình ứng dụng dùng ối tợng Factory có kh nng nh sau :
- to ợc ối tợng hằng số
- to ợc ối tợng biến
- to ợc ối tợng biểu thức nhị phân
- to ợc ối tợng biểu thức ngẫu nhiên
- to ợc ối tợng biểu thức ngẫu nhiên có tối a maxprof cấp lồng nhau
- to ợc ối tợng qun lý trị các biến ợc dùng ể tính biểu thức
Dời chuột về th mục Expression trong cửa sổ “Solution Explorer”, ấn phi chuột vào nó ể hiển thị menu lệnh, chọn chức nng 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à IExpressionFactory.cs, chọn button Add ể máy to 1 interface mới Viết code cho interface này nh sau :
interfaceIExpressionFactory {
//hàm to hằng có giá trị xác ịnh
IExpression createConstant(double constant);
//hàm to biến có chỉ số xác ịnh
IExpression createVariable(int id);
//hàm to biểu thức dùng toán tử 2 ngôi
IExpression createBinaryOp(Operator op, IExpression left, IExpression right);
//hàm to biểu thức ngẫu nhiên
IExpression createRandomExpression();
//hàm to biểu thức ngẫu nhiên có tối a maxProf cấp
IExpression createRandomExpression(int maxProf);
//hàm to ối tợng tính toán ngẫu nhiên
IVarList createRandomVarList();
}
chuột vào nó ể hiển thị menu lệnh, chọn chức nng 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 9ExpressionFactory.cs, chọn button Add ể máy to 1 class mới Viết code cho class này nh sau :
classExpressionFactory : IExpressionFactory {
//số biến ợc dùng trong biểu thức
privatestaticint MAXVARIABLE = 2;
//ối tợng to số ngẫu nhiên duy nhất dng Singleton
privateMyRandom rnd = MyRandom.getInstance();
//hàm to biểu thức dùng toán tử 2 ngôi
publicIExpression createBinaryOp(Operator op, IExpression left, IExpression right) { returnnewBinOpExpr(op, left, right);
}
//hàm to hằng có giá trị xác ịnh
publicIExpression createConstant(double constant) {
returnnewConstant(constant);
}
//hàm to biến có chỉ số xác ịnh
publicIExpression createVariable(int id) {
if (id >= MAXVARIABLE)
MAXVARIABLE = id + 1;
returnnewVariable(id);
}
//hàm to biểu thức ngẫu nhiên (có tối a 3 cấp lồng nhau)
publicIExpression createRandomExpression() {
return createRandomExpression(3);
}
//hàm to biểu thức ngẫu nhiên có tối a maxProf cấp lồng nhau
publicIExpression 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
//to biểu thức con bên trái
IExpression left = createRandomExpression(maxProf - 1);
Trang 10//to biểu thức con bên phi
IExpression right = createRandomExpression(maxProf - 1);
//to biểu thức 2 ngôi
return createBinaryOp((Operator)(rnd.RndInt(3)), left, right);
}
//hàm to ối tợng tính toán ngẫu nhiên
publicIVarList createRandomVarList() {
IVarList e = newVarList(MAXVARIABLE);
for (int i = 0; i < MAXVARIABLE; i++) {
e[i] = rnd.RndDouble();
}
return e;
}
}
16 Duyệt tìm phần tử Form1 trong cửa sổ "Solution Explorer", ấn phi chuột vào mục này, chọn option "View Designer" ể hiển thị cửa sổ thiết kế Form1
17 Nếu cửa sổ ToolBox cha hiển thị chi tiết, chọn menu View.Toolbox ể hiển
Hide) nằm ở góc trên phi 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 li thuộc tính Text = "Start", thuộc tính (Name) = btnStart To hàm xử lý sự kiện Click trên Button rồi viết on code kiểm thử hệ thống qun lý biểu thức nh sau : privatevoid btnStart_Click(object sender, EventArgs e){
//to ối tợng qun lý file ể ghi dữ liệu
StreamWriter oFile = newStreamWriter("data.txt", true, Encoding.Unicode);
//to ối tợng Factory qun lý việc to các biểu thức
IExpressionFactory ef = newExpressionFactory();
//to biểu thức ngẫu nhiên có tối a 6 cấp lồng nhau
IExpression e1 = ef.createRandomExpression(6);
//to 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:f5}", e1.eval(env)));
oFile.WriteLine("Biểu thức có dng tối gin sau :");
e1 = e1.simplify();
oFile.WriteLine(e1.ToString());
oFile.WriteLine(String.Format("Kết qu tính là : {0:f5}", e1.eval(env)));
oFile.Close();
}