状态模式和策略模式

状态模式和策略模式

策略模式,简而言之就是解决某个问题的方法。最近在玩原神,而原神由于其氪金机制和各种运行操作使得网上风评不高,而从玩家大体上分为3类:氪金大佬、中小氪和白嫖。而从策略模式分析,为了去抽到角色和武器需要解决方法,而方法分为三种:直接648、氪金+小肝、直接肝报废。而在其中有很多相同的地方,比如消耗相同、肝的方式相同等等。而策略模式就是将一个算法架构放于基类,减少代码重复,之后将某些待拓展点抽象化或者多态操作,使得拓展方便,并且不需要修改基类的算法架构。

状态模式,用来实现状态变化的操作。比如你小时候是4条腿走路、青年是2条、老年是3条,像这样的实现可能比较简单,一个判断分支就行了,可是由于状态变化的时候,可能随之改变的东西很多,比如年纪、身体状况、经济、家庭情况等等,这样的状态变化的情况就可能仅仅使用判断语句了,因此出现状态模式,简而言之,状态模式就是用处理当一个东西的状态改变的时候,数据或者操作变化太过于复杂的时候所用的一种易拓展模式。

基础UML

 

 

策略模式

状态模式

Strategy/State

抽象基础类,大部分情况存储一个算法的共同数据和函数。比如基本价格等等

状态抽象类,大部分情况下存储抽象的共同函数,比如状态下的处理函数

ConcreateXXXX

实际算法节点实现类。当算法中的一些方法节点需要拓展的时候,将节点归类为另外一个方法而派生为一个子类

具体状态实现类。

将东西的状态分离,实现每个状态下需要存储的数据或者进行的操作

Context/Handle

外部的接口类。

使用场景

当一系列类存在很多的相同点,只有一些行为不同的时候

当不同的情况需要动态的使用不同的节点处理方式的时候

状态变化的时候,行为或者数据随之变化的时候

当可能存在分支很庞大的时候,同来替代

优点

可以自由切换算法的某些行为

避免了可能的多条件判断

易拓展

可以用枚举方式省掉许多指针或者对象的传递

每个状态一个类去实现自己需要的行为,易拓展

在使用的时候,可以将不同的变量使用同一个状态类, 减少了类。比如长大状态,涉及到许多因素。

缺点

当方法很多的时候,会导致类比较多

由于客户端使用的方法,会导致所以的类暴露,因此常用中间控件来进行限制

结构和行为比较复杂,因此需要使用仔细

部分支持“开发封闭”,因为可能导致有些地方需要修改

相同点

易拓展

常用中间件在类组和用户之间减少操作和权限设置

差异点

常用于共同点较多的情况,子类只是实现某些特定需求

目的是为在不同的要求下是用不同的方法

常用于状态变化的时候,涉及到的数据或者方法变化过大的情况

目的是为了减少状态变化后导致随之变化太过复杂的情况

实操

UML

 

关于两个模式的思维方式其实大致相同:

1.分析

策略模式:主要分析那些是可共享的,那些是不可共享

状态模式:主要分析分成那些状态,而对应状态的行为、数据是什么

2.继承和派生

只需要先单一的实现基类和派生类就行了

3.中间类的设定

在写完类组之后,会发现客户端使用比较麻烦,因此给定中间状态,设定权限和简化操作等等

4.看是否需要支持自动跳转

看是否需要用责任链的方式,实现状态自动选择的情况

 

而策略模式和状态模式在实现、uml大致是相同的,不同的在于关注点不同:

策略主要关注方法和行为的多种

状态主要关注变化时操作和行为变化太复杂

策略模式代码

// StrategyModel.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include <iostream>
using namespace std;
#define  interface struct

interface IKillBoss
{
public:
    virtual void ToKillBoss() = 0;
};
class CKillStrategyA:public IKillBoss
{
public:
    void ToKillBoss()
    {
        cout << "屠龙宝刀,只卖999,任何boss不用愁!" << endl;
    }
};
class CKillStrategyB :public IKillBoss
{
public:
    void ToKillBoss()
    {
        cout << "白色大剑 + 普通的肝 , 小氪 +肝,慢慢打穿。" << endl;
    }
};
class CKillStrategyC :public IKillBoss
{
public:
    void ToKillBoss()
    {
        cout << "七彩大腰子 , 只要还没肝硬化,那个boss都不怕。" << endl;
    }
};

class CKillStrategyChoose
{
private:
    IKillBoss* m_kill;
public:
    CKillStrategyChoose(int num)
    {
        if (0 == num)
        {
            m_kill = new CKillStrategyA();
        }
        else if (1 == num)
        {
            m_kill = new CKillStrategyB();
        }
        else if (2 == num)
        {
            m_kill = new CKillStrategyC();
        }
    }
    void KillStrategy()
    {
        if (m_kill)
            m_kill->ToKillBoss();
    }
};

int main()
{
    CKillStrategyChoose kill1(0);
    kill1.KillStrategy();

    CKillStrategyChoose kill2(1);
    kill2.KillStrategy();

    CKillStrategyChoose kill3(2);
    kill3.KillStrategy();
}

状态模式代码

// StateModel.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include <iostream>
using namespace std;

class CWalk;

class IPeopleState
{
public:
    virtual void howToWalk(CWalk *walk) = 0;
};

class COldState :public IPeopleState
{
    void howToWalk(CWalk *walk)
    {
        cout << "老人用3条腿走路。" << endl;
    }
};

class CYoungState:public IPeopleState
{
    void howToWalk(CWalk *walk)
    {
        cout << "青年人用2条腿走路。" << endl;
    }
};

class CChildState :public IPeopleState
{
public:
    void howToWalk(CWalk *walk)
    {
        cout << "小孩用4条腿走路。" << endl;
    }
};

class CWalk
{
private:
    IPeopleState* m_state;
    int m_age;
public:
    CWalk()
    {
        m_state = NULL;
        m_age = 0;
    }

    int getAge() { return m_age; }
    void setAge(int age) { m_age = 0; }

    void setState(IPeopleState* state) { m_state = state; }

    void  toWalk() { m_state->howToWalk(this); }
};

int main()
{
    IPeopleState* state1 = new CChildState();
    IPeopleState* state2 = new CYoungState();
    IPeopleState* state3 = new COldState();

    CWalk *walk = new CWalk();
    walk->setState(state1);
    walk->toWalk();
    walk->setState(state2);
    walk->toWalk();
    walk->setState(state3);
    walk->toWalk();
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值