【设计模式——Strategy模式】

设计模式——Strategy模式

策略模式

开发—封闭(OCP)原则作为扩展的面向对象设计的指导方针,策略(Strategy)模式是这一重要原则的体现。一下是该模式的任务说明:
定义一组算法,然后封装每个算法,并使它们可以相互替换。策略模式允许算法独立于使用它的客户端而变化。
在软件设计中,以不同的方式做同一件事情是一个常见的需求。想想列表的排序算法。不同的排序算法,有不同的时间复杂度和空间复杂度。例如:冒泡排序、快速排序、插入排序和堆排序。
冒泡排序是复杂度最低的,也是小消耗内存最少的,但是也是最慢的排序算法之一。相比之下,快读排序是一种快速高效的排序算法,通过递归很容易实现,不需要额外的内存,但在预先排好序的或倒序的列表上效率非常低。借助于策略模式,使用时可以动态地选择不同的排序算法,例如,根据要排序列表的不同特性选择不同的排序算法。
假设希望在任意一个IT 系统中使用 Customer 类实例的文本表示。需求指出文本表示可以被格式化成多种格式:纯文本格式、XML 格式和JSON格式。
首先,为格式化策略引入一个抽象——抽象的Formatter类:
#pragma once
#include
#include<string_view>
#include
using string_view = std::string;
class Formatter
{
public:
virtual ~Formatter() = default;
Formatter& withCustomerId(string_view customerId)
{
this->customerId = customerId;
return *this;
}

Formatter& withForename(string_view forename)
{
	this->forename = forename;
	return *this;
}

Formatter& withSurname(string_view surname)
{
	this->surname = surname;
	return *this;
}

Formatter& withStreet(string_view street)
{
	this->street = street;
	return *this;
}

Formatter& withZipCode(string_view zipCode)
{
	this->zipCode = zipCode;
	return *this;
}

Formatter& withCity(string_view city)
{
	this->city = city;
	return *this;
}

virtual std::string format() const = 0;

protected:
std::string customerId{ “000000” };
std::string forename{ “n/a” };
std::string surname{ “n/a” };
std::string street{ “n/a” };
std::string zipCode{ “n/a” };
std::string city{ “n/a” };

};

using FormatterPtr = std::unique_ptr;
提供利益相关者请求的格式化样式的三个特定格式化程序如下:
#pragma once
//三个特定格式化的程序,重写了Formatter类的Format()纯虚函数
#include"Formatter.h"
class PlainTextFormatter :public Formatter
{
public:
virtual std::string format() const override
{
std::stringstream formattedString{};
formattedString << “[” << customerId << "]: "
<< forename << " " << surname << ", "
<< street << ", " << zipCode << ", "
<< city << “.”;
return formattedString.str();
}
};

class XmlFormatter :public Formatter
{
public:
virtual std::string format() const override
{
std::stringstream formattedString{};
formattedString <<
“<customer id=”" << customerId << “”>\n" <<
" " << forename << “\n” <<
" " << surname << “\n” <<
" " << street << “\n” <<
" " << zipCode << “\n” <<
" " << city << “\n” <<
“\n”;
return formattedString.str();
}
};

class JsonFormatter :public Formatter
{
public:
virtual std::string format() const override
{
std::stringstream formattedString{};
formattedString <<
“{\n” <<
" “CustomerId : “” << customerId << END_OF_PROPERTY <<
" “Foreame: “” << forename << END_OF_PROPERTY <<
" “Surname: “” << surname << END_OF_PROPERTY <<
" “Street: “” << street << END_OF_PROPERTY <<
" “ZIP code: “” << zipCode << END_OF_PROPERTY <<
" “City: “” << city << “”\n” <<
“}\n”;
return formattedString.str();
}
private:
static constexpr const char* const END_OF_PROPERTY{””,\n”};
};
在这里可以看到,开放—封闭(OCP)原则得到了非常好的支持。当需要一个新的输出格式化时,只需要实现Formatter抽象类的一个特殊化即可,不需要修改现有的格式化程序。
如何在getAsFormattedString()成员函数中使用传入的格式化对象
#pragma once
#include"Address.h”
#include"CustomerId.h”
#include"Formatter.h"

class Custmer
{
public:
//…
std::string getAsFormattedString(const FormatterPtr& formatter) const
{
return formatter->withCustomerId(customerId.toString()).
withForename(forename).
withSurname(surename).
withStreet(address.getStreet()).
withZipCode(address.getZipCodeAsString()).
withCity(address.getCity()).
format();
}
//…
private:
CustomerId customerId;
std::string forename;
std::string surename;
Address address;
};
Customer::getAsFormattedString()成员函数有一个接受指向格式化对象的unique_ptr
指针,这个参数可以用于控制该成员函数返回的字符串的格式。换句话说,Customer::getAsFormattedString()成员函数支持格式化策略。

一个抽象的格式化策略和三个具体的格式化类
很容易看到,策略模式能够保证本例中的Customer::getAsFormattedString()成员函数的调用者可以根据需求配置输出格式。示例代码遵循开放—封闭(OCP)原则,可以很容易地添加另一种具体的格式化策略类。当然,其他格式策略类及Customer类完全不受此扩展的影响。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值