• 设计模式2:策略模式


    例子来源于《大话设计模式》第二章。

    策略模式的作用:封装算法

    在简单工厂模式中,客户端需要认识两个类,分别是工厂类和抽象方法类。而在策略模式里,客户端只需要认识一个类,就是context类。因此,策略模式比简单工厂模式对算法的封装更加彻底。在

    在学习一个设计模式的时候,一定要理解它的UML图,这对设计模式的理解很重要。

    strategy.h

     1 #include<iostream>
     2 using namespace std;
     3 //抽象方法类---现金收费
     4 class CashSuper
     5 {
     6     public:
     7     virtual double acceptcash(double money)=0;//纯虚函数
     8 };
     9 //具体方法类-普通方式
    10 class CashNormal:public CashSuper
    11 {
    12     public:
    13     double acceptcash(double money)
    14     {
    15         return money;
    16     }
    17 };
    18 //具体方法---打折
    19 class CashRebate:public CashSuper
    20 {
    21 private:
    22     double discount;
    23 public:
    24     CashRebate(double discount)//构造函数。构造函数可以有参数,但是不能有返回值,void类型都不行
    25                                //在初始化的时候,传入具体的策略对象
    26     {
    27         this->discount=discount;
    28     }
    29     double acceptcash(double money)
    30     {
    31         return money*discount;
    32     }
    33 };
    34 //具体方法--满减
    35 //满减是针对总共的价格来讲的
    36 class CashReturn:public CashSuper
    37 {
    38     private:
    39     double moneycondition;
    40     double moneyreturn;
    41     public:
    42     
    43     CashReturn(double moneycondition,double moneyreturn)//构造函数,这个必须写,可以参考cashcontext.h里对这个类的调用
    44                                                         //在cashcontext.h里对它的调用有两个参数
    45                                                         //因为后面要new一个对象,并且给对象赋初值,所以必须写带参数的构造函数来调用
    46     {
    47         this->moneycondition=moneycondition;
    48         this->moneyreturn=moneyreturn;
    49     }
    50     double acceptcash(double money)
    51     {
    52         double result=money;
    53         if(money>=moneycondition)
    54         {
    55             result=money-money/moneycondition*moneyreturn;
    56         }
    57         return result;
    58     }
    59 };

    CashContext.h

     1 #include "strategy.h"
     2 //context类
     3 class CashFactory
     4 {
     5     CashSuper *cas;//子对象
     6 public:
     7     
     8     CashFactory(int type):cas(NULL)  
     9     //构造函数,通过初始化列表初始化数据成员
    10     //子对象的初始化方式
    11     //参数不是一个具体的收费策略的对象,而是一个表示收费类型的数字
    12     //为什么这里写的注释和别的地方不一样???
    13     {
    14         switch(type)
    15         {
    16             case 1:
    17             cas=new CashNormal();
    18             break;
    19             case 2:
    20             cas=new CashRebate(0.8);//打折方式
    21             break;
    22             case 3:
    23             cas=new CashReturn(200,100);//满减
    24             break;
    25             default:;
    26         }
    27     }
    28     ~CashFactory()//析构函数.没有参数,没有返回值,不能重载
    29                     //作用是释放使用完的指针内存空间
    30     {
    31         if(cas!=NULL)
    32         {
    33             delete cas;
    34             cas=NULL;
    35         }
    36     }
    37     double getresult(double money)
    38     {
    39         return cas->acceptcash(money);
    40     }
    41 };

    main.cpp

     1 #include"CashContext.h"
     2 #include<iostream>
     3 using namespace std;
     4 int main()
     5 {
     6     double totalprice=0.0;
     7     CashFactory *cash=NULL;//策略模式只需要建立context的对象
     8     cash=new CashFactory(2);//给新建的对象初始化
     9     totalprice=cash->getresult(300);//使用context的对象访问对应的算法,参考context函数
    10     cout<<totalprice;
    11     return 0;
    12 }

    构造函数:

    有两种:

    1.自己写出来,根据自己要建立的对象初始化的方式来写自己需要的构造函数,可以有参数,也可以没参数,但是一旦写了没有参数的系统就不会提供默认的构造函数。

    2.不写,系统会提供一个空的构造函数,里面什么都没有。但是这并不代表建立对象的时候不能将它初始化。

    按照c++书上的说法,如果有参数,并且想要参数随着自己建立对象的不同而变化,就必须写自己的构造函数。但是也不一定。具体看下面我写的。

    在c++中,建立一个对象,就必须调用构造函数。如果没有些构造函数,默认的构造函数不能对类中的成员初始化。但是,没有构造函数,公有的数据成员可以用初始值列表进行初始化。例如:

     1 class Myclass
     2 {
     3     public:
     4     int no;
     5     int year;
     6 };
     7 int main()
     8 {
     9     Myclass a={25,20};
    10     cout<<a.no<<endl;
    11     cout<<a.year<<endl;
    12     return 0;
    13 }

    但是对象的初始化如过写成

    Myclass a(25,24);

    就不行。

    原因是这种初始化只能调用默认的构造函数,但是默认的构造函数没有参数。同理,如果new一个对象并初始化也不可以。

  • 相关阅读:
    素数推断算法(高效率)
    Hibernate的fetch
    TRIZ系列-创新原理-22-变害为利原理
    Offer是否具有法律效力?
    浅谈C++多态性
    C语言scanf函数详解
    大话设计模式之原型模式
    Android源码文件夹结构
    简单的REST的框架实现
    android startActivityForResult的用法
  • 原文地址:https://www.cnblogs.com/neverland0718/p/11346473.html
Copyright © 2020-2023  润新知