设计模式_策略模式 更改激光雷达类型

slam 设计模式_策略模式

  • 1介绍
    • 1.1原始需求
    • 1.2 策略模式
      • 1.2.1策略模式介绍
      • 1.2.2 最终使用
      • 1.2.3 接口类(策略定义)
      • 1.2.4 使用类
    • 1.3新激光雷达加入
  • 2 其他实例

1介绍

slam中经常需要更改激光雷达适配算法,最近在学习设计模式,这里使用策略模式,做一些处理,纯粹瞎写,欢迎拍砖。

1.1原始需求

在不同的slam算法里面经常要做算法适配,会有传感器坐标系的适配、数据格式的适配,,激光雷达的类型也比较多,有些需要pcl中注册生成新的数据类型。
这里是激光雷达数据适配的一部分代码。
 void CloudConvert::Process(const sensor_msgs::PointCloud2::ConstPtr &msg,
​                               std::vector<point3D> &pcl_out){switch (lidar_type_){case LidarType::OUST64:Oust64Handler(msg);break;case LidarType::VELO32:VelodyneHandler(msg);break;case LidarType::ROBOSENSE16:RobosenseHandler(msg);break;case LidarType::PANDAR:PandarHandler(msg);break;default:LOG(ERROR) << "Error LiDAR Type: " << int(lidar_type_);break;}
​        pcl_out = cloud_out_;}

可以看到是swich case 的结构,那么下面用策略模式改一下。

1.2 策略模式

1.2.1策略模式介绍

策略模式是生成模式的一种,
1. 是为了维持逻辑稳定
2. 把需要变动的部分抽象成接口,纯虚函数,让实现类去继承他

一般需要三个类:使用类,接口类(策略定义)和实现类(策略实现)。

  1. 按照变化部分和稳定部分的切分,应该有一个类是不变的,我一般都认为是使用类
  2. 有一个策略类作为接口(纯虚函数),
  3. 另外是一个 策略实现类 是可变的;
    在使用的时候,生成相关的策略实现类,传递给使用类的构造函数。然后用多态,动态加载去调用相关的函数,代码如下:

1.2.2 最终使用

我们先看最终使用情况:

int main()
{
​	Strategy *strategy =  new Strategy(ROBOSENSE16); //接口类和实现类
  LidarProcess lidarProcess(strategy);
	// 上面两句可以合成一句  LidarProcess lidarProcess(new Strategy(ROBOSENSE16));
​	lidarProcess->process(msg); //msg 为激光雷达的数据结构
} 

1.2.3 接口类(策略定义)

接口(策略)类要做成纯虚类:

class  Stategy  {virtual int lidarPreprocess(const sensor_msgs::PointCloud2::ConstPtr &msg);	
}

1.2.4 使用类

使用类,这部分是不会改变的,有两点要求
第一:要包含接口类作为成员变量,构造函数要传入接口类对其初始化;
第二:类中应有方法,可操作接口类的方法,完成动态绑定。

class LidarProcess  {
​	Stategy  *stategy ;//void LidarProcess( StrategyFactory *strategyFactory){	 也可以用工厂方法生成对象//this->stategy = strategyFactory.creat(); //}void LidarProcess( Stategy *stategy){this->stategy = stategy;}void process(const sensor_msgs::PointCloud2::ConstPtr &msg  ){
		if(stategy!= nullptr)) //通常要判断是不是为空。
​		    stategy->lidarPreprocess(const sensor_msgs::PointCloud2::ConstPtr &msg);}
}

最后是策略实现类,继承接口,重写对应的方法。



class OUST64lidar:Stategy
{virtual int lidarPreprocess(const sensor_msgs::PointCloud2::ConstPtr &msg) override{}

};

class VELO32:Stategy{virtual int lidarPreprocess(const sensor_msgs::PointCloud2::ConstPtr &msg) override{}

};



class ROBOSENSE16:Stategy{virtual int lidarPreprocess(const sensor_msgs::PointCloud2::ConstPtr &msg) override{}

};



 

1.3新激光雷达加入

1.新激光雷达加入,需要 新的类去继承Stategy,重写对应的函数

class NEWlidar:Stategy{virtual int lidarPreprocess(const sensor_msgs::PointCloud2::ConstPtr &msg) override{}
};
2.需要更改main函数的第一句,	
Strategy *strategy =  new Strategy(NEWlidar); //接口类和实现类

