1.2.1设计模式(一)

1.2.1设计模式(一)

背景

设计模式是什么?

  • 是软件开发中,经过验证的,用于解决在特定环境下,重复出现的特定问题的解决方案
  • 是解决问题的固定套路
  • 慎用设计模式

设计模式是怎么来的?

通过满足设计原则之后,慢慢迭代出来的

设计模式解决了什么问题?

前提:具体的需求既有稳定点,又有变化点

期望修改少量代码就可以适应需求的变化
比喻:整洁的房间,好动的猫,怎么保证房间的整洁?把猫放在笼子里

设计模式基础

1)面向对象的思想

  • 封装 -------- 隐藏实现细节,实现模块化
  • 继承 -------- 无需改变原有类的情况下通过继承实现对功能的扩展
  • 多态 -------- 静态多态(函数重载),动态多态(虚函数重写)

2)设计原则

  1. 依赖倒置原则
  • 高层模块不应该依赖低层模块,两者都应该依赖于抽象
  • 抽象不应该依赖具体实现,具体实现应该依赖于抽象
  • 例子:自动驾驶公司是高层,汽车生产商是低层,他们不应该互相依赖。一方变动,另一方也会跟着变动;而应该抽象一个自动驾驶行业标准,高层和低层都依赖它;这样就解耦了两方的变动;自动驾驶系统,汽车生产商都是具体实现,他们应该都依赖自动驾驶行业标准(抽象);
  1. 开放封闭原则
  • 对扩展开放,对修改关闭
  • 类、模块、函数,可以去扩展,但不要去修改。如果要修改代码,尽量用继承或组合的方式来扩展类的功能,而不是直接修改类的代码。
  1. 单一职责原则
  • 一个类应该只有一个发生变化的原因,即一个类只负责一项任务或功能。
  1. 最少知识原则
  • 尽量减少对象之间的交互,从而减小类之间的耦合。在做系统设计时,不要让一个类依赖于太多其他的类,需尽量减小依赖关系
  1. 接口隔离原则
  • 客户端不应该依赖于它不使用的接口。应该将大的接口拆分成小的、特定的接口。
  1. 里式替换原则
  • 子类对象必须能够替换掉它们的父类对象,而不影响程序的行为。

23种设计模式(一)

模板方法模式(Template Method):

在方法中定义算法的骨架,延迟到子类中实现
稳定点:算法的骨架(流程,步骤)
变化点:重写某些具体的步骤

例子:某品牌动物园,有一套固定的表演流程,但是其中若干个表演可以创新替换,以尝试迭代更新表演流程
原流程:猴子->老虎->狗熊->山羊
替换为:猴子->大象->长颈鹿->山羊

代码实现:
不使用设计模式:

#include <iostream>
using namespace std;

// 定义每个动物的表演函数
void monkeyShow() {
    cout << "猴子表演" << endl;
}

void tigerShow() {
    cout << "老虎表演" << endl;
}

void bearShow() {
    cout << "狗熊表演" << endl;
}

void goatShow() {
    cout << "山羊表演" << endl;
}

void elephantShow() {
    cout << "大象表演" << endl;
}

void giraffeShow() {
    cout << "长颈鹿表演" << endl;
}

// 定义一个函数来执行原始流程
void originalProcess() {
    monkeyShow();
    tigerShow();
    bearShow();
    goatShow();
}

// 定义一个函数来执行替换后的流程
void replacedProcess() {
    monkeyShow();
    elephantShow();
    giraffeShow();
    goatShow();
}

int main() {
    // 执行原始流程
    cout << "执行原始流程:" << endl;
    originalProcess();

    // 执行替换后的流程
    cout << "\n执行替换后的流程:" << endl;
    replacedProcess();

    return 0;
}

使用模板方法模式改进后

// 抽象类,定义算法的骨架
class AnimalAction {
public:
    // 模板方法,定义算法的框架
    virtual void performActions() {
        step1();
        step2();
        step3();
        step4();
    }

protected:
    // 抽象方法,由子类实现具体的行为
    virtual void step1() = 0;
    virtual void step2() = 0;
    virtual void step3() = 0;
    virtual void step4() = 0;
};

然后,我们为每套流程定义一个具体的类,这些类继承自AnimalAction类,并实现具体的步骤:

// 第一套
class Action1 : public AnimalAction {
protected:
    void step1() override {
        std::cout << "猴子表演" << std::endl;
    }
    void step2() override {
        std::cout << "老虎表演" << std::endl;
    }
    void step3() override {
        std::cout << "狗熊表演" << std::endl;
    }
    void step4() override {
        std::cout << "山羊表演" << std::endl;
    }
};

// 第二套
class Action2 : public AnimalAction {
protected:
    void step1() override {
        std::cout << "猴子表演" << std::endl;
    }
    void step2() override {
        std::cout << "大象表演" << std::endl;
    }
    void step3() override {
        std::cout << "长颈鹿表演" << std::endl;
    }
    void step4() override {
        std::cout << "山羊表演" << std::endl;
    }
};

最后,我们可以使用这些类来执行不同的流程

int main() {
    AnimalAction* action;

    // 使用猴子->老虎->狗熊->山羊的流程
    action = new MonkeyAction();
    action->performActions();
    delete action;

    // 使用猴子->大象->长颈鹿->山羊的流程
    action = new ElephantAction();
    action->performActions();
    delete action;

    return 0;
}

