接口类和抽象类在设计模式中的一些应用

C++设计模式中,有些模式需要使用接口类(Interface Class)和抽象类(Abstract Class)来实现特定的设计目标。以下是一些常见的设计模式及其需要的原因,并附上相应的代码片段。

1. 策略模式(Strategy Pattern

需要接口类:策略模式通过定义一组算法或行为接口,使得算法可以独立于使用它们的客户端而变化。

原因:策略模式需要定义一组通用的行为接口,这些接口可以在运行时动态切换。

代码片段:

cpp 复制代码
// 接口类
class Strategy {
public:
    virtual void execute() = 0;  // 纯虚函数
};

// 具体策略类
class ConcreteStrategyA : public Strategy {
public:
    void execute() override {
        std::cout << "Executing strategy A\n";
    }
};

class ConcreteStrategyB : public Strategy {
public:
    void execute() override {
        std::cout << "Executing strategy B\n";
    }
};

// 上下文类
class Context {
private:
    Strategy* strategy;

public:
    Context(Strategy* s) : strategy(s) {}
    void setStrategy(Strategy* s) {
        strategy = s;
    }

    void executeStrategy() {
        strategy->execute();
    }
};

// 使用策略模式
int main() {
    Context context(new ConcreteStrategyA());
    context.executeStrategy();  // 输出 "Executing strategy A"
    context.setStrategy(new ConcreteStrategyB());
    context.executeStrategy();  // 输出 "Executing strategy B"
    return 0;
}

2. 工厂方法模式(Factory Method Pattern

需要抽象类:工厂方法模式通过定义一个创建对象的接口,但将具体类的实例化延迟到子类中。

原因:工厂方法模式需要定义一个抽象类,用于定义创建对象的接口,并让子类实现具体的产品创建逻辑。

代码片段:

cpp 复制代码
// 抽象产品类
class Product {
public:
    virtual void use() = 0;  // 纯虚函数
};

// 具体产品类
class ConcreteProductA : public Product {
public:
    void use() override {
        std::cout << "Using product A\n";
    }
};

class ConcreteProductB : public Product {
public:
    void use() override {
        std::cout << "Using product B\n";
    }
};

// 抽象工厂类
class Creator {
public:
    virtual Product* factoryMethod() = 0;  // 纯虚函数
};

// 具体工厂类
class ConcreteCreatorA : public Creator {
public:
    Product* factoryMethod() override {
        return new ConcreteProductA();
    }
};

class ConcreteCreatorB : public Creator {
public:
    Product* factoryMethod() override {
        return new ConcreteProductB();
    }
};

// 使用工厂方法模式
int main() {
    Creator* creator = new ConcreteCreatorA();
    Product* product = creator->factoryMethod();
    product->use();  // 输出 "Using product A"

    creator = new ConcreteCreatorB();
    product = creator->factoryMethod();
    product->use();  // 输出 "Using product B"
    return 0;
}

3. 观察者模式(Observer Pattern

需要接口类:观察者模式通过定义观察者和主题的接口,使得主题状态发生变化时,所有观察者都能得到通知。

原因:观察者模式需要定义通用的观察者和主题接口,以便在运行时动态添加和移除观察者。

代码片段:

cpp 复制代码
// 接口类:观察者
class Observer {
public:
    virtual void update(int value) = 0;  // 纯虚函数
};

// 具体观察者类
class ConcreteObserverA : public Observer {
public:
    void update(int value) override {
        std::cout << "Observer A received update: " << value << "\n";
    }
};

class ConcreteObserverB : public Observer {
public:
    void update(int value) override {
        std::cout << "Observer B received update: " << value << "\n";
    }
};

// 主题类
class Subject {
private:
    std::vector<Observer*> observers;
    int state;

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

    void setState(int value) {
        state = value;
        notifyObservers();
    }

    void notifyObservers() {
        for (Observer* observer : observers) {
            observer->update(state);
        }
    }
};

// 使用观察者模式
int main() {
    Subject subject;
    ConcreteObserverA observerA;
    ConcreteObserverB observerB;

    subject.attach(&observerA);
    subject.attach(&observerB);
    subject.setState(10);  // 输出 "Observer A received update: 10" 和 "Observer B received update: 10"

    return 0;
}

4. 模板方法模式(Template Method Pattern

需要抽象类:模板方法模式通过定义一个算法的骨架,将某些步骤延迟到子类中实现。

原因:模板方法模式需要定义一个抽象类,用于定义算法的骨架,并让子类实现具体的步骤。

代码片段:

cpp 复制代码
// 抽象类
class AbstractClass {
public:
    void templateMethod() {
        step1();
        step2();
        step3();
    }

    virtual void step1() = 0;  // 纯虚函数
    virtual void step2() = 0;  // 纯虚函数
    void step3() {
        std::cout << "Step 3 in AbstractClass\n";
    }
};


// 具体子类
class ConcreteClassA : public AbstractClass {
public:
    void step1() override {
        std::cout << "Step 1 in ConcreteClassA\n";
    }

    void step2() override {
        std::cout << "Step 2 in ConcreteClassA\n";
    }
};

class ConcreteClassB : public AbstractClass {
public:
    void step1() override {
        std::cout << "Step 1 in ConcreteClassB\n";
    }

    void step2() override {
        std::cout << "Step 2 in ConcreteClassB\n";
    }
};

// 使用模板方法模式
int main() {
    AbstractClass* obj1 = new ConcreteClassA();
    AbstractClass* obj2 = new ConcreteClassB();

    obj1->templateMethod();
    // 输出 "Step 1 in ConcreteClassA"
    // 输出 "Step 2 in ConcreteClassA"
    // 输出 "Step 3 in AbstractClass"

    obj2->templateMethod();
    // 输出 "Step 1 in ConcreteClassB"
    // 输出 "Step 2 in ConcreteClassB"
    // 输出 "Step 3 in AbstractClass"

    delete obj1;
    delete obj2;
    return 0;
}

在C++设计模式中,命令模式(Command Pattern)、状态模式(State Pattern)、职责链模式(Chain of Responsibility Pattern)和组合模式(Composite Pattern)也都涉及使用接口类和抽象类来实现特定的设计目标。以下是对这些模式的详细说明,并附上相应的代码片段。

1. 命令模式(Command Pattern

需要接口类:命令模式通过定义命令的接口,将请求封装为对象,使得可以参数化客户端对象、记录请求队列、支持撤销操作等。

原因:命令模式需要定义一个通用的命令接口,使得不同的命令对象可以被统一处理。

代码片段:

cpp 复制代码
// 接口类:命令
class Command {
public:
    virtual void execute() = 0;  // 纯虚函数
};

// 具体命令类
class ConcreteCommandA : public Command {
private:
    std::string recipient;

public:
    ConcreteCommandA(const std::string& r) : recipient(r) {}
    void execute() override {
        std::cout << "Command A executed by " << recipient << "\n";
    }
};

class ConcreteCommandB : public Command {
private:
    std::string recipient;

public:
    ConcreteCommandB(const std::string& r) : recipient(r) {}
    void execute() override {
        std::cout << "Command B executed by " << recipient << "\n";
    }
};

// 调用者类
class Invoker {
private:
    Command* command;

public:
    void setCommand(Command* c) {
        command = c;
    }

    void executeCommand() {
        command->execute();
    }
};

// 使用命令模式
int main() {
    Invoker invoker;
    ConcreteCommandA commandA("Client A");
    ConcreteCommandB commandB("Client B");

    invoker.setCommand(&commandA);
    invoker.executeCommand();  // 输出 "Command A executed by Client A"
    invoker.setCommand(&commandB);
    invoker.executeCommand();  // 输出 "Command B executed by Client B"

    return 0;
}

2. 状态模式(State Pattern

需要接口类:状态模式通过定义状态的接口,使得对象的行为可以根据其内部状态的改变而改变。

原因:状态模式需要定义一个通用的状态接口,使得不同的状态对象可以被统一处理。

代码片段:

cpp 复制代码
// 接口类:状态
class State {
public:
    virtual void handle() = 0;  // 纯虚函数
};

// 具体状态类
class ConcreteStateA : public State {
public:
    void handle() override {
        std::cout << "Handling state A\n";
    }
};

class ConcreteStateB : public State {
public:
    void handle() override {
        std::cout << "Handling state B\n";
    }
};

// 上下文类
class Context {
private:
    State* state;

public:
    void setState(State* s) {
        state = s;
    }

    void request() {
        state->handle();
    }
};

// 使用状态模式
int main() {
    Context context;
    ConcreteStateA stateA;
    ConcreteStateB stateB;

    context.setState(&stateA);
    context.request();  // 输出 "Handling state A"

    context.setState(&stateB);
    context.request();  // 输出 "Handling state B"
    return 0;
}

3. 职责链模式(Chain of Responsibility Pattern

需要接口类:职责链模式通过定义处理请求的接口,将多个处理者链接在一起,使得请求可以沿着链进行传递,直到被处理为止。

原因:职责链模式需要定义一个通用的处理者接口,使得不同的处理者可以被统一处理。

代码片段:

cpp 复制代码
// 接口类:处理者
class Handler {
protected:
    Handler* next;

public:
    void setNext(Handler* n) {
        next = n;
    }

    virtual void handleRequest(int request) = 0;  // 纯虚函数
};

// 具体处理者类
class ConcreteHandlerA : public Handler {
public:
    void handleRequest(int request) override {
        if (request < 10) {
            std::cout << "ConcreteHandlerA handled request " << request << "\n";
        } else if (next != nullptr) {
            next->handleRequest(request);
        }
    }
};

class ConcreteHandlerB : public Handler {
public:
    void handleRequest(int request) override {
        if (request >= 10 && request < 20) {
            std::cout << "ConcreteHandlerB handled request " << request << "\n";
        } else if (next != nullptr) {
            next->handleRequest(request);
        }
    }
};

// 使用职责链模式
int main() {
    ConcreteHandlerA handlerA;
    ConcreteHandlerB handlerB;

    handlerA.setNext(&handlerB);
    handlerA.handleRequest(5);   // 输出 "ConcreteHandlerA handled request 5"
    handlerA.handleRequest(15);  // 输出 "ConcreteHandlerB handled request 15"
    handlerA.handleRequest(25);  // 没有处理者处理该请求
    return 0;
}

4. 组合模式(Composite Pattern

需要抽象类:组合模式通过定义组合对象和叶子对象的接口,使得客户端可以统一处理单个对象和组合对象。

原因:组合模式需要定义一个通用的组件接口,使得叶子节点和组合节点可以被统一处理。

代码片段:

cpp 复制代码
// 抽象类:组件
class Component {
public:
    virtual void operation() = 0;  // 纯虚函数
    virtual void add(Component* component) {}
    virtual void remove(Component* component) {}
    virtual Component* getChild(int index) { return nullptr; }
};

// 叶子类
class Leaf : public Component {
public:
    void operation() override {
        std::cout << "Leaf operation\n";
    }
};

// 组合类
class Composite : public Component {
private:
    std::vector<Component*> children;

public:
    void operation() override {
        std::cout << "Composite operation\n";
        for (Component* child : children) {
            child->operation();
        }
    }

    void add(Component* component) override {
        children.push_back(component);
    }

    void remove(Component* component) override {
        children.erase(std::remove(children.begin(), children.end(), component), children.end());
    }

    Component* getChild(int index) override {
        return children[index];
    }
};

// 使用组合模式
int main() {
    Composite root;
    Leaf leaf1;
    Leaf leaf2;
    Composite branch;

    branch.add(&leaf1);
    branch.add(&leaf2);
    root.add(&branch);

    root.operation();

    // 输出 "Composite operation"
    // 输出 "Leaf operation"
    // 输出 "Leaf operation"

    return 0;
}

总结

  • 策略模式:需要接口类来定义一组通用的行为接口。
  • 工厂方法模式:需要抽象类来定义创建对象的接口,并让子类实现具体的产品创建逻辑。
  • 观察者模式:需要接口类来定义观察者和主题的接口,以便在运行时动态添加和移除观察者。
  • 模板方法模式:需要抽象类来定义算法的骨架,并让子类实现具体的步骤。
  • 命令模式:需要接口类来定义命令的接口,使得可以参数化客户端对象、记录请求队列、支持撤销操作等。
  • 状态模式:需要接口类来定义状态的接口,使得对象的行为可以根据其内部状态的改变而改变。
  • 职责链模式:需要接口类来定义处理请求的接口,使得请求可以沿着链进行传递,直到被处理为止。
  • 组合模式:需要抽象类来定义组合对象和叶子对象的接口,使得客户端可以统一处理单个对象和组合对象。

这些设计模式通过接口类和抽象类,提供了灵活的、可扩展的解决方案,有效地解决了软件设计中的常见问题。

相关推荐
微澜-10 分钟前
编译以前项目更改在x64下面时报错:函数“PVOID GetCurrentFiber(void)”已有主体
c++
闻缺陷则喜何志丹19 分钟前
【C++动态规划】1411. 给 N x 3 网格图涂色的方案数|1844
c++·算法·动态规划·力扣·网格·数目·涂色
岳轩子1 小时前
23种设计模式之原型模式
设计模式·原型模式
熬夜学编程的小王1 小时前
【C++篇】解锁C++模板的魔法:从万能钥匙到精准雕刻
c++·进阶模版·c++模版·类模版实例化·函数模版实例化
Octopus20771 小时前
【C++】读取数量不定的输入数据
开发语言·c++·笔记·学习
忘梓.1 小时前
C嘎嘎探索篇:栈与队列的交响:C++中的结构艺术
c语言·开发语言·c++·
十五年专注C++开发1 小时前
C++中的链式操作原理与应用(一)
开发语言·c++·设计模式
PaLu-LI1 小时前
ORB-SLAM2源码学习:Initializer.cc:Initializer::CheckFundamental地图初始化——检查基础矩阵F并评分
c++·opencv·学习·线性代数·ubuntu·计算机视觉·矩阵
9毫米的幻想2 小时前
【Linux系统】—— 基本指令(四)
linux·c语言·c++·学习
waves浪游2 小时前
类和对象(中)
c语言·开发语言·数据结构·c++·算法·链表