• 设计模式-策略模式


    策略模式Strategy): 

        他定义了算法家族,分别封装起来,让它们之间可以相互替换,此模式让算法的变化,不会影响到使用算法的客户。




    1.策略模式是一种定义一系列算法的方法,从概念上来看,所有这些算法完成的都是相同的工作,只是实现不同,它可以以相同的方式调用所有的算法,减少各种算法类与使用算法类之间的耦合。
    2.策略模式的Strategy类层次为Contex定义了一系列的可供重用的算法或行为。继承有助于吸取出这些算法中的公共功能。
    3.策略模式的优点是简化了单元测试,因为每个算法都有自己的类,可以通过自己的接口单独测试。
    4.当不同的行为堆砌在一个类中时,就很难避免使用个条件语句来选择合适的行为。将这些行为封装在一个个独立的Strtegy类中,可以在使用这些行为的类中消除条件语句。
    5.策略模式就是用来封装算法的,但在实践中,我们发现可以用它来封装几乎任何类型的规则,只要在分析过程中听到需要在不同时间应用不同的业务规则,就可以考虑使用策略模式处理这种变化的可能性。
    6.但是在基本的策略模式中,选择所用具体实现的职责由客户端对象承担,并转给策略模式的Context对象。这本身没有接触客户端需要选择判断的压力,而策略模式与简单工厂模式结合后,选择具体实现的职责也可以由Context来承担,这就最大优化地减轻了客户端的职责,然后在用反射优化一下工厂。
    7.然后我实现一下加减乘除的基本策略模式和用简单工厂优化的策略模式,至于反射优化简单工厂就先不写了,用的C++写的,原因你们懂的。

    基本策略模式实现加减乘除


    实现代码

    #pragma once
    
    class CInterface 
    {
    public:
    	virtual bool GetValue(const int &nNumberA ,const int &nNumberB ,int &nAns) = 0;
    };
    
    class CAddition : public CInterface
    {
    public:
    	bool GetValue(const int &nNumberA ,const int &nNumberB ,int &nAns)
    	{
    		nAns = nNumberA + nNumberB;
    		return true;
    	}
    };
    
    class CSubtraction : public CInterface
    {
    public:
    	bool GetValue(const int &nNumberA ,const int &nNumberB ,int &nAns)
    	{
    		nAns = nNumberA - nNumberB;
    		return true;
    	}
    };
    
    class CMultiplication : public CInterface
    {
    public:
    	bool GetValue(const int &nNumberA ,const int &nNumberB ,int &nAns)
    	{
    		nAns = nNumberA * nNumberB;
    		return true;
    	}
    };
    
    class CDivision : public CInterface
    {
    public:
    	bool GetValue(const int &nNumberA ,const int &nNumberB ,int &nAns)
    	{
    		if(nNumberB == 0) 
    			return false;
    		nAns = nNumberA / nNumberB;
    		return true;
    	}
    };
    
    class CStrategy
    {
    private:
    	CInterface *m_pAlgorithm;
    public:
    	void SetStrategy(CInterface *pAlgorithm)
    	{
    		m_pAlgorithm = pAlgorithm;
    	}
    	bool RunFun(const int &nNumberA ,const int &nNumberB ,int &Ans)
    	{
    		return m_pAlgorithm -> GetValue(nNumberA ,nNumberB ,Ans);
    	}
    };
    
    客户端调用

    #include "stdafx.h"
    #include "StrategyMode.h"
    #include <iostream>
    #include <windows.h>
    using namespace std;
    
    int main()
    {
    	CStrategy *pStrate = new CStrategy();
    	CInterface * pMarkMemAlgorithmBody[10] = {0};
    	int nAlgId = 0 ,nAns;
    	pMarkMemAlgorithmBody[nAlgId++] = new CAddition();
    	pMarkMemAlgorithmBody[nAlgId++] = new CSubtraction();
    	pMarkMemAlgorithmBody[nAlgId++] = new CMultiplication();
    	pMarkMemAlgorithmBody[nAlgId++] = new CDivision();
    	
    	for(int i = 0 ;i < nAlgId ;i ++)
    	{
    		pStrate->SetStrategy(pMarkMemAlgorithmBody[i]);
    		if(pStrate->RunFun(1 ,5 ,nAns))
    		{
    			cout<<nAns<<endl;
    		}
    		else 
    		{
    			cout<<"Error"<<endl;
    		}
    	}
        delete pStrate;
    	for(int i = 0 ;i < nAlgId ;i ++)
    	{
    		delete pMarkMemAlgorithmBody[i];
    	}
    	return 0;
    }
    
    结果


        然后是用简单工厂来优化客户端选择的算法的问题,为此解决掉客户端和算法实现之间本身的耦合度过高问题。大体思路就是我们直接在策略类里面建造一个小的工厂,然后客户端只要创建策略类然后直接传进去一个key值就行了。和工厂相比,这个姿势并不是得到对象,而是设置对象,客户端方面不会得到任何新的对象,只是在设置策略里面的一个算法变量指针的值而已,然后直接调用策略提供的函数,从而执行想要的结果,耦合度远远低于工厂模式(工厂模式客户端不光知道工厂,起码还要知道算法接口类型,不然怎么创建出来一个类型变量来接受工厂创建出来的对象呢?)

    结构实现代码

    #pragma once
    #include <string.h>
    
    class CInterface 
    {
    public:
    	virtual bool GetValue(const int &nNumberA ,const int &nNumberB ,int &nAns) = 0;
    };
    
    class CAddition : public CInterface
    {
    public:
    	bool GetValue(const int &nNumberA ,const int &nNumberB ,int &nAns)
    	{
    		nAns = nNumberA + nNumberB;
    		return true;
    	}
    };
    
    class CSubtraction : public CInterface
    {
    public:
    	bool GetValue(const int &nNumberA ,const int &nNumberB ,int &nAns)
    	{
    		nAns = nNumberA - nNumberB;
    		return true;
    	}
    };
    
    class CMultiplication : public CInterface
    {
    public:
    	bool GetValue(const int &nNumberA ,const int &nNumberB ,int &nAns)
    	{
    		nAns = nNumberA * nNumberB;
    		return true;
    	}
    };
    
    class CDivision : public CInterface
    {
    public:
    	bool GetValue(const int &nNumberA ,const int &nNumberB ,int &nAns)
    	{
    		if(nNumberB == 0) 
    			return false;
    		nAns = nNumberA / nNumberB;
    		return true;
    	}
    };
    
    class CStrategy
    {
    private:
    	CInterface *m_pAlgorithm;
    	CInterface * pMarkMemAlgorithmBody[10];
    	int nAlgId;
    public:
    	CStrategy()
    	{
    		nAlgId = 0x00;
    		memset(pMarkMemAlgorithmBody ,0x00 ,sizeof(pMarkMemAlgorithmBody));
    	}
    	void SetStrategy(int nKey)
    	{
    		m_pAlgorithm = NULL;
    		switch (nKey)
    		{
    		case '+' :
    			{
    				m_pAlgorithm = new CAddition();
    			}break;
    		case '-' :
    			{
    				m_pAlgorithm = new CSubtraction();
    			}break;
    		case '*' :
    			{
    				m_pAlgorithm = new CMultiplication();
    			}break;
    		case '/' :
    			{
    				m_pAlgorithm = new CDivision();
    			}break;
    		default :break;
    		}
    		pMarkMemAlgorithmBody[nAlgId++] = m_pAlgorithm;
    	}
    
    	//释放内存防止内存泄露
    	~CStrategy()
    	{
    		for(int i = 0 ;i < nAlgId ;i ++)
    		{
    			delete pMarkMemAlgorithmBody[i];
    		}
    	}
    
    	bool RunFun(const int &nNumberA ,const int &nNumberB ,int &Ans)
    	{
    		if(m_pAlgorithm != NULL)
    		{
    			return m_pAlgorithm -> GetValue(nNumberA ,nNumberB ,Ans);
    		}
    		else return -1;
    	}
    };
    客户端调用

    #include "stdafx.h"
    #include "StrategyMode.h"
    #include <iostream>
    #include <windows.h>
    using namespace std;
    
    int main()
    {
    	CStrategy *pStrate = new CStrategy();
    	int nKey[] = {'+' ,'-' ,'*' ,'/'} ,nAns;
    	for(int i = 0 ;i < 4 ;i ++)
    	{
    		pStrate->SetStrategy(nKey[i]);
    		if(pStrate->RunFun(1 ,5 ,nAns))
    		{
    			cout<<nAns<<endl;
    		}
    		else 
    		{
    	        cout<<"Error"<<endl;
    		}
    	}
    	delete pStrate;
    	return 0;
    }

    执行结果


        最后如果是想继续优化的话,就把上面的策略工厂里面的switch用反射处理下就行了(前提是语言支持反射)。


  • 相关阅读:
    MySQL体系结构
    Java线程池ThreadPoolExecuter:execute()原理
    Java Thread 如何处理未捕获的异常?
    SSL/TSL握手过程详解
    LockSupport HotSpot里park/unpark的实现
    JAVA 对象内存结构
    JAVA 线程状态转换
    Spring源码解析(四)Bean的实例化和依赖注入
    Spring源码解析(五)循环依赖问题
    Spring源码解析(三)BeanDefinition的载入、解析和注册
  • 原文地址:https://www.cnblogs.com/csnd/p/12062359.html
Copyright © 2020-2023  润新知