观察者模式(Observer):

对象间的一对多依赖关系,当一个对象改变状态时,所有依赖于它的对象都会得到通知并自动更新。
稳定点:一对多的依赖关系,“一”变化的时候“多”跟着变化
变化点:“多”增加,“多”减少

例子:某气象站发布气象资料给数据中心,数据中心经过处理,将气象站的信息更新到两个不同的终端( A和B);

#include <iostream>
#include <vector>
#include <algorithm>

class Observer {
public:
    virtual ~Observer() {}
    virtual void update() = 0; // 纯虚函数,具体的更新操作由子类实现
};

class Subject {
private:
    std::vector<Observer*> observers; // 观察者列表

public:
    virtual ~Subject() {}

    // 注册观察者
    void attach(Observer* observer) {
        observers.push_back(observer);
    }

    // 注销观察者
    void detach(Observer* observer) {
        observers.erase(std::remove(observers.begin(), observers.end(), observer), observers.end());
    }

    // 通知所有观察者
    void notify() {
        for (Observer* observer : observers) {
            observer->update();
        }
    }
};

接下来,我们创建两个具体的观察者类ConcreteObserverA和ConcreteObserverB:
由于继承自Observer类所以要重写Obsever类中的update()虚函数

class ConcreteObserverA : public Observer {
public:
    void update() override {
        std::cout << "ConcreteObserverA: Reacting to the event" << std::endl;
    }
};

class ConcreteObserverB : public Observer {
public:
    void update() override {
        std::cout << "ConcreteObserverB: Reacting to the event" << std::endl;
    }
};

然后,我们可以创建一个具体的Subject类ConcreteSubject,它将使用观察者模式:

class ConcreteSubject : public Subject {
private:
    std::string state; // 主题的当前状态

public:
    void setState(const std::string& newState) {
        state = newState;
        notify(); // 状态改变时通知所有观察者
    }

    std::string getState() const {
        return state;
    }
};

最后,在main函数中,我们将创建ConcreteSubject和观察者对象,注册观察者,改变状态,并观察结果:

int main() {
	//创建一个项目(被观察的对象)
    ConcreteSubject subject;
	
	//创建两个观察者
    ConcreteObserverA observerA;
    ConcreteObserverB observerB;
    
	//把观察者加入要观察的项目的项目队列中
    subject.attach(&observerA);
    subject.attach(&observerB);

    // 改变状态,观察者将被通知
    subject.setState("State 1");
    subject.setState("State 2");

    // 注销一个观察者
    subject.detach(&observerA);

    // 再次改变状态,只有未注销的观察者会被通知
    subject.setState("State 3");

    return 0;
}

策略模式(Strategy)

定义一系列算法,把它们一个个封装起来,并使它们可互换。
稳定点:客户程序与算法的调用关系
变化点:可互换

例子:某商场节假日有固定的促销活动,为了加大促销力度,现提升国庆节促销活动规格;
代码:
首先,定义一个Strategy接口,所有的促销策略都将实现这个接口:

class Strategy {
public:
    virtual ~Strategy() {}
    virtual void Promotion() const = 0; 
    // 纯虚函数,具体的促销逻辑由子类实现
};

然后,实现不同的促销策略:

// 普通节假日促销策略A, 要实现父类虚函数Promotion()
class StrategyA : public Strategy {
public:
    void Promotion() const override {
        std::cout << "Applying regular holiday promotion(A)." << std::endl;
    }
};

// 国庆节促销策略B, 要实现父类虚函数Promotion()
class StrategyB : public Strategy {
public:
    void Promotion() const override {
        std::cout << "Applying enhanced National Day promotion(B)." << std::endl;
    }
};

接下来,定义一个Mall类,它将使用一个Strategy对象来执行促销活动:

class Mall {
private:
	//成员变量,一个接口类
    Strategy* promotionStrategy;

public:
	//有参构造
    Mall(Strategy* strategy) : promotionStrategy(strategy) {}

    // 执行促销活动
    void runPromotion() const {
    //promotionStrategy是Strategy类的成员变量
    //Promotion()是Strategy类的成员函数
        promotionStrategy->Promotion();
    }

    // 改变促销策略
    void changePromotionStrategy(Strategy* newStrategy) {
        delete promotionStrategy; // 释放旧策略
        promotionStrategy = newStrategy; // 采用新策略
    }

    ~Mall() {
        delete promotionStrategy; // 销毁策略
    }
};

最后,在main函数中,创建商场实例和不同的促销策略,然后根据需要改变促销策略:

int main() {
    // 创建商场,初始使用普通节假日促销策略
    Mall mall(new StrategyA());
    mall.runPromotion(); // 运行普通节假日促销活动

    // 国庆节来临,提升促销活动规格
    Mall* nationalDayMall = new Mall(new StrategyB());
    nationalDayMall->runPromotion(); // 运行国庆节促销活动

    // 假设国庆节结束后,恢复普通促销活动
    nationalDayMall->changePromotionStrategy(new StrategyB());
    nationalDayMall->runPromotion(); // 运行普通节假日促销活动

    delete nationalDayMall; // 清理资源

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值