返回顶部

几种常见的设计模式

设计模式是软件开发中解决常见问题的可重用方案。

以下是几种常见的设计模式,将使用 Go 语言和 C++ 语言分别简单实现,并说明它们解决的问题。

一、单例模式

解决的问题:

确保一个类只有一个实例,并提供全局访问点。适用于需要唯一控制资源(如配置管理器、日志记录器)的场景。

代码实现(go版本):

package main

import (
    "fmt"
    "sync"
)

type Singleton struct {
    data string
}

var instance *Singleton
var once sync.Once

func GetInstance() *Singleton {
    once.Do(func() {
        instance = &Singleton{data: "I am the only instance"}
    })
    return instance
}

func main() {
    s1 := GetInstance()
    s2 := GetInstance()
    fmt.Println(s1.data)
    fmt.Println(s2 == s1) // true,说明是同一个实例
}

代码实现(c++版本):

#include <iostream>
#include <mutex>

class Singleton {
private:
    static Singleton* instance;
    static std::mutex mtx;
    std::string data;

    // 私有构造函数,防止外部创建
    Singleton() : data("I am the only instance") {}

public:
    static Singleton* GetInstance() {
        std::lock_guard<std::mutex> lock(mtx); // 线程安全
        if (instance == nullptr) {
            instance = new Singleton();
        }
        return instance;
    }

    std::string GetData() const { return data; }
};

Singleton* Singleton::instance = nullptr;
std::mutex Singleton::mtx;

int main() {
    Singleton* s1 = Singleton::GetInstance();
    Singleton* s2 = Singleton::GetInstance();
    std::cout << s1->GetData() << std::endl;
    std::cout << (s1 == s2) << std::endl; // 输出 1,表示是同一实例
    return 0;
}
二、工厂模式

解决的问题:

当需要创建的对象类型在运行时才能确定时,工厂模式隐藏对象的创建细节,提供统一的创建接口。适用于解耦对象创建与使用。

代码实现(go版本):

package main

import "fmt"

type Product interface {
    Use() string
}

type ConcreteProductA struct{}
func (p *ConcreteProductA) Use() string { return "Product A" }

type ConcreteProductB struct{}
func (p *ConcreteProductB) Use() string { return "Product B" }

func CreateProduct(productType string) Product {
    switch productType {
    case "A":
        return &ConcreteProductA{}
    case "B":
        return &ConcreteProductB{}
    default:
        return nil
    }
}

func main() {
    p1 := CreateProduct("A")
    p2 := CreateProduct("B")
    fmt.Println(p1.Use()) // Product A
    fmt.Println(p2.Use()) // Product B
}

代码实现(c++版本):

#include <iostream>
#include <string>

class Product {
public:
    virtual std::string Use() const = 0;
    virtual ~Product() {}
};

class ConcreteProductA : public Product {
public:
    std::string Use() const override { return "Product A"; }
};

class ConcreteProductB : public Product {
public:
    std::string Use() const override { return "Product B"; }
};

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

int main() {
    Product* p1 = Factory::CreateProduct("A");
    Product* p2 = Factory::CreateProduct("B");
    std::cout << p1->Use() << std::endl; // Product A
    std::cout << p2->Use() << std::endl; // Product B
    delete p1;
    delete p2;
    return 0;
}

通过 CreateProduct 函数根据参数动态创建对象,客户端无需关心具体实现类。

三、观察者模式

解决的问题:

定义对象间的一对多依赖关系,当一个对象状态变化时,所有依赖它的对象都能自动收到通知。适用于事件驱动系统。

代码实现(go版本):

package main

import "fmt"

type Subject struct {
    observers []Observer
    data      string
}

type Observer interface {
    Update(data string)
}

type ConcreteObserver struct {
    name string
}

func (o *ConcreteObserver) Update(data string) {
    fmt.Printf("%s received update: %s\n", o.name, data)
}

