动机:
在软件开发过程中代码可能会很多变,而如果将这些代码都放在对象中,可能导致需要频繁的修改代码。
将算法和对象进行解耦来解决这个问题。
例子:
假设我们需要设计一款计费收税的app,显然税收的计算方法是多变的,如果将各个国家,各种计算方法都固话在对象中对象的代码将显得臃肿,并且消耗不必要的内存为了避免这种情况,我们需要进行解耦合。
定义一系列算法,把它们一个个封装起来,并且使它们可互相替换(变化)。该模式使得算法可独立于使用它的客户程 序(稳定)而变化(扩展,子类化)。
要点:
1、策略模式是将一组IF-ELSE转化为一系列的可以互相替换的对象,在运行时根据输入来判断调用哪一个对象来实现功能。
2、策略模式主要针对IFELSE语句的解耦合,当代码中存在大量的IFELSE时往往可以考虑使用策略模式来处理。
3、过多的IF_ELSE语句如果全部读取到内存中会有空间浪费。
tips:
如果Strategy对象没有实例变量,那么各个上下文可以共享同一个Strategy对象,从而节省对象开销
https://github.com/chouxianyu/design-patterns-cpp/blob/master/docs/Strategy.md
代码:
https://github.com/chouxianyu/design-patterns-cpp/tree/master/Strategy
/*
实现方式1通过将文件分割为多个小文件,每完成一个小文件的写入刷新一次进度条。
*/
#include <string>
#include <iostream>
using std::string;
class ProgressBar{
public:
void setValue(float value){
// ...
}
};
class FileSplitter
{
string m_filePath;
int m_fileNumber;
ProgressBar* m_progressBar;
public:
FileSplitter(const string& filePath, int fileNumber, ProgressBar* progressBar) :
m_filePath(filePath),
m_fileNumber(fileNumber),
m_progressBar(progressBar){
}
void split(){
//1.读取大文件
//2.分批次向小文件中写入
for (int i = 0; i < m_fileNumber; i++){
//...
float progressValue = m_fileNumber;
progressValue = (i + 1) / progressValue;
m_progressBar->setValue(progressValue);
}
}
};
//MainForm
#include <string>
#include <iostream>
using std::string;
// 以下几个类的具体实现不重要
class Form{
};
class TextBox{
public:
string getText(){
// ...
return "";
}
};
class ProgressBar;
class FileSplitter{
public:
FileSplitter(string filePath, int number, ProgressBar* progressBar){
// ...
}
void split(){
// ...
}
};
//
class MainForm : public Form
{
TextBox* txtFilePath;
TextBox* txtFileNumber;
ProgressBar* progressBar;
public:
void Button1_Click(){
string filePath = txtFilePath->getText();
int number = atoi(txtFileNumber->getText().c_str());
FileSplitter splitter(filePath, number, progressBar);
splitter.split();
}
};
/*
* C++ Design Patterns: Bridge
* Author: Jakub Vojvoda [github.com/JakubVojvoda]
* 2016
*
* Source code is licensed under MIT License
* (for more details see LICENSE)
*
*/
#include <iostream>
#include <vector>
class Subject;
/*
* Observer
* defines an updating interface for objects that should be notified
* of changes in a subject
*/
class Observer
{
public:
virtual ~Observer() {}
virtual int getState() = 0;
virtual void update( Subject *subject ) = 0;
// ...
};
/*
* Concrete Observer
* stores state of interest to ConcreteObserver objects and
* sends a notification to its observers when its state changes
*/
class ConcreteObserver : public Observer
{
public:
ConcreteObserver( const int state ) :
observer_state( state ) {}
~ConcreteObserver() {}
int getState()
{
return observer_state;
}
void update( Subject *subject );
// ...
private:
int observer_state;
// ...
};
/*
* Subject
* knows its observers and provides an interface for attaching
* and detaching observers
*/
class Subject
{
public:
virtual ~Subject() {}
void attach( Observer *observer )
{
observers.push_back(observer);
}
void detach( const int index )
{
observers.erase( observers.begin() + index );
}
void notify()
{
for ( unsigned int i = 0; i < observers.size(); i++ )
{
observers.at( i )->update( this );
}
}
virtual int getState() = 0;
virtual void setState( const int s ) = 0;
// ...
private:
std::vector<Observer*> observers;
// ...
};
/*
* Concrete Subject
* stores state that should stay consistent with the subject's
*/
class ConcreteSubject : public Subject
{
public:
~ConcreteSubject() {}
int getState()
{
return subject_state;
}
void setState( const int s )
{
subject_state = s;
}
// ...
private:
int subject_state;
// ...
};
void ConcreteObserver::update( Subject *subject )
{
observer_state = subject->getState();
std::cout << "Observer state updated." << std::endl;
}
int main()
{
ConcreteObserver observer1( 1 );
ConcreteObserver observer2( 2 );
std::cout << "Observer 1 state: " << observer1.getState() << std::endl;
std::cout << "Observer 2 state: " << observer2.getState() << std::endl;
Subject *subject = new ConcreteSubject();
subject->attach( &observer1 );
subject->attach( &observer2 );
subject->setState( 10 );
subject->notify();
std::cout << "Observer 1 state: " << observer1.getState() << std::endl;
std::cout << "Observer 2 state: " << observer2.getState() << std::endl;
delete subject;
return 0;
}