You are on page 1of 12

SINGLETON PATTERN

- Khi class theo Singleton Pattern, chỉ có duy nhất một đối tượng cụ thể của class
được khởi tạo xuyên suốt chương trình.
- Ưu điểm: + Hạn chế việc sử dụng tài nguyên.
+ Tránh xung đột trong việc truy cập dữ liệu khi có nhiều đối tượng của
cùng 1 class cùng hoạt động.

1. Tạo Singleton database class:


#include <string>
using namespace std;

class Database {
private:
static Database* pInstance;
int Record;
string Name;
// Cách để ngăn việc tạo đối tượng mới vơi mỗi câu lệnh new là KHAI
BÁO CONSTRUCTOR CỦA LỚP DATABASE THÀNH PRIVATE.
Database (string name) {
Name = name;
Record = 0;
}
public:
void editRecord (string S) {
cout << “Chuong trinh dang thuc hien mot ” << S << “ hoat
dong tren ban ghi ” << Record << “ trong co so du lieu ” <<
Name << ‘\n’;
}

string getName() {
return Name;
}
static Database* getInstance (string name) {
if ( pInstance == NULL ) {
pInstance = new Database(name);
}
return pInstance;
}
};
Database* Database::pInstance = NULL;
// Khi gọi hàm getInstance(…) thì sẽ lấy được đối tượng của lớp Database, và đối tượng đó
là đối tượng duy nhất.

HÀM TEST SINGLETON DATABASE CLASS


/* int main() {
Database* Data;
Data = Database::getInstance(“product”);
cout << “Day la co so du lieu ” << Data->getName() << ‘\n’;
Data = Database::getInstance(“employee”);
cout << “Day la co so du lieu ” << Data->getName() << ‘\n’;
return 0;
}*/

2. Đa luồng trong Singleton Pattern:


- Trong hàm getInstance(…) ta thấy hàm vẫn còn lỗ hỏng. Đó là việc khi có
nhiều thread hoạt động. ( thread được hiểu là 1 phần của chương trình đa luồng
(Chương trình đa luồng chữa 2 hoặc nhiều phần chạy đồng thời), môic thread định
nghĩa 1 đường đi riêng biệt của sự thực thi. )
- Vậy lỗ hỏng là ở câu lệnh kiểu tra con trỏ pInstance == NULL. Vì ở cả 2
threads khi chúng cùng gọi đến hàm getInstance(…) thì cả 2 threads đều trả về kết
quả true.
- Cách ngăn chặn:
+ Sử dụng mutex để đồng bộ xử lý các threads.
/* #include <iostream>
#include <mutex>

using namespace std;

class Database {
//…
private:
static mutex Khoa;
public:
//…
static Database* getInstance(string name) {
Khoa.lock();
if (pInstance == NULL) {
pInstance = new Database(name);
}
Khoa.unlock();
return pInstance;
}
};
//…
Mutex Database::Khoa;
*/
+ Tạo đối tượng tĩnh ngay từ lúc khởi chạy chương trình (tức là trước
khi vào hàm main() )
/* #include <string>
using namespace std;

class Database {
private:
int Record;
string Name;
Database (string name) {
Name = name;
Record = 0;
}
public:
void editRecord (string S) {
cout << “Chuong trinh dang thuc hien mot ” << S << “ hoat
dong tren ban ghi ” << Record << “ trong co so du lieu ” <<
Name << ‘\n’;
}

string getName() {
return Name;
}

static Database* getInstance(string name) {


static Database Instance (name);
return &Instance;
}
}; */
FACTORY PATTERN
PHẦN 1: FACTORY METHOD
- Trong quá trình sử dụng ứng dụng, sẽ có lúc khách hàng/ người dùng yêu cầu đồi
kiểu CSDL khác nhau. Thay vì khi khách hàng yêu cầu thì ta lại phải code 1 class mới có
interface giống với CSDL ban đầu và thay đồi liên kết (gây ra mất thời gian và tiêu tốn
nhiều tài nguyên)  Ta sẽ khai báo enum cho connection types.
/* class Connection
{
// define interfaces
virtual string description() = 0;
virtual void setDbName(string dbName) = 0;
virtual void setUsername(string username) = 0;
virtual void setPassword(string password) = 0;
virtual bool initialize() = 0;
.
.
.
};

class OracleConnection : public Connection


{
// implemement Connection's interfaces
string description()
{
return "OracleConnection";
};
.
.
.
};

class SqlServerConnection : public Connection


{
// implemement Connection's interfaces
string description()
{
return "SqlServerConnection";
};
.
.
.
};

class MySqlConnection : public Connection


{
// implemement Connection's interfaces
string description()
{
return "MySqlConnection";
};
.
.
.
}; */
- Tuy nhiên việc có nhiều chỗ cần tạo database connection, đồng nghĩa ta phải có
nhiều đoạn switch case
/* // connectionType is a variable of eConnectionType type
// value of connectionType is set base on some business logical
...

Connection *connection = nullptr;

switch (connectionType)
{
case CONNECTION_TYPE_ORACLE:
connection = new OracleConnection();
break;
case CONNECTION_TYPE_SQLSERVER:
connection = new SqlServerConnection();
break;
case CONNECTION_TYPE_MYSQL:
connection = new MySqlConnection();
break;
default:
connection = new OracleConnection(); // default is Oracle
break;
}*/
- Cách để giải quyết là ta sẽ đặt đoạn code tạo connection vào 1 method của 1 class
để tránh trùng lặp code
/* class DbConnectionFactory
{
public:
static Connection* createConnection(eConnectionType connectionType);
};

Connection* DbConnectionFactory::createConnection(eConnectionType
connectionType)
{
Connection *connection = nullptr;
switch (connectionType)
{
case CONNECTION_TYPE_ORACLE:
connection = new OracleConnection();
break;
case CONNECTION_TYPE_SQLSERVER:
connection = new SqlServerConnection();
break;
case CONNECTION_TYPE_MYSQL:
connection = new MySqlConnection();
break;
default:
connection = new OracleConnection(); // default is Oracle
break;
}

return connection;
}*/
- Hàm DbConnectionFactory::createConnection chính là Factory Method
* Ưu điểm của Factory Method:
- Tách biệt công việc tạo đối tượng ra khỏi xử lý code của khách hàng
<Chỉ cho khách hàng thấy phần giao diện chứ không cho thấy sự thay đổi của
cách thức thực hiện của ứng dụng>
- Dễ bảo trì:
Khi muốn thêm/bớt các liên kết các lớp, hoặc sửa tên. Cách thức thực hiện của
phương thức mà không làm ảnh hưởng đến các phần code khác.

