객체지향/디자인패턴
디자인 패턴을 이용하여 채팅 프로그램을 만드는 과제
desafinado
2023. 12. 10. 09:03
728x90
싱글톤 패턴 (Server 클래스): 서버 인스턴스는 애플리케이션 전체에서 하나만 존재해야 함. 이를 보장하기 위해 싱글톤 패턴 사용. getInstance() 메서드를 통해 유일한 서버 인스턴스에 접근.
옵저버 패턴 (Observer 및 User 클래스): 서버 상태 변화(여기서는 메시지 전송)를 실시간으로 다수의 클라이언트(유저)에게 알리기 위해 사용. User 클래스는 Observer 인터페이스를 구현하여 서버로부터 메시지를 받음.
빌더 패턴 (MessageBuilder 클래스): 복잡한 문자열(메시지) 생성 과정을 단순화. 메시지를 단계적으로 구축하고, 최종적으로 결합된 메시지를 생성.
#include <iostream>
#include <string>
#include <vector>
#include <list>
// Observer 인터페이스: 상태 변화를 관찰하는 객체들을 위한 인터페이스
class Observer {
public:
virtual ~Observer() {}
virtual void update(const std::string& message) = 0;
};
class Server {
private:
static Server* instance; // 유일한 인스턴스를 저장하는 정적 멤버
std::list<Observer*> observers; // 관찰자 목록
Server() {} // private 생성자로 외부 생성 방지
public:
// 싱글톤 패턴: 인스턴스가 오직 하나만 존재
static Server* getInstance() {
if (instance == nullptr) {
instance = new Server();
}
return instance;
}
void addObserver(Observer* observer) {
observers.push_back(observer);
}
void removeObserver(Observer* observer) {
observers.remove(observer);
}
// 옵저버에게 알림: 모든 관찰자에게 메시지 전달
void notifyObservers(const std::string& message) {
for (Observer* observer : observers) {
observer->update(message);
}
}
};
Server* Server::instance = nullptr;
class User : public Observer {
private:
std::string name; // 유저 이름
Server* server; // 서버 인스턴스
public:
User(const std::string& name, Server* server) : name(name), server(server) {}
void sendMessage(const std::string& message) {
server->notifyObservers(name + ": " + message);
}
// 옵저버 패턴: 상태 변화 시 업데이트 메서드 호출
void update(const std::string& message) override {
std::cout << name << " received: " << message << std::endl;
}
std::string getName() const {
return name;
}
};
// UserFactory: 유저 객체 생성을 단순화
class UserFactory {
public:
static User* createUser(const std::string& name, Server* server) {
return new User(name, server);
}
};
// MessageBuilder: 빌더 패턴, 메시지 생성을 위한 클래스
class MessageBuilder {
private:
std::vector<std::string> messages;
public:
MessageBuilder& addMessage(const std::string& sender, const std::string& message) {
messages.push_back(sender + ": " + message);
return *this;
}
std::string build() {
std::string combinedMessage;
for (const auto& msg : messages) {
combinedMessage += msg + "\n";
}
return combinedMessage;
}
void clear() {
messages.clear();
}
};
int main() {
// 서버 인스턴스 생성
Server* server = Server::getInstance();
// 유저 생성
User* alice = UserFactory::createUser("Alice", server);
User* bob = UserFactory::createUser("Bob", server);
// 유저 등록
server->addObserver(alice);
server->addObserver(bob);
// 메시지 빌더 사용
MessageBuilder messageBuilder;
messageBuilder.addMessage("Alice", "Hello, everyone!")
.addMessage("Bob", "Hi, Alice!");
alice->sendMessage(messageBuilder.build());
messageBuilder.clear();
messageBuilder.addMessage("Bob", "Hello, everyone!")
.addMessage("Alice", "Hi, Alice!");
bob->sendMessage(messageBuilder.build());
delete alice;
delete bob;
return 0;
}
728x90