Tải bản đầy đủ (.pdf) (10 trang)

Giáo trình hình thành hệ thống ứng dụng nguyên lý tạo chuỗi dùng phương thức forreach p5 docx

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (1.36 MB, 10 trang )

Ngôn Ngữ Lập Trình C#
public static comparison WhichStudentComesFirst( Object o1, Object o2)
{
Student s1 = (Student) o1;
Student s2 = (Student) o2;
return (String.Compare( s1.name, s2.name) <0 ?
comparison.theFirstComesFirst :
comparison.theSecondComesFirst);
}
public override string ToString()
{
return name;
}
// biến lưu tên
private string name;
}
public class Test
{
public static void Main()
{
// tạo ra hai đối tượng Student và Cat
// đưa chúng vào hai đối tượng Pair
Student Thao = new Student(“Thao”);
Student Ba = new Student(“Ba”);
Cat Mun = new Cat(5);
Cat Ngao = new Cat(2);
Pair studentPair = new Pair(Thao, Ba);
Pair catPair = new Pair(Mun, Ngao);
Console.WriteLine(“Sinh vien \t\t\t: {0}”, studentPair.ToString());
Console.WriteLine(“Meo \t\t\t: {0}”, catPair.ToString());
// tạo ủy quyền


Pair.WhichIsFirst theStudentDelegate = new
Pair.WhichIsFirst( Student.WhichStudentComesFirst);
Pair.WhichIsFirst theCatDelegate = new
Pair.WhichIsFirst( Cat.WhichCatComesFirst);
// sắp xếp dùng ủy quyền
studentPair.Sort( theStudentDelegate);
Console.WriteLine(“Sau khi sap xep studentPair\t\t:{0}”,
studentPair.ToString());
Cơ Chế Ủy Quyền - Sự Kiện
313
.
.
Ngôn Ngữ Lập Trình C#
studentPair.ReverseSort(theStudentDelegate);
Console.WriteLine(“Sau khi sap xep nguoc studentPair\t\t:{0}”,
studentPair.ToString());
catPair.Sort( theCatDelegate);
Console.WriteLine(“Sau khi sap xep catPair\t\t:{0}”,
catPair.ToString());
catPair.ReverseSort(theCatDelegate);
Console.WriteLine(“Sau khi sap xep nguoc catPair\t\t:{0}”,
catPair.ToString());
}
}
}

 Kết quả:
Sinh vien : Thao, Ba
Meo : 5, 2
Sau khi sap xep studentPair : Ba, Thao

Sau khi sap xep nguoc studentPair : Thao, Ba
Sau khi sap xep catPair : 2, 5
Sau khi sap xep nguoc catPair : 5, 2

Trong đoạn chương trình thử nghiệm trên chúng ta tạo ra hai đối tượng Student và hai đối
tượng Cat sau đó đưa chúng vào hai đối tượng chứa Pair theo từng loại. Bộ khởi dựng của lớp
Student lấy một chuỗi đại diện cho tên của sinh viên và bộ khởi dựng của lớp Cat thì lấy một
số int đại diện cho trọng lượng của mèo.
Student Thao = new Student(“Thao”);
Student Ba = new Student(“Ba”);
Cat Mun = new Cat(“5”);
Cat Ngao = new Cat(“2”);
Pair studentPair = new Pair(Thao, Ba);
Pair catPair = new Pair(Mun, Ngao);
Console.WriteLine(“Sinh vien \t\t\t: {0}”, studentPair.ToString());
Console.WriteLine(“Meo \t\t\t: {0}”, catPair.ToString());
Sau đó chương trình in nội dung chứa bên trong của hai đối tượng chứa Pair, và chúng ta có
thể thấy thứ tự như sau:
Sinh vien : Thao, Ba
Meo : 5, 2
Cơ Chế Ủy Quyền - Sự Kiện
314
.
.
Ngôn Ngữ Lập Trình C#
Thứ tự xuất hiện của nó chính là thứ tự đưa vào. Tiếp theo chúng ta khởi tạo hai đối tượng ủy
quyền:
Pair.WhichIsFirst theStudentDelegate = new
Pair.WhichIsFirst( Student.WhichStudentComesFirst);
Pair.WhichIsFirst theCatDelegate = new