PHẦN 2: ABSTRACT FACTORY


- Bài toán được đặt ra là việc thay đổi phong cách trong việc hiển thị giao diện cho
người dùng. Việc mỗi giao diện có 1 màu sắc và đồ họa khác nhau sẽ khiến việc trực tiếp
code từng giao diện cho mỗi chủ đề (theme) gây trùng lặp code, khó bảo trì và tái sử dụng.
- Ta sẽ định nghĩa một lớp WidgetFactory đóng vai trò là Interface.
- Trong class mỗi phương thức sẽ là một theme của giao diện
ADAPTER PATTERN
- Cho phép người lập trình sử dụng chung interface giữa các đối tượng hoặc các lớp
mà không cần phải sửa đối lại các đối tượng hoặc lớp (cho phù hợp với interface đó).
FACADE PATTERN

- Facade Pattern là một design pattern khá giống với Adapter Pattern.
- Cả 2 đều dùng để chuyển đối interface của các class nhưng có mục đích khác nhau.
- Facade Pattern sẽ giúp đơn giản hóa interface (tức là khi giao diện quá phức tạp,
loằng ngoàng khiến người dùng khó sử dụng ta sẽ sử dụng đến facade để đơn giản hóa giao
diện và các vấn đề phức tạp sẽ được thực hiện một cách âm thầm theo đúng quá trình để
cho ra kết quả đúng như mong muốn)
TEMPLATE METHOD PATTERN
- Template Method Pattern được áp dụng để định nghĩa cấu trúc chung, bộ khung
chung cho một xử lý nào đó ở lớp cha và cho phép các lớp con định nghĩa lại bộ khung đó
mà không làm thay đổi cấu trcs chung của nó.
- Ví dụ:
class Robot {
public:
Robot() {}

void start() {
cout << "Starting ..." << endl;
}

void getParts() {
cout << "Getting a carburetor ..." << endl;
}

void assemble() {
cout << "Installing the carburetor ..." << endl;
}

void test() {
cout << "Revving the engine ..." << endl;
}

void stop() {
cout << "Stopping ..." << endl;
}
void go() {
start();
getParts();
assemble();
test();
stop();
}
};
 Việc sử dụng template method pattern chỉ có tác dụng khi cách thức thực hiện các
hàm hầu như giống nhau và chỉ khác nhau chủ yếu ở thứ tự thực hiện thì khi đó áp
dụng template mới hiệu quả
OBSERVER PATTERN
- Dùng để tạo ra mối quan hệ phụ thuộc one-to-many giữa các đối tượng, khi 1 đối
tượng thay đổi trạng thái thì tất cả các đối tượng phụ thuộc nó sẽ được thông báo và cập
nhật tự động.
- Observer cần phải đăng kí với Subject và mỗi Subject có thể có nhièu hơn 1
Observer
- Subject sẽ lưu thông tin về tất cả các observer đã đăng kí.
- Khi có sự kiện xảy ra, Subject sẽ thông báo đến tất cả các observer đã đăng kí.
- Bất kì lúc nào các observer đã đăng kí cũng có thể hủy đăng kí với Subject và sẽ
ngừng nhận thông báo.
STATE PATTERN
- Cho phép một đối tượng có thể thay đổi hành vi của nó dựa trên trạng thái bên
trong.
- Phù hợp để áp dụng trong trường hợp hành vi một đối tượng phụ thuộc vào trạng
thái của nó và nó phải xác định và thay đối hành vi lúc runtime.
- Sự dụng đối tượng và đóng gói state lại như 1 class trỏ đúng vào cái state object
tương ứng với trạng thai hiện tại và gọi các phương thức tương ứng thông qua con trỏ.
 giúp code được tách biệt và đóng gói được xử lý của các state ra các class khác
nhau, dễ bảo trì và mở rộng hơn.

You might also like