Olio-ohjelmointi
Olio-ohjelmoinnin suunnittelumallit C++:ssa

Suunnittelumallit (Design Patterns) tarjoavat vakiintuneita ja tehokkaita ratkaisuja ohjelmoinnissa esiintyviin rakenteellisiin ja käyttäytymiseen liittyviin haasteisiin. Tässä esitellään kolme yleisesti käytettyä mallia: Singleton, Observer ja Factory.

1. Singleton-malli

Tarkoitus: Varmistaa, että luokalla on vain yksi instanssi ja tarjoaa globaalin pääsyn siihen.

Missä käytetään: Esimerkiksi konfiguraatiohallinta, lokitusjärjestelmät tai tietokantayhteys.

UML

+--------------------+
|    Singleton       |
+--------------------+
| - instance: static |
| - Singleton()      |
+--------------------+
| + getInstance()    |
+--------------------+

Koodiesimerkki

class Singleton {
private:
    inline static Singleton* instance = nullptr;
    Singleton() {}
    string name;
public:
    static Singleton* getInstance() {
        if (!instance)
            instance = new Singleton();
        return instance;
    }
    string getName(){
        return name;
    }
    void setName(string value){
        name=value;
    }
};
Edellisestä luokasta voidaan luoda olioita seuraavasti
Singleton* objSingleton1 = Singleton::getInstance();
objSingleton1->setName("Teppo Testi");
//edellä luodaan uusi olio

Singleton* objSingleton2 = Singleton::getInstance();
//edellä ei luoda uutta oliota, vaan palautetaan olemassa oleva olio
cout<<objSingleton2->getName();
2. Observer-malli

Tarkoitus: Mahdollistaa monen olion reagoinnin toisen olion tilamuutoksiin.

Missä käytetään: Käyttöliittymät (UI), tapahtumakäsittely, pelitilanteet (esim. pisteytys tai tilapäivitys).

UML

+----------------+       +--------------------+
|   Subject      |<----- |   Observer         |
+----------------+       +--------------------+
| +attach(obs)   |       | +update()          |
| +setState()    |       +--------------------+

Koodiesimerkki

#include <iostream>
#include <vector>
#include <string>

class Observer {
public:
    virtual void update(int value) = 0;
    virtual ~Observer() = default;
};

class Subject {
    int state;
    std::vector<Observer*> observers;
public:
    void attach(Observer* obs) {
        observers.push_back(obs);
    }

    void setState(int s) {
        state = s;
        notifyAll();
    }

    void notifyAll() {
        for (Observer* obs : observers) {
            obs->update(state);
        }
    }
};

class ConcreteObserver : public Observer {
    std::string name;
public:
    ConcreteObserver(const std::string& n) : name(n) {}

    void update(int value) override {
        std::cout << "Observer [" << name << "] sai päivityksen: tila = " << value << std::endl;
    }
};

int main() {
    Subject subject;

    ConcreteObserver obs1("A");
    ConcreteObserver obs2("B");

    subject.attach(&obs1);
    subject.attach(&obs2);

    std::cout << "Asetetaan tila arvoon 42...\n";
    subject.setState(42);

    std::cout << "Asetetaan tila arvoon 100...\n";
    subject.setState(100);

    return 0;
}
3. Factory-malli

Tarkoitus: Tarjoaa rajapinnan olioiden luomiseen ilman, että asiakasohjelman tarvitsee tietää, mitä luokkaa käytetään.

Missä käytetään: Pelit (eri vihollistyypit), käyttöliittymäkomponenttien luonti, plugin-arkkitehtuuri.

UML

+----------------+         +------------------------+
|   Factory      |-------> |   Product (interface)  |
+----------------+         +------------------------+
| +create(type)  |         | +use() = 0             |
+----------------+         +------------------------+
          |                             ↑
          |                   +----------------------+
          +-----------------> | ConcreteProductA/B   |
                              +----------------------+

Koodiesimerkki

class Product {
public:
    virtual void use() = 0;
};

class ConcreteProductA : public Product {
public:
    void use() override { std::cout << "Tuote A käytössä\n"; }
};

class ConcreteProductB : public Product {
public:
    void use() override { std::cout << "Tuote B käytössä\n"; }
};

class Factory {
public:
    static Product* create(const std::string& type) {
        if (type == "A") return new ConcreteProductA();
        else if (type == "B") return new ConcreteProductB();
        return nullptr;
    }
};

// --- Main-funktio ---
int main() {
    Product* product1 = Factory::create("A");
    Product* product2 = Factory::create("B");

    if (product1) {
        product1->use();
        delete product1;
    }

    if (product2) {
        product2->use();
        delete product2;
    }

    return 0;
}
Yhteenveto
  • Singleton: Yksi instanssi, globaali pääsy.
  • Observer: Ilmoitusmekanismi tilamuutoksista useille olioille.
  • Factory: Luo olioita tyypin mukaan ilman suoraa riippuvuutta luokkien toteutuksesta.



Toggle Menu