设计模式相当于说明书
1. 策略模式
英雄使用不同的武器,需要进行武器切换。

使用多态,运行时切换对象内的算法。可将算法的实现和使用算法的代码隔离开。可以组合来代替继承。开闭原则。无需对上下文进行修改就能引入新的策略

cpp
#include <iostream>
#include <string>
using namespace std;
//Strategy
class Weapon {
public:
virtual string fightAlgorithm() const = 0;
};
class Nife : public Weapon {
public:
string fightAlgorithm() const override {
return "Calculating damage using a dagger.";
}
};
class Axe : public Weapon {
public:
string fightAlgorithm() const override {
return "Calculating damage using an axe.";
}
};
//Context
class Hero {
private:
Weapon* m_weapon; // 抽象类指针指向实现类对象
public:
Hero(Weapon* weapon = nullptr) :m_weapon(weapon) {}
void setWeapon(Weapon* weapon) { m_weapon = weapon; }
void fight() {
cout << m_weapon->fightAlgorithm() << "\n";
}
};
int main()
{
cout << "Client: Hero attacks with a dagger.\n";
Nife nife;
Hero hero(&nife);
hero.fight();
cout << "Client: Hero attacks with an axe.\n";
Axe axe;
hero.setWeapon(&axe);
hero.fight();
}
2.策略模式在Qt中的使用
将策略抽象出来,来实现不同的过滤条件类。不同的过滤条件类交给同一个代理进行操作。实现按照条件进行过滤的功能。按照条件查找对应的人和对象
实现思路
1.创建一个模型QStandardItemModel,将数据添加到模型中
2.新建一个模型过滤代理类FilterStrategy,将模型添加到模型过滤代理类,过滤代理类是抽象类通过不同的类来进行继承和扩展。



cpp
#include <QApplication>
#include <QTreeView>
#include <QStandardItemModel>
#include <QSortFilterProxyModel>
#include <QVBoxLayout>
#include <QComboBox>
#include <QWidget>
// 自定义过滤策略
class FilterStrategy {
public:
virtual ~FilterStrategy() = default;
virtual bool filterAcceptsRow(const QModelIndex& sourceIndex, const QAbstractItemModel* sourceModel) const = 0;
};
// 按名称过滤
class NameFilterStrategy : public FilterStrategy {
public:
bool filterAcceptsRow(const QModelIndex& sourceIndex, const QAbstractItemModel* sourceModel) const override {
QString name = sourceModel->data(sourceIndex.siblingAtColumn(0)).toString(); // 0拿到字符串
return name.contains("A", Qt::CaseInsensitive);
}
};
// 按年龄过滤
class AgeFilterStrategy : public FilterStrategy {
public:
bool filterAcceptsRow(const QModelIndex& sourceIndex, const QAbstractItemModel* sourceModel) const override {
int age = sourceModel->data(sourceIndex.siblingAtColumn(1)).toInt(); // 1拿到姓名
return age > 25;
}
};
// 自定义代理模型
class StrategyProxyModel : public QSortFilterProxyModel {
public:
void setFilterStrategy(FilterStrategy* strategy) {
m_strategy.reset(strategy);
invalidateFilter();
}
protected:
bool filterAcceptsRow(int sourceRow, const QModelIndex& sourceParent) const override {
if (!m_strategy) return true; // 如果为空则返回,如果不为空则继续执行
// 获取到这个module里面这个数据要不要显示出来
QModelIndex index0 = sourceModel()->index(sourceRow, 0, sourceParent);
return m_strategy->filterAcceptsRow(index0, sourceModel());
}
private:
// 依赖于抽象策略
QScopedPointer<FilterStrategy> m_strategy;
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
// 创建数据模型(只有Name和Age两列)
QStandardItemModel model;
model.setHorizontalHeaderLabels({"Name", "Age"});
model.appendRow({new QStandardItem("Alice"), new QStandardItem("25")});
model.appendRow({new QStandardItem("Bob"), new QStandardItem("30")});
model.appendRow({new QStandardItem("Charlie"), new QStandardItem("22")});
model.appendRow({new QStandardItem("David"), new QStandardItem("28")});
// 创建代理模型
StrategyProxyModel proxyModel;
proxyModel.setSourceModel(&model);
QWidget window;
QVBoxLayout layout(&window);
QComboBox filterCombo;
QTreeView treeView;
treeView.setModel(&proxyModel);
filterCombo.addItems({"All", "Name contains A", "Age > 25"});
layout.addWidget(&filterCombo);
layout.addWidget(&treeView);
window.resize(300, 250);
// 连接策略切换
QObject::connect(&filterCombo, &QComboBox::currentTextChanged, [&](const QString& text) {
if (text == "Name contains A") return proxyModel.setFilterStrategy(new NameFilterStrategy());
if (text == "Age > 25") return proxyModel.setFilterStrategy(new AgeFilterStrategy());
return proxyModel.setFilterStrategy(nullptr);
});
window.show();
return a.exec();
}