Pair.WhichIsFirst( Student.WhichCatComesFirst);
Ủ y quyền đầu tiên theStudentDelegate được tạo ra bằng cách truyền vào một phương thức
tĩnh tương ứng của lớp Student. Đối tượng ủy quyền thứ hai, theCatDelegate được một
phương thức tĩnh của lớp Cat.
Bây giờ ta đã có các đối tượng ủy quyền, chúng ta truyền ủy quyền đầu tiên cho phương thức
Sort của đối tượng Pair, và sau đó là phương thức ReverseSort. Kết quả được xuất ra màn
hình:
Sau khi sap xep studentPair : Ba, Thao
Sau khi sap xep nguoc studentPair : Thao, Ba
Sau khi sap xep catPair : 2, 5
Sau khi sap xep nguoc catPair : 5, 2
Ủ y quyền tĩnh
Như chúng ta đã thấy trong ví dụ minh hoạ 11.1 trước thì hai thể hiện phương thức ủy
quyền được khai báo bên trong lớp gọi (chính xác là trong hàm Main của Test). Điều này có
thể không cần thiết ta có thể sử dụng khai báo ủy quyền tĩnh từ hai lớp Student và Cat. Do
vậy ta có thể bổ sung lớp Student bằng cách thêm vào:
public static readonly Pair.WhichIsFirst OrderStudents =
new Pair.WhichIsFirst(Student.WhichStudentComesFirst);
Ý nghĩa của lệnh trên là tạo một ủy quyền tĩnh tên là OrderStudents và có thuộc tính chỉ đọc
readonly. Việc thêm vào thuộc tính readonly để ghi chú rằng một khi trường đã được tạo ra
thì không được bổ sung sau đó.
Tương tự như vậy chúng ta có thể tạo ủy quyền tĩnh cho Cat như sau:
public static readonly Pair.WhichIsFirst OderCats =
new Pair.WhichIsFirst( Cat.WhichCatComesFirst);
Bây giờ thì đã có hai trường tĩnh hiện diện bên trong các lớp Student và Cat, mỗi cái sẽ gắn
với phương thức tương ứng bên trong lớp. Sau đó chúng ta có thể thực hiện ủy quyền mà
không cần khai báo thể hiện ủy quyền cục bộ. Việc chuyển ủy quyền được thực hiện trong
lệnh in đậm như sau:
studentPair.Sort( theStudentDelegate);
Console.WriteLine(“Sau khi sap xep studentPair\t\t:{0}”, studentPair.ToString());

studentPair.ReverseSort(Student.OrderStudents);
Console.WriteLine(“Sau khi sap xep nguoc studentPair\t\t:{0}”,
Cơ Chế Ủy Quyền - Sự Kiện
315
.
.
Ngôn Ngữ Lập Trình C#
studentPair.ToString());
catPair.Sort( theCatDelegate);
Console.WriteLine(“Sau khi sap xep catPair\t\t:{0}”, catPair.ToString());
catPair.ReverseSort(Cat.OrderCats);
Console.WriteLine(“Sau khi sap xep nguoc catPair\t\t:{0}”, catPair.ToString());
Kết quả thực hiện tương tự như trong ví dụ 11.1
Sử dụng ủy quyền như thuộc tính
Đối với ủy quyền tĩnh thì chúng bắt buộc phải được tạo thể hiện, do tính chất tĩnh, mà
không cần biết là chúng có được sử dụng hay không, như lớp Student và Cat trong ví dụ bên
trên. Chúng ta có thể phát triển những lớp này tốt hơn bằng cách thay thế ủy quyền tĩnh từ
trường thành thuộc tính.
Với lớp Student ta có thể chuyển khai báo:
public static readonly Pair.WhichIsFirst OrderStudent =
new Pair.WhichIsFirst( Student.WhichStudentComesFirst);
thành khai báo như sau:
public static Pair.WhichIsFirst OrderStudents
{
get
{
return new Pair.WhichIsFirst( WhichStudentComesFirst);
}
}
Tương tự như vậy chúng ta thực hiện thay thế với lớp Cat:

public static Pair.WhichIsFirst OderCats
{
get
{
return new Pair.WhichIsFirst( WhichCatComesFirst);
}
}
Khi truyền cho phương thức thì không thay đổi:
studentPair.Sort( Student.OderStudents);
catPair.Sort( Cat.OrderCats);
Khi thuộc tính OrderStudents được truy cập thì ủy quyền được tạo ra:
return new Pair.WhichIsFirst( WhichCatComesFirst);
Cơ Chế Ủy Quyền - Sự Kiện
316
.
.
Ngôn Ngữ Lập Trình C#
Điều quan trọng ở đây là ủy quyền sẽ không được tạo cho đến khi nào nó được yêu cầu. Việc
này cho phép lớp gọi (như lớp Test) quyết định khi nào cần thiết sử dụng một ủy quyền
nhưng vẫn cho phép việc tạo ủy quyền là trách nhiệm của lớp Student hay lớp Cat.
Thiết lập thứ tự thi hành với mảng ủy quyền
Ủ y quyền có thể giúp chúng ta tạo ra một hệ thống trong đó người sử dụng có thể quyết
định đến thứ tự của các hoạt động khi thực thi. Giả sử chúng ta có một hệ thống xử lý ảnh
trong đó các ảnh có thể được thao tác bởi một phương pháp được định nghĩa tốt như là: làm
mờ, làm đậm, xoay, lọc ảnh, Giả sử rằng, thứ tự khi sử dụng các hiệu ứng này được áp dụng
cho ảnh là quan trọng. Người sử dụng muốn lựa chọn những hiệu ứng này từ menu, anh ta
chọn tất cả các hiệu ứng tùy thích, và sau đó yêu cầu bộ xứ lý ảnh thực hiện lần lượt các hiệu
ứng mà anh ta đã xác định.
Chúng ta có thể tạo những ủy quyền cho mỗi hoạt động và sau đó thêm chúng vào một tập
hợp được sắp, như là một mảng chẳng hạn, theo một thứ tự mà ta muốn chúng thực thi. Một

khi tất cả các ủy quyền được tạo ra và đưa vào tập hợp, chúng ta dễ dàng lặp lần lượt qua các
thành phần của mảng, và thực thi lần lượt từng phương thức ủy quyền.
Chúng ta bắt đầu bằng việc xây dựng một lớp Image thể hiện một ảnh sẽ được xử lý bởi lớp
ImageProcessor:
public class Image
{
public Image()
{
Console.WriteLine(“An image created”);
}
}
Chúng ta có thể tưởng tượng rằng việc xuất ra chuỗi như vậy tương ứng với việc tạo một
ảnh .gif hay .jpeg hay đại loại như vậy.
Sau đó lớp ImageProcessor khai báo một ủy quyền. Dĩ nhiên là chúng ta có thể định nghĩa
một ủy quyền riêng trả về bất cứ kiểu dữ liệu nào hay lấy bất cứ tham số nào mà chúng ta
muốn. Trong ví dụ này chúng ta định nghĩa một ủy quyền có thể đóng gói bất cứ phương thức
không có giá trị trả về và cũng không nhận bất cứ tham số nào hết:
public delegate void DoEffect();
Tiếp tục lớp ImageProcessor khai báo một sô phương thức, và từng phương thức này phù
hợp với ký pháp và kiểu trả về được khai báo bởi ủy quyền:
public static void Blur()
{
Console.WriteLine(“Blurring image”);
}
Cơ Chế Ủy Quyền - Sự Kiện
317
.
.
Ngôn Ngữ Lập Trình C#
public static void Filter()

{
Console.WriteLine(“Filtering image”);
}
public static void Sharpen()
{
Console.WriteLine(“Sharpening image”);
}
public static void Rotate()
{
Console.WriteLine(“Rotating image”);
}
Lớp ImageProcessor cần thiết có một mảng để lưu giữ các ủy quyền mà người sử dụng chọn,
một biến lưu giữ số hiệu ứng được chọn và dĩ nhiên là có một biến ảnh để xử lý:
DoEffect[] arrayOfEffects;
Image image;
int numEffectsRegistered = 0;
ImageProcessor cũng cần một phương thức để thêm các ủy quyền vào trong mảng:
public void AddToEffects( DoEffect theEffect)
{
if (numEffectsRegistered >=0)
{
throw new Exception(“Too many members in array”);
}
arrayOfEffects[numEffectsRegistered ++] = theEffect;
}
Ngoài ra còn cần một phương thức thật sự gọi các ủy quyền này:
public void ProcessImage()
{
for (int i = 0; i < numEffectsRegistered; i++)
{

arrayOfEffects[i]();
}
}
Cuối cùng, chúng ta khai báo những ủy quyền tĩnh, để các client gọi, và chặn chúng lại để xử
lý những phương thức:
public DoEffect BlurEffect = new DoEffect(Blur);
public DoEffect SharpenEffect = new DoEffect(Sharpen);
Cơ Chế Ủy Quyền - Sự Kiện
318
.
.
Ngôn Ngữ Lập Trình C#
public DoEffect FilterEffect = new DoEffect(Filter);
public DoEffect RotateEffect = new DoEffect(Rotate);
Việc chọn các thao tác diễn ra trong quá trình tương tác ở thành phần giao diện người sử
dụng. Trong ví dụ này chúng ta mô phỏng bằng cách chọn các hiệu ứng, thêm chúng vào
trong mảng, và ProcessImage.
 Ví dụ minh họa 11.2: Sử dụng mảng ủy quyền.

namespace Programming_CSharp
{
using System;
// khai báo lớp ảnh
public class Image
{
public Image()
{
Console.WriteLine(“An image created”);
}
}

// lớp xử lý ảnh
public class ImageProcessor
{
// khai báo ủy quyền
public delegate void DoEffect();
// tạo các ủy quyền tĩnh
public DoEffect BlurEffect = new DoEffect(Blur);
public DoEffect SharpenEffect = new DoEffect(Sharpen);
public DoEffect FilterEffect = new DoEffect(Filter);
public DoEffect RotateEffect = new DoEffect(Rotate);
// bộ khởi dựng khởi tạo ảnh và mảng
public ImageProcessor(Image image)
{
this.image = image;
arrayOfEffects = new DoEffect[10];
}
// thêm hiệu ứng vào trong mảng
public void AddToEffects( DoEffect theEffect)
{
if (numEffectsRegistered >=0)
Cơ Chế Ủy Quyền - Sự Kiện
319
.
.
Ngôn Ngữ Lập Trình C#
{
throw new Exception(“Too many members in array”);
}
arrayOfEffects[numEffectsRegistered ++] = theEffect;
}

// các phương thức xử lý ảnh
public static void Blur()
{
Console.WriteLine(“Blurring image”);
}
public static void Filter()
{
Console.WriteLine(“Filtering image”);
}
public static void Sharpen()
{
Console.WriteLine(“Sharpening image”);
}
public static void Rotate()
{
Console.WriteLine(“Rotating image”);
}
// gọi các ủy quyền để thực hiện hiệu ứng
public void ProcessImage()
{
for (int i = 0; i < numEffectsRegistered; i++)
{
arrayOfEffects[i]();
}
}
// biến thành viên
private DoEffect[] arrayOfEffects;
private Image image;
private int numEffectsRegistered = 0;
}

// lớp Test để kiểm chứng chương trình
public class Test
{
Cơ Chế Ủy Quyền - Sự Kiện
320
.
.
Ngôn Ngữ Lập Trình C#
public static void Main()
{
Image theImage = new Image();
// do không có GUI để thực hiện chúng ta sẽ chọn lần
// lượt các hành động và thực hiện
ImageProcessor theProc = new ImageProcessor(theImage);
theProc.AddToEffects(theProc.BlurEffect);
theProc.AddToEffects(theProc.FilterEffect);
theProc.AddToEffects(theProc.RotateEffect);
theProc.AddToEffects(theProc.SharpenEffect);
theProc.ProcessImage();
}
}
}

 Kết quả:
An image created
Blurring image
Filtering image
Rotate image
Sharpening image


Trong ví dụ trên, đối tượng ImageProcessor được tạo ra và những hiệu ứng được thêm vào.
Nếu người dùng chọn làm mờ trước khi lọc ảnh, thì đơn giản là được đưa vào mảng ủy quyền
theo thứ tự tương ứng. Tương tự như vậy, bất cứ hành động lựa chọn nào của người dùng
mong muốn, ta đưa thêm nhiều ủy quyền vào trong tập hợp.
Chúng ta có thể tưởng tượng việc hiển thị thứ tự hành động này trong một danh sách listbox
và cho phép người sử dụng sắp xếp lại phương thức, di chuyển chúng lên xuống trong danh
sách. Khi các hành động này được sắp xếp lại thì chúng ta chỉ cần thay đổi thứ tự trong tập
hợp. Ngoài ra ta cũng có thể đưa các hoạt động này vào trong cơ sở dữ liệu rồi sau đó đọc
chúng lúc thực hiện.
Ủ y quyền dễ dàng cung cấp động cho ta các phương thức được gọi theo một thứ tự xác định
Multicasting
Cơ chế multicasting cho phép gọi hai phương thức thực thi thông qua một ủy quyền đơn.
Điều này trở nên quan trọng khi xử lý các sự kiện, sẽ được thảo luận trong phần cuối của
chương.
Cơ Chế Ủy Quyền - Sự Kiện
321
.
.
Ngôn Ngữ Lập Trình C#
Mục đích chính là có một ủy quyền có thể gọi thực hiện nhiều hơn một phương thức. Điều
này hoàn toàn khác với việc có một tập hợp các ủy quyền, vì mỗi trong số chúng chỉ gọi được
duy nhất một phương thức. Trong ví dụ trước, tập hợp được sử dụng để lưu giữ các ủy quyền
khác nhau. Tập hợp này cũng có thể thêm một ủy quyền nhiều hơn một lần, và sử dụng tập
hợp để sắp xếp lại các ủy quyền và điều khiển thứ tự hành động được gọi.
Với Multicasting chúng ta có thể tạo một ủy quyền đơn và cho phép gọi nhiều phương thức
được đóng. Ví dụ, khi một nút lệnh được nhấn chúng ta có thể muốn thực hiện nhiều hơn một
hàh động. Để làm được điều này chúng ta có thể đưa cho button một tập hợp các ủy quyền,
nhưng để sáng rõ hơn và dễ dàng hơn là tạo một ủy quyền Multicast.
Bất cứ ủy quyền nào trả về giá trị void là ủy quyền multicast, mặc dù vậy ta có thể đối xử với
nó như là ủy quyền bình thường cũng không sao. Hai ủy quyền Multicast có thể được kết hợp

với nhau bằng phép toán cộng (+). Kết quả là một ủy quyền Multicast mới và gọi đến tất cả
các phương thức thực thi nguyên thủy của cả hai bên. Ví dụ, giả sử Writer và Logger là ủy
quyền trả về giá trị void, dòng lệnh theo sau sẽ kết hợp chúng lại với nhau và tạo ra một ủy
quyền Multicast mới:
myMulticastDelegate = Writer + Logger;
Chúng ta cũng có thể thêm những ủy quyền vào trong ủy quyền Multicast bằng toán tử cộng
bằng (+=). Phép toán này sẽ thêm ủy quyền ở phía bên phải của toán tử vào ủy quyền
Multicast ở bên trái. Ví dụ minh họa như sau, giả sử có Transmitter và myMulticastDelegate
là những ủy quyền, lệnh tiếp theo sau đây sẽ thực hiện việc thêm ủy quyền Transmitter vào
trong myMulticastDelegate:
myMulticastDelegate += Transmitter;
Để hiểu rõ ủy quyền Multicast được tạo ra và sử dụng, chúng ta sẽ từng bước tìm hiểu thông
qua ví dụ 11.3 bên dưới, trong ví dụ minh họa này chúng ta sẽ tạo ra một lớp có tên gọi là
MyClassWithDelegate lớp này định nghĩa một delegate, delegate này lấy một tham số là
chuỗi và không có giá trị trả về:
void delegate void StringDelegate( string s);
Sau đó chúng ta định một lớp gọi là MyImplementingClass lớp này có ba phương thức, tất cả
các phương thức này đều trả về giá trị void và nhận một chuỗi làm tham số: WriteString,
LogString, và Transmitting. Phương thức đầu tiên viết một chuỗi xuất ra màn hình tiêu
chuẩn, chuỗi thứ hai mô phỏng viết vào một log file, và phương thức thứ ba mô phỏng việc
chuyển một chuỗi qua Internet. Chúng ta tạo thể hiện delegate để gọi những phương thức
tương ứng:
Writer(“String passed to Writer\n”);
Logger(“String passed to Logger\n”);
Transmitter(“String passed to Transmitter\n”);
Để xem cách kết hợp các delegate, chúng ta tạo một thể hiện delegate khác:
MyClassWithDelegate.StringDelegate myMulticastDelegate;
Cơ Chế Ủy Quyền - Sự Kiện
322
.

.

×