策略模式

18次阅读

共计 914 个字符,预计需要花费 3 分钟才能阅读完成。

简介

策略模式,定义了一个算法族,并且封装了每一个算法,使它们可以互相替换。策略模式让算法与使用它的客户端独立的变化。

UML 类图

示例

策略模式比较常见。人总要学习,正如在开篇中所说,通过读可以,写效果更好,能够通过分享或者教会别人可能会更有效。
策略相关类,strategy.h

#ifndef STRATEGY_H
#define STRATEGY_H
#include <iostream>

using namespace std;
class CLearning
{
public:
    virtual void Learn() = 0;};

class CReading:public CLearning
{
public:
    void Learn()
    {cout<<"Learn by Reading."<<endl;}
};

class CWriting:public CLearning
{void Learn()
    {cout<<"Learn by Writing."<<endl;}
};

class CTeaching:public CLearning
{void Learn()
    {cout<<"Learn by Teaching."<<endl;}
};

class CLearningContext
{
public:
    CLearningContext(CLearning* pLearning)
    {m_pLearning = pLearning;}
    void Learn()
    {m_pLearning->Learn();
    }
private:
    CLearning* m_pLearning;
};
#endif

客户端调用,main.cpp

#include "strategy.h"

#define SAFE_DELETE(p) if(p){delete (p); (p) = NULL;}
int main(int argc, char* argv[])
{
    CWriting* pWriting = new CWriting;
    CLearningContext* pContext = new CLearningContext(pWriting);
    pContext->Learn();
    SAFE_DELETE(pWriting);
    SAFE_DELETE(pContext);
    return 0;
}

正文完
 0

策略模式

18次阅读

共计 1287 个字符,预计需要花费 4 分钟才能阅读完成。

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

  • 系统有很多类,而它们的区别仅仅在于它们的行为不同
  • 一个系统需要动态地在几种算法中选择一种

优点

  • 开闭原则
  • 避免使用多重条件转移语句(if…else…,switch)
  • 提高算法的保密性和安全性

缺点:

  • 客户端必须知道所有的策略类,并自行决定使用哪一个策略类。
  • 产生很多策略类

案例

某知识平台的教学视频促销(满减、立减、返现)

促销策略接口

public interface PromotionStrategy {void doPromotion();
}

返现策略

public class FanXianPromotionStrategy implements PromotionStrategy{
    @Override
    public void doPromotion() {System.out.println("返现促销, 返回的金额存放到慕课网用户的余额中");
    }
}

立减策略

public class LiJianPromotionStrategy implements PromotionStrategy {
    @Override
    public void doPromotion() {System.out.println("立减促销, 课程的价格直接减去配置的价格");
    }
}

满减策略

public class ManJianPromotionStrategy implements PromotionStrategy{
    @Override
    public void doPromotion() {System.out.println("满减促销, 满 200-20 元");
    }
}

促销活动

public class PromotionActivity {
    private PromotionStrategy promotionStrategy;

    public PromotionActivity(PromotionStrategy promotionStrategy) {this.promotionStrategy = promotionStrategy;}

    public void executePromotionStrategy(){promotionStrategy.doPromotion();
    }

}
public class Test {public static void main(String[] args) {PromotionActivity promotionActivity618 = new PromotionActivity(new LiJianPromotionStrategy());
        PromotionActivity promotionActivity1111 = new PromotionActivity(new FanXianPromotionStrategy());

        promotionActivity618.executePromotionStrategy();
        promotionActivity1111.executePromotionStrategy();}
}

结果:

正文完
 0

策略模式

18次阅读

共计 1220 个字符,预计需要花费 4 分钟才能阅读完成。

设计原则

找出应用中可能需要变化之处,把它们独立出来,不要和哪些那些不需要变化的代码混在一起。

面向接口编程,而不是面向实现编程。面向接口编程,真正的意思是面对超类型 (supertype) 编程,即“变量”的声明类型应该是超类型,通常是一个抽象类或者是一个接口。这样,只要是 具体实现此超类型的类所产生的对象,都可以指定给这个变量。这也意味着声明类时不用理会以后执行的真正的对象类型。
多用组合,少用继承。

定义
​ 定义了算法族(把具有相同特性的行为看作一族算法,比如鸭子的飞,不同的飞法即不同的算法),分别封装起来,让他们之间可以相互替换,此模式让算法的变化独立于使用算法的客户。
​ 根据相同特性的行为族创建 supertype(接口或者抽象类),然后根据 supertype 构建出具体实现类。在需要该特性的客户基类中加入 supertype 的实例变量,然后根据子类所需要的行为的不同在子类构造器中为该变量赋予不同的具体实现类对象(根据 supertype 构建),也可以在基类中加入实例变量的 set 方法,那么就可以在运行时动态设定行为了(即通过 set 赋予不同的行为实例)。
实现方式

定义 Strategy 和 Context 接口。Strategy 和 Context 接口必须使得 ConcreteStrategy 能够有效的访问它所需要的 Context 中的任何数据,反之亦然。一种办法是让 Context 将数据放在参数中传递给 Strategy 操作—也就是说,将数据发送给 Strategy。这使得 Strategy 和 Context 解耦。但另一方面,Context 可能发送一些 Strategy 不需要的数据。
另一种办法是让 Context 将自身作为一个参数传递给 Strategy,该 Strategy 再显式地向该 Context 请求数据。或者,Strategy 可以存储对它的 Context 的一个引用,这样根本不再需要传递任何东西。这两种情况下,Strategy 都可以请求到它所需要的数据。但现在 Context 必须对它的数据定义一个更为精细的接口,这将 Strategy 和 Context 更紧密地耦合在一起。

使 Strategy 对象成为可选的。如果即使在不使用额外的 Strategy 对象的情况下,Context 也还有意义的话,那么它还可以被简化。Context 在访问某 Strategy 前先检查它是否存在,如果有,那么就使用它;如果没有,那么 Context 执行缺省的行为。这种方法的好处是客户根本不需要处理 Strategy 对象,除非它们不喜欢缺省的行为。比如 TreeSet 类型的对象在创建时可以选择传入 Comparator 对象也可以传入,这就是策略模式的一个例子。

什么时候使用策略模式
​ 解决类直接实现接口造成的方法具体代码不能复用可以考虑采用策略模式,更本质的讲,是想要设计出可复用、可扩展的行为族时。在这里的族可以是根据一个 (抽象) 基类来创建,也可以像是本例中根据一个接口 FlyBehavior 来创立。

正文完
 0