Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Observer pattern #1

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
cmake-build-debug
.idea
.idea
build/
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[submodule "lib/googletest"]
path = lib/googletest
url = https://github.com/google/googletest.git
15 changes: 11 additions & 4 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,15 +1,22 @@
cmake_minimum_required(VERSION 3.8)
cmake_minimum_required(VERSION 3.5)
project(patterns)

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall")
add_subdirectory(lib/googletest)

include_directories(include)
include_directories(lib/googletest/googletest/include)
include_directories(lib/googletest/googlemock/include)


set(SOURCE_FILES main.cpp)
set(SOURCE_FILES_TESTING Test/main.cpp)
set(SOURCE_FILES
main.cpp
include/Builder.h include/Singleton.h)

set(SOURCE_FILES_TESTING
Test/ObserverTest.cpp
Test/BuilderTest.cpp
Test/SingletonTest.cpp)

add_executable(patterns ${SOURCE_FILES})
add_executable(patterns_testing ${SOURCE_FILES_TESTING})
Expand Down
34 changes: 34 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
C++ Design Patterns
----------------------

### Creational Patters
##### Singleton
Done
##### Abstract Factory
TODO
##### Builder
Done
##### Dependency Injection
##### Factory Method
##### Lazy Initialization
##### Multiton
##### Object Pool
##### Prototype

### Structural Patterns
##### Adapter
##### Bridge
##### Composite
##### Decorator
##### Facade
##### Flyweight
##### Extension Point


### Behavioral Patterns
##### Observer
Done
##### Publish/Subscribe
Ready, not integrated yet
##### Visitor
TODO
60 changes: 60 additions & 0 deletions Test/BuilderTest.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/**
* @file
* Implementation of unit tests for observer pattern.
*/

#include "gtest/gtest.h"

#include "Builder.h"

struct CarData{
protected:
int numSeats = 4;
bool GPS = false;

public:
virtual bool operator==(const CarData& other) const{return numSeats == other.numSeats && GPS == other.GPS;}
};

class Car: public CarData{
public:
explicit Car(const CarData& data):CarData(data){}

int getNumSeats() const{return numSeats;}
bool hasGPS() const{return GPS;}
};

class CarBuilder: public Builder<Car, CarData>{
public:
void setNumSeats(int numSeats){
this->numSeats = numSeats;
}

void setGPS(bool GPS){
this->GPS = GPS;
}

virtual bool isValid() override{
return numSeats < 8;
}
};

// Test builder methods
TEST(Builder, test){
CarBuilder builder;
builder.setNumSeats(5);
builder.setGPS(true);

ASSERT_TRUE(builder.isValid());

builder.setNumSeats(100);
ASSERT_DEATH(builder.getResult(), "Assertion .* failed.");

builder.setNumSeats(5);
Car car = builder.getResult();
std::shared_ptr<Car> car_p = builder.getResultNew();

ASSERT_EQ(car.getNumSeats(), 5);
ASSERT_EQ(car.hasGPS(), true);
ASSERT_EQ(car, *car_p);
}
54 changes: 54 additions & 0 deletions Test/ObserverTest.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/**
* @file
* Implementation of unit tests for observer pattern.
*/

#include "gtest/gtest.h"

#include "Subject.h"

class EventObserver{
public:
virtual void event1(){};
virtual void event2(int a, const std::string &b)=0;
};

class MySubject: public Subject<EventObserver>{
public:
void fireEvent1(){notify(&EventObserver::event1);}
void fireEvent2(){notify(&EventObserver::event2, 42, "test");}
};

class MyObserver: public EventObserver{
public:
bool event1Fired = false;
bool event2Fired = false;

virtual void event1() override{
event1Fired = true;
}

virtual void event2(int a, const std::string &b) override{
ASSERT_EQ(a, 42);
ASSERT_EQ(b, "test");
event2Fired = true;
}
};

// Test if message is received.
TEST(OBS_Subject, test){
MySubject subject;
std::shared_ptr<MyObserver> observer = std::make_shared<MyObserver>();
subject.registerObserver(observer);

ASSERT_FALSE(observer->event1Fired);
ASSERT_FALSE(observer->event2Fired);

subject.fireEvent1();
ASSERT_TRUE(observer->event1Fired);
ASSERT_FALSE(observer->event2Fired);

subject.fireEvent2();
ASSERT_TRUE(observer->event1Fired);
ASSERT_TRUE(observer->event2Fired);
}
43 changes: 43 additions & 0 deletions Test/SingletonTest.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/**
* @file
* Implementation of unit tests for singleton pattern.
*/

#include "gtest/gtest.h"

#include "Singleton.h"


class MySingleton: public Singleton<MySingleton>{
protected:
MySingleton() = default; // make it so no objects can be constructed from the outside.
public:
int a = 3;

bool operator==(const MySingleton& other) const{
return a == other.a;
}
};

// Test if exactly one valid instance.
TEST(Singleton, one_valid){
MySingleton& instance1 = MySingleton::getInstance();
MySingleton& instance2 = MySingleton::getInstance();

ASSERT_EQ(instance1, instance2);
ASSERT_EQ(&instance1, &instance2);

instance1.a = 5;

ASSERT_EQ(instance1, instance2);
ASSERT_EQ(&instance1, &instance2);

instance1 = instance2;

ASSERT_EQ(instance1, instance2);
ASSERT_EQ(&instance1, &instance2);
}

// Test if extra instances can be made. These statements should fail
//MySingleton instance1 = MySingleton::getInstance(); // copy
//MySingleton instance2; // construct
12 changes: 0 additions & 12 deletions Test/main.cpp

This file was deleted.

30 changes: 30 additions & 0 deletions include/Builder.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#ifndef PATTERNS_BUILDER_H
#define PATTERNS_BUILDER_H

/**
* @file Implementation of Builder for builder pattern.
*/


#include <memory>

/**
* @brief A builder interface for a specific class
*/
template <class Result, class Data>
class Builder: protected Data {
public:
virtual Result getResult(){
assert(isValid());
return Result((Data)*this);
}

virtual std::shared_ptr<Result> getResultNew(){
assert(isValid());
return std::make_shared<Result>((Data)*this);
};

virtual bool isValid(){return true;}
};

#endif //PATTERNS_BUILDER_H
30 changes: 30 additions & 0 deletions include/Singleton.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#ifndef PATTERNS_SINGLETON_H
#define PATTERNS_SINGLETON_H

/**
* @file Implementation of Singleton pattern.
*/

template <class T>
class Singleton {
private:
class A: public T{
public:
A() = default;
};

public:
Singleton() = default;
Singleton(Singleton&) = delete;
Singleton(Singleton&&) = delete;
Singleton& operator=(Singleton&) = default;
Singleton& operator=(Singleton&&) = default;

static T& getInstance(){
static A instance;
return instance;
}
};


#endif //PATTERNS_SINGLETON_H
Loading