zoukankan      html  css  js  c++  java
  • 策略模式(Strategy)

    1、作用

    策略模式的主要目的主要是将算法的定义(strategy类)和使用分开(context类),也就是将算法的行为和环境分开,将算法的定义放在专门的策略类中,每一个策略类封装一个实现算法。而使用算法的环境中针对抽象策略编程,而不是针对实现编程,符合依赖倒置原则。

    2、实现方式

    策略模式包含以下3个角色:

      (1)Context(环境类):负责使用算法策略,其中维持了一个抽象策略类的引用实例。

      (2)Strategy(抽象策略类):所有策略类的父类,为所支持的策略算法声明了抽象方法。=> 既可以是抽象类也可以是接口

      (3)ConcreteStrategy(具体策略类):实现了在抽象策略类中声明的方法。

    比如要开发一个电影售票系统,将这个系统封装为MovieTicket类,售票系统要使用一些打折的策略,如果把这些打折的策略实现在MovieTicket类中,那么如果增加或者修改打折策略就需要修改MovieTicket类。使用策略模式,那么就把MovieTicket当做使用算法的类(Context类),而将策略抽象成一个DiscountStrategy类,MovieTicket类依赖于DiscountStrategy类进行编程,这样继承于DiscountStragegy类的具体策略类有修改或者新增不需要修改MovieTicket类。

    优点:

          这里主要的好处是对MovieTicket中使用的策略满足的开闭原则

    缺点:

      对于使用MovieTicket这个类的用户就不友好了,他需要具体有哪些策略,将策略的选择留给了用户,增加了用户代码的复杂度(扩展性、使用灵活性就要付出代付复杂的代价。)

    这个例子对应的UML图:

    3、C++代码

    Discount.h

    #include <iostream>
    #include <memory>   // shared_ptr
    
    #ifndef __DISCOUNT__H__
    #define __DISCOUNT__H__
    
    using namespace std;
    
    
    class DiscountStrategy {                                         // 策略的抽象基类,定义接口。有的像模板模式的模板,但模板模式定义死了一个模板函数。
        public:
            virtual float getPrice(float originalPrice) = 0;
    };
    
    class ChildrenDiscount : public DiscountStrategy {               // 扩展的一种打折策略,小孩打折————免费。
        public:
            float getPrice(float originalPrice) override {
                return 0;
            }
    
            ~ChildrenDiscount() { cout<<"distroy ChildrenDiscount..."<<endl; }
    };
    
    class StudentDiscount : public DiscountStrategy {               // 扩展的一种打折策略,学生打折————半价。
        public:
            float getPrice(float originalPrice) override {
                return originalPrice * 0.5;
            }
    
            ~StudentDiscount() { cout<<"distroy StudentDiscount...."<<endl; }
    };
    
    class VIPDiscount : public DiscountStrategy {                   // 扩展的一种打折策略,会员打折————8折。
        public:
            float getPrice(float originalPrice) override {
                return originalPrice * 0.8;
            }
    
            ~VIPDiscount() { cout<<"distroy VIPDiscount...."<<endl; }
    };
    
    
    
    
    class MovieTicket {
        public:
            MovieTicket(shared_ptr<DiscountStrategy> discount) : discountStrategy(discount) {}
    
            void setDiscountStrategy(shared_ptr<DiscountStrategy> discount) {
                discountStrategy = discount;
            }
            float discount(float originalPrice) {
                return discountStrategy->getPrice(originalPrice);
            }
        private:
            shared_ptr<DiscountStrategy> discountStrategy;
    };
    
    
    #endif

    test.cc

    #include <iostream>
    #include <memory>
    #include "Discount.h"
    
    int main() {
        shared_ptr<DiscountStrategy> discountStrategy = make_shared<StudentDiscount>();
        MovieTicket movieTicket(discountStrategy);                                                      // 在对电影票使用学生票的打折策略
        double originalPrice = 100;
        double discountPrice = movieTicket.discount(originalPrice);
        cout<<"StudentDiscount: originalPrice="<<originalPrice<<", discountPrice="<<discountPrice<<endl;
    
        movieTicket.setDiscountStrategy(make_shared<ChildrenDiscount>());                               // 在对电影票使用儿童票的打折策略
        discountPrice = movieTicket.discount(originalPrice);
        cout<<"ChildrenDiscount: originalPrice="<<originalPrice<<", discountPrice="<<discountPrice<<endl;
    
        movieTicket.setDiscountStrategy(make_shared<VIPDiscount>());                                    // 在对电影票使用会员票的打折策略
        discountPrice = movieTicket.discount(originalPrice);
        cout<<"VIPDiscount: originalPrice="<<originalPrice<<", discountPrice="<<discountPrice<<endl;
    
        return 0;
    }

    输出:

    在这个例子中,MovieTicket类要保存一个DiscountStrategy的一个指针,为了好管理指针,这里使用了智能指针,省去了指针的复杂管理。

  • 相关阅读:
    C++ 11 :override 关键字的使用
    vsphere部署说明
    Windows 下部署Subversion
    Centos 7 最小化部署zabbix
    在vmware中安装mac os
    如何将OS dmg文件制作成U盘启动
    HDU1518(dfs)java/ c++
    HDU1010(bfs)
    HDU1495(bfs)
    HD1285(拓扑排序)
  • 原文地址:https://www.cnblogs.com/yuandonghua/p/11907910.html
Copyright © 2011-2022 走看看