2 其他实例

//示例1
#include 
#include 
#include 

using namespace std;

//高层策略接口
class Strategy
{
public:
    virtual double CalcPrice(double  goodsPrice){return 0;}
};

//具体策略
//普通客户策略
class NormalCustomerStrategy : public Strategy
{
public:
    double CalcPrice(double  goodsPrice) override
    {
        //普通客户没有折扣
        std::cout<<"普通客户没有折扣"<<std::endl;
        return goodsPrice;
    }
};

//老客户策略
class OldCustomerStrategy : public Strategy
{
public:
    double CalcPrice(double  goodsPrice) override
    {
        //老客户 统一折扣5%
        std::cout<<"老客户折扣5%"<<std::endl;
        return goodsPrice * (1 - 0.05);
    }
};

//大客户策略
class LargeCustomerStrategy : public Strategy
{
    double CalcPrice(double  goodsPrice) override
    {
        //大客户 统一折扣10%
        std::cout<<"大客户折扣10%"<<std::endl;
        return goodsPrice * (1 - 0.1);
    }
};


//策略上下文
class Price
{
public:
    Price(Strategy* strategy) : pStrategy(strategy){}
    double Quote(double goodsPrice)
    {
        if(pStrategy != nullptr)
        {
            return pStrategy->CalcPrice(goodsPrice);
        }
        return 0;
    }
private:
    std::unique_ptr<Strategy> pStrategy {nullptr};
};
int main()
{
    {
        Price price(new NormalCustomerStrategy);
        double goodsPrice = price.Quote(100);
        std::cout<<"普通客户最终价:"<<goodsPrice<<std::endl;
    }

    {
        Price price(new OldCustomerStrategy);
        double goodsPrice = price.Quote(100);
        std::cout<<"老客户最终价:"<<goodsPrice<<std::endl;
    }

    {
        Price price(new LargeCustomerStrategy);
        double goodsPrice = price.Quote(100);
        std::cout<<"大客户最终价:"<<goodsPrice<<std::endl;
    }

    return 0;
}
//示例2
#include 
#include 
#include 

using namespace std;

//策略模式扩展方式
//1.扩展上下文:通过继承上下文方式,然后在子类中添加相关数据
//2.扩展策略算法:在具体策略算法中添加相关数据

//高层策略接口
class PayStrategy
{
public:
    //virtual void Pay(PayContext* pPayContext){} //c++ 没有反射 不能直接传入context 然后获取上下文相关数据 适用于扩展方式1
    virtual void Pay(const std::string& user, double money){}
};

//具体策略
//人民币现金支付
class RMBCashStrategy : public PayStrategy
{
public:
    void Pay(const std::string& user, double money) override
    {
        std::cout<<user<<"人民币现金支付:"<<money<<std::endl;
    }
};

//美元支付
class DollarCashStrategy : public PayStrategy
{
public:
    void Pay(const std::string& user, double money) override
    {
        std::cout<<user<<"美元现金支付:"<<money<<std::endl;
    }
};

//RMB账户支付 扩展方式2
class RMBAccountStrategy : public PayStrategy
{
private:
    std::string account;
public:
    RMBAccountStrategy(std::string account) : account(account){}
public:
    void Pay(const std::string& user, double money) override
    {
        std::cout<<user<<"RMB账户"<<account<<"支付:"<<money<<std::endl;
    }
};

//策略上下文
class PayContext
{
private:
    std::string user;
    double money;

public:
    PayContext(std::string user, double money, PayStrategy* payStrategy) : user(user), money(money), pPayStrategy(payStrategy){}

public:
    void PayNow()
    {
        if(pPayStrategy != nullptr)
        {
            return pPayStrategy->Pay(this->user, this->money);
        }
    }

private:
    std::unique_ptr<PayStrategy> pPayStrategy {nullptr};
};


int main()
{
    {
        PayContext* payContext = new PayContext("张三", 100.0, new RMBCashStrategy());
        payContext->PayNow();
    }

    {
        PayContext* payContext = new PayContext("petter", 200.0, new DollarCashStrategy());
        payContext->PayNow();
    }

    {
        PayContext* payContext = new PayContext("李四", 300.0, new RMBAccountStrategy("123456789"));
        payContext->PayNow();
    }
    return 0;
}

你可能感兴趣的:(个人日记,设计模式学习,设计模式,策略模式)