func (s *Subject) Attach(observer Observer) {
    s.observers = append(s.observers, observer)
}

func (s *Subject) Notify() {
    for _, observer := range s.observers {
        observer.Update(s.data)
    }
}

func (s *Subject) SetData(data string) {
    s.data = data
    s.Notify()
}

func main() {
    subject := &Subject{}
    observer1 := &ConcreteObserver{name: "Observer1"}
    observer2 := &ConcreteObserver{name: "Observer2"}

    subject.Attach(observer1)
    subject.Attach(observer2)

    subject.SetData("State changed!")
}

代码实现(c++版本):

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

class Observer {
public:
    virtual void Update(const std::string& data) = 0;
    virtual ~Observer() {}
};

class Subject {
private:
    std::vector<Observer*> observers;
    std::string data;

public:
    void Attach(Observer* observer) {
        observers.push_back(observer);
    }

    void SetData(const std::string& newData) {
        data = newData;
        Notify();
    }

    void Notify() {
        for (Observer* observer : observers) {
            observer->Update(data);
        }
    }
};

class ConcreteObserver : public Observer {
private:
    std::string name;

public:
    ConcreteObserver(const std::string& n) : name(n) {}
    void Update(const std::string& data) override {
        std::cout << name << " received update: " << data << std::endl;
    }
};

int main() {
    Subject subject;
    ConcreteObserver observer1("Observer1");
    ConcreteObserver observer2("Observer2");

    subject.Attach(&observer1);
    subject.Attach(&observer2);

    subject.SetData("State changed!");
    return 0;
}

当 Subject 的状态改变时,调用 Notify 通知所有观察者,解决状态变化与依赖对象同步的问题。

四、策略模式

解决的问题:

将一组算法封装起来,使它们可以互换使用,客户端可以动态选择算法。适用于需要在运行时切换行为的场景。

代码实现(go版本):

package main

import "fmt"

type Strategy interface {
    Execute(a, b int) int
}

type AddStrategy struct{}
func (s *AddStrategy) Execute(a, b int) int { return a + b }

type MultiplyStrategy struct{}
func (s *MultiplyStrategy) Execute(a, b int) int { return a * b }

type Context struct {
    strategy Strategy
}

func (c *Context) SetStrategy(strategy Strategy) {
    c.strategy = strategy
}

func (c *Context) ExecuteStrategy(a, b int) int {
    return c.strategy.Execute(a, b)
}

func main() {
    context := &Context{}

    context.SetStrategy(&AddStrategy{})
    fmt.Println(context.ExecuteStrategy(2, 3)) // 5

    context.SetStrategy(&MultiplyStrategy{})
    fmt.Println(context.ExecuteStrategy(2, 3)) // 6
}

代码实现(c++版本):

#include <iostream>

class Strategy {
public:
    virtual int Execute(int a, int b) const = 0;
    virtual ~Strategy() {}
};

class AddStrategy : public Strategy {
public:
    int Execute(int a, int b) const override { return a + b; }
};

class MultiplyStrategy : public Strategy {
public:
    int Execute(int a, int b) const override { return a * b; }
};

class Context {
private:
    Strategy* strategy;

public:
    Context() : strategy(nullptr) {}
    void SetStrategy(Strategy* s) { strategy = s; }
    int ExecuteStrategy(int a, int b) const {
        if (strategy) return strategy->Execute(a, b);
        return 0;
    }
    ~Context() { delete strategy; } // 注意内存管理
};

int main() {
    Context context;

    context.SetStrategy(new AddStrategy());
    std::cout << context.ExecuteStrategy(2, 3) << std::endl; // 5

    context.SetStrategy(new MultiplyStrategy());
    std::cout << context.ExecuteStrategy(2, 3) << std::endl; // 6

    return 0;
}

通过 Context 动态切换策略(如加法或乘法),解决算法硬编码导致的扩展性问题。

posted @ 2025-04-07 14:56  十方央丶  阅读(35)  评论(0)    收藏  举报