Design Patterns

 “Mỗi 1 mẫu mô tả 1 vấn đề xảy ra lặp đi lặp lại trong môi trường của chúng ta và mô tả cái cốt lõi của giải pháp đề ra cho vấn đề đó. Bằng cách nào đó bạn đã dùng nó cả triệu lần mà không làm giống nhau hai lần” – Christopher Alexander

Design pattern là 1 kĩ thuật dành cho lập trình hướng đối tượng. Nó cung cấp cho ta cách tư duy trong từng tình huống của việc lập trình hướng đối tượng, và nhà phân tích thiết kế hệ thống phần mềm. Nó cần thiết cho cả nhà lập trình và nhà phân tích thiết kế. Ngoài việc nắm vững công cụ lập trình ,lập trình viên cần phải có một tư duy, một kĩ năng giải quyết các tình huống nhỏ của công việc thiết kế , xây dựng phần mềm mà họ thi hành , điều này phải đảm bảo tính ổn định có nghĩa là lập trình viên phải có thể giải quyết được trong mọi tình huống , đúng tiến độ, phương pháp giải quyết hợp lý và đặc biệt là phải theo một chuẩn nhất định.

Design pattern được dùng ở nhiều lĩnh vực, trong các phần mềm hướng đối tượng các hệ thống lớn, trong các chương trình trò chơi và cả trong các hệ thống xử lý song song

 

docx27 trang | Chuyên mục: Lập Trình Hướng Đối Tượng | Chia sẻ: dkS00TYs | Lượt xem: 2310 | Lượt tải: 1download
Tóm tắt nội dung Design Patterns, để xem tài liệu hoàn chỉnh bạn click vào nút "TẢI VỀ" ở trên
turn _icons[i];
 _icons[_numIcons] = new Icon(name);
 return _icons[_numIcons++];
 }
 static void reportTheIcons()
 {
 cout << "Active Flyweights: ";
 for (int i = 0; i < _numIcons; i++)
 cout getName() << " ";
 cout << endl;
 }
 private:
 enum
 {
 MAX_ICONS = 5
 };
 static int _numIcons;
 static Icon *_icons[MAX_ICONS];
};
int FlyweightFactory::_numIcons = 0;
Icon *FlyweightFactory::_icons[];
class DialogBox
{
 public:
 DialogBox(int x, int y, int incr): _iconsOriginX(x), _iconsOriginY(y),
 _iconsXIncrement(incr){}
 virtual void draw() = 0;
 protected:
 Icon *_icons[3];
 int _iconsOriginX;
 int _iconsOriginY;
 int _iconsXIncrement;
};
class FileSelection: public DialogBox
{
 public:
 FileSelection(Icon *first, Icon *second, Icon *third): DialogBox(100, 100,
 100)
 {
 _icons[0] = first;
 _icons[1] = second;
 _icons[2] = third;
 }
 void draw()
 {
 cout << "drawing FileSelection:" << endl;
 for (int i = 0; i < 3; i++)
 _icons[i]->draw(_iconsOriginX + (i *_iconsXIncrement), _iconsOriginY);
 }
};
class CommitTransaction: public DialogBox
{
 public:
 CommitTransaction(Icon *first, Icon *second, Icon *third): DialogBox(150,150, 150)
 {
 _icons[0] = first;
 _icons[1] = second;
 _icons[2] = third;
 }
 void draw()
 {
 cout << "drawing CommitTransaction:" << endl;
 for (int i = 0; i < 3; i++)
 _icons[i]->draw(_iconsOriginX + (i *_iconsXIncrement), _iconsOriginY);
 }
};
int main()
{
 DialogBox *dialogs[2];
 dialogs[0] = new FileSelection(FlyweightFactory::getIcon("go"),
 FlyweightFactory::getIcon("stop"),FlyweightFactory::getIcon("select"));
 dialogs[1] = new CommitTransaction(FlyweightFactory::getIcon("select"),
 FlyweightFactory::getIcon("stop"),FlyweightFactory::getIcon("undo"));
 for (int i = 0; i < 2; i++)
 dialogs[i]->draw();
 FlyweightFactory::reportTheIcons();
 return 0;
}
Behavioral
.Iterator
a. Vấn đề đặt ra 
Một đối tượng tập hợp như là một danh sách cũng cung cấp cho ta các phương thức truy cập các thành phần của nó. Tuy nhiên đôi lúc chúng ta cần duyệt các thành phần của danh sách theo những cách thức và tiêu chí khác nhau. Chúng ta không nên làm phồng giao diện của danh sách List với các phương thức cho các cách thức duyệt. 
Mẫu Iterator cho phép chúng ta duyệt danh sách dễ dàng bằng cách tách rời chức năng truy cập và duyệt ra khỏi danh sách và đặt vào đối tượng iterator. Lớp Iterator sẽ định nghĩa một giao diện để truy cập các thành phần của danh sách, đồng thời quản lý cách thức duyệt danh sách hiện thời.
Ví dụ:
Mỗi đối tượng thuộc ListIterator quản lý một đối tượng List. Phương thức CurrentItem trả về đối tượng hiện thời, First chuyển đến đối tượng đầu tiên còn Next chuyển sang đối tượng tiếp theo; IsDone kiểm tra xem quá trình duyệt đã hoàn tất chưa. 
Việc tách biệt giữa cơ chế duyệt và đối tượng List cho phép chúng ta xây dựng các đối tượng iterator với các tiêu khác nhau. Lấy ví dụ, hàm FilteringListIterator chỉ cung cấp quyền truy cập đến các thành phần thoả mãn điều kiện lọc.
b. Định nghĩa 
Mẫu Iterator cung cấp khả năng truy cập và duyệt các thành phần của một tập hợp không cần quan tâm đến cách thức biểu diễn bên trong.
c. Sơ đồ UML
Iterator (AbstractIterator) 
Định nghĩa một giao diện cho việc truy cập và duyệt các phần tử 
ConcreteIterator (Iterator) 
Cài đặt giao diện Iterator 
Giữ dấu vết của vị trí hiện tại trong tập duyệt 
Aggregate (AbstractCollection) 
Định nghĩa một giao diện để tạo một đối tượng Iterator 
ConcreteAggregate (Collection) 
Cài đặt giao diện tạo Iterator để trả về một thể nghiệm đúng của ConcreteIterator.
d. Ứng dụng 
- Hỗ trợ nhiều phương án duyệt một tập hợp. 
- Đơn giản hoá giao diện tập hợp. 
- Cho phép có lớn hơn một cách thức duyệt đối với một tập hợp tại một thời điểm. 
Ứng dụng trong các trường hợp sau :
- Truy cập các thành phần của một tập hợp mà không cần quan tâm đến cách thức biểu diễn bên trong. 
- Hỗ trợ nhiều phương án duyệt của các đối tượng tập hợp. 
- Cung cấp giao diện chung cho việc duyệt các cấu trúc tập hợp.
Code minh họa.
#include 
using namespace std;
class Stack
{
 int items[10];
 int sp;
 public:
 friend class StackIter;
 Stack()
 {
 sp = - 1;
 }
 void push(int in)
 {
 items[++sp] = in;
 }
 int pop()
 {
 return items[sp--];
 }
 bool isEmpty()
 {
 return (sp == - 1);
 }
 StackIter *createIterator()const; // 2. Add a createIterator() member
};
class StackIter
{
 // 1. Design an "iterator" class
 const Stack *stk;
 int index;
 public:
 StackIter(const Stack *s)
 {
 stk = s;
 }
 void first()
 {
 index = 0;
 }
 void next()
 {
 index++;
 }
 bool isDone()
 {
 return index == stk->sp + 1;
 }
 int currentItem()
 {
 return stk->items[index];
 }
};
StackIter *Stack::createIterator()const
{
 return new StackIter(this);
}
bool operator == (const Stack &l, const Stack &r)
{
 // 3. Clients ask the container object to create an iterator object
 StackIter *itl = l.createIterator();
 StackIter *itr = r.createIterator();
 // 4. Clients use the first(), isDone(), next(), and currentItem() protocol
 for (itl->first(),itr->first();!itl->isDone();itl->next(),itr>next())
 if (itl->currentItem() != itr->currentItem())
 break;
 bool ans = itl->isDone() && itr->isDone();
 delete itl;
 delete itr;
 return ans;
}
void main()
{
 Stack s1;
 for (int i = 1; i < 5; i++)
 s1.push(i);
 Stack s2(s1), s3(s1), s4(s1), s5(s1);
 s3.pop();
 s5.pop();
 s4.push(2);
 s5.push(9);
 cout << "1 == 2 is " << (s1 == s2) << endl;
 cout << "1 == 3 is " << (s1 == s3) << endl;
 cout << "1 == 4 is " << (s1 == s4) << endl;
 cout << "1 == 5 is " << (s1 == s5) << endl;
}
2.Visitor
a. Định nghĩa 
Visitor là mẫu thiết kế xác định sườn của một giải thuật trong một thao tác, theo một số bước của các phân lớp. Template Method cho phép các lớp con xác định lại chắc chắn một số bước của một giải thuật bên ngoài cấu trúc của giải thuật đó.
b. Sơ đồ UML
- Visitor: + Đưa ra một thao tác Visit cho mỗi lớp của ConcreteElement trong cấu trúc đối tượng. Tên và dấu hiệu của các thao tác này nhận dạng lớp gửi yêu cầu Visit tới visitor, nó cho phép visitor quyết định lớp cụ thể nào của thành phần được thăm. Sau đó visitor có thể truy nhập thành phần trực tiếp thông qua giao diện đặc biệt của nó. 
- ConcreteVisitor: 
+ Thực hiện mỗi thao tác được đưa ra bởi Visitor. Mỗi thao tác thực hiện một phần của giải thuật định nghĩa cho lớp phù hợp của đối tượng trong cấu trúc. ConcreteVisitor cung cấp ngữ cảnh cho giải thuật và lưu trữ trạng thái cục bộ của nó. 
- Element: 
+ Định nghĩa một thao tác Accept, thao tác này mang một visitor như là một đối số. 
- ConcreteElement: 
+ Thực hiện một thao tác Accept, thao tác này mang một visitor như là một đối số. 
- ObjectStructure: 
+ Có thể đếm các thành phần của nó. 
+ Có thể cung cấp một giao diện mức cao cho phép visitor thăm các thành phần của nó. 
+ Có thể là một composite hoặc một sưu tập như danh sách hay tập hợp. 
c. Vận dụng: 
Sử dụng Visitor pattern khi: 
- Một cấu trúc đối tượng chứa đựng nhiều lớp của các đối tượng với các giao diện khác nhau, và ta muốn thực hiện các thao tác trên các đối tượng này thì đòi hỏi các lớp cụ thể của chúng. 
- Nhiều thao tác khác nhau và không có mối liên hệ nào cần được thực hiện trên các đối tượng trong một cấu trúc đối tượng, và ta muốn tránh “làm hỏng” các lớp của chúng khi thực hiện các thao tác đó. Visitor cho phép ta giữ các thao tác có mối liên hệ với nhau bằng cách định nghĩa chúng trong một lớp. Khi một cấu trúc đối tượng được chia sẻ bởi nhiều ứng dụng, sử dụng Visitor để đặt các thao tác này vào trong các ứng dụng cần chúng. 
- Các lớp định nghĩa các cấu trúc đối tượng hiếm khi thay đổi, nhưng ta muốn định nghĩa các thao tác mới trên các cấu trúc. Thay đổi các lớp cấu trúc yêu cầu định nghĩa lại giao diện cho tất cả các visitor 
Code minh họa cho visitor desgin patter
#include 
#include 
using namespace std;
// 1. Add an accept(Visitor) method to the "element" hierarchy
class Element
{
 public:
 virtual void accept(class Visitor &v) = 0;
};
class This: public Element
{
 public:
 /*virtual*/void accept(Visitor &v);
 string thiss()
 {
 return "This";
 }
};
class That: public Element
{
 public:
 /*virtual*/void accept(Visitor &v);
 string that()
 {
 return "That";
 }
};
class TheOther: public Element
{
 public:
 /*virtual*/void accept(Visitor &v);
 string theOther()
 {
 return "TheOther";
 }
};
// 2. Create a "visitor" base class w/ a visit() method for every "element" type
class Visitor
{
 public:
 virtual void visit(This *e) = 0;
 virtual void visit(That *e) = 0;
 virtual void visit(TheOther *e) = 0;
};
 /*virtual*/void This::accept(Visitor &v)
{
 v.visit(this);
}
 /*virtual*/void That::accept(Visitor &v)
{
 v.visit(this);
}
 /*virtual*/void TheOther::accept(Visitor &v)
{
 v.visit(this);
}
// 3. Create a "visitor" derived class for each "operation" to do on "elements"
class UpVisitor: public Visitor
{
 /*virtual*/void visit(This *e)
 {
 cout thiss() << '\n';
 }
 /*virtual*/void visit(That *e)
 {
 cout that() << '\n';
 }
 /*virtual*/void visit(TheOther *e)
 {
 cout theOther() << '\n';
 }
};
class DownVisitor: public Visitor
{
 /*virtual*/void visit(This *e)
 {
 cout thiss() << '\n';
 }
 /*virtual*/void visit(That *e)
 {
 cout that() << '\n';
 }
 /*virtual*/void visit(TheOther *e)
 {
 cout theOther() << '\n';
 }
};
int main()
{
 Element *list[] = 
 {
 new This(), new That(), new TheOther()
 };
 UpVisitor up; // 4. Client creates
 DownVisitor down; // "visitor" objects
 for (int i = 0; i < 3; i++)
 // and passes each
 list[i]->accept(up);
 // to accept() calls
 for (i = 0; i < 3; i++)
 list[i]->accept(down);
}

File đính kèm:

  • docxDesignPatterns.docx
  • pptxDesign pattern.pptx
  • rarDesign Pattern.rar