zoukankan      html  css  js  c++  java
  • java游戏服务器 策略+简单工厂

    上一篇中我们讲到简单工厂模式有它的弊端,它不好在哪里呢?
    我们看到,每次创建场景,我们都需要暴露两个类。。。
    这是比较不好的,
    可以通过策略模式+简单工厂模式来稍微改造下

    一.先来一个策略模式UML图(大话设计模式)

    • Strategy:所有策略的基类
    • StrategyA、StrategyB、StrategyC:三个策略子类
    • Context:上下文,包含一个父类Strategy引用,指向具体的子类策略对象(聚合关系)


    二.接下来我们以游戏服务端开发里的生活技能来讲解。这个需求非常适合策略模式。
    这里简化下需求:
    游戏里生活技能为采集(采矿、采药...)和合成(烹饪、铸造...)两大类。

    我们稍微改造下UML图:
    1.有一个Context上下文类:
    LifeSkillContext2

    2.有一个strategy抽象类:
    /**
    * 生活技能策略基类
    * 基类,所以是抽象类,方便子类去不同的实现
    * @author lizhibiao
    * @date 2019/1/10 21:18
    */
    public abstract class AbstractLifeSkillLogic

    3.有一个StrategyA子类(这里我们把它也设计为抽象类)
    /**
    * 采集抽象类
    * 这里是抽象类,是因为采集包括采矿、采药。。。
    * 方便子类覆写
    * @author lizhibiao
    * @date 2019/1/10 21:30
    */
    public abstract class AbstractAbilityCollectLogic extends AbstractLifeSkillLogic

    4.有一个StrategyB子类(这里我们把它也设计为抽象类)
    /**
    *
    * 合成类
    * 这里把合成类,也定义为抽象类是因为合成类包括(烹饪、铸造...)
    * 方便子类覆写
    * @author lizhibiao
    * @date 2019/1/10 21:23
    */
    public abstract class AbstractAbilityComposeLogic extends AbstractLifeSkillLogic


    5.StrategyA类下面挂两个子类分别是采矿和采药
    /**
    * 采矿
    * 继承采集抽象类
    * @author lizhibiao
    * @date 2019/1/11 14:26
    */
    public class AbilityMining extends AbstractAbilityCollectLogic
    /**
    * 采药
    * 继承采集抽象类
    * @author lizhibiao
    * @date 2019/1/11 14:30
    */
    public class AbilityHerbs extends AbstractAbilityCollectLogic

    6.同理StrategyB类下面也挂两个子类分别是烹饪和铸造
    /**
    *
    * 烹饪
    * 继承合成抽象类
    * @author lizhibiao
    * @date 2019/1/11 14:37
    */
    public class AbilityCooking extends AbstractAbilityComposeLogic
    /**
    * 铸造类
    * 继承合成抽象类
    * @author lizhibiao
    * @date 2019/1/11 14:43
    */
    public class AbilityCasting extends AbstractAbilityComposeLogic



    三:依次开始上代码
    /**
    *
    * 生活技能上下文2
    * @author lizhibiao
    * @date 2019/1/11 15:23
    */
    public class LifeSkillContext2
    {
    private AbstractLifeSkillLogic abstractLifeSkillLogic = null;

    public LifeSkillContext2(LifeSkillTypeEnum typeEnum)
    {
    switch (typeEnum)
    {
    case MINING:
    abstractLifeSkillLogic = new AbilityMining();
    break;
    case HERBS:
    abstractLifeSkillLogic = new AbilityHerbs();
    break;
    case COOKING:
    abstractLifeSkillLogic = new AbilityCooking();
    break;
    case CASTING:
    abstractLifeSkillLogic = new AbilityCasting();
    break;
    default:
    break;
    }
    }

    public AbstractLifeSkillLogic getAbstractLifeSkillLogic()
    {
    return abstractLifeSkillLogic;
    }
    }

    /**
    * 生活技能策略基类
    * 基类,所以是抽象类,方便子类去不同的实现
    * @author lizhibiao
    * @date 2019/1/10 21:18
    */
    public abstract class AbstractLifeSkillLogic
    {

    /**
    * 使用生活技能操作
    * 抽象方法
    */
    public abstract void lifeSkillOperate();



    }



    /**
    * 采集抽象类
    * 这里是抽象类,是因为采集包括采矿、采药。。。
    * 方便子类覆写
    * @author lizhibiao
    * @date 2019/1/10 21:30
    */
    public abstract class AbstractAbilityCollectLogic extends AbstractLifeSkillLogic
    {

    @Override
    public void lifeSkillOperate()
    {
    System.out.println("执行采集共有操作------操起镰刀,动手");
    }

    }

    /**
    *
    * 合成类
    * 这里把合成类,也定义为抽象类是因为合成类包括(烹饪、铸造...)
    * 方便子类覆写
    * @author lizhibiao
    * @date 2019/1/10 21:23
    */
    public abstract class AbstractAbilityComposeLogic extends AbstractLifeSkillLogic
    {

    @Override
    public void lifeSkillOperate()
    {
    System.out.println("执行合成公有操作----------烹饪和铸造先点火。。。");
    }

    }


    /**
    * 采矿
    * 继承采集抽象类
    * @author lizhibiao
    * @date 2019/1/11 14:26
    */
    public class AbilityMining extends AbstractAbilityCollectLogic
    {
    @Override
    public void lifeSkillOperate()
    {
    super.lifeSkillOperate();

    System.out.println("我是采矿--------采矿。。采矿。。。");
    }
    }
    /**
    * 采药
    * 继承采集抽象类
    * @author lizhibiao
    * @date 2019/1/11 14:30
    */
    public class AbilityHerbs extends AbstractAbilityCollectLogic
    {
    @Override
    public void lifeSkillOperate()
    {
    super.lifeSkillOperate();

    System.out.println("我是采药-------采药。。采药。。");
    }
    }




    /**
    *
    * 烹饪
    * 继承合成抽象类
    * @author lizhibiao
    * @date 2019/1/11 14:37
    */
    public class AbilityCooking extends AbstractAbilityComposeLogic
    {

    @Override
    public void lifeSkillOperate()
    {
    super.lifeSkillOperate();

    System.out.println("我是烹饪----烹饪。。烹饪。。");

    }

    }
    /**
    * 铸造类
    * 继承合成抽象类
    * @author lizhibiao
    * @date 2019/1/11 14:43
    */
    public class AbilityCasting extends AbstractAbilityComposeLogic
    {
    @Override
    public void lifeSkillOperate()
    {
    super.lifeSkillOperate();

    System.out.println("我是铸造----铸造。。铸造。。");
    }
    }



    四:接下来,我们开始测试
    1.添加一个枚举类,如下:
    /**
    * 生活技能枚举类
    * @author lizhibiao
    * @date 2019/1/11 14:52
    */
    public enum LifeSkillTypeEnum
    {
    /**
    * 采矿
    */
    MINING,

    /**
    * 采药
    */
    HERBS,

    /**
    * 烹饪
    */
    COOKING,

    /**
    * 铸造
    */
    CASTING

    }


    2.开始测试
    //采矿  注意这里只暴露一个LifeSkillContext2类
    LifeSkillContext2 context = new LifeSkillContext2(LifeSkillTypeEnum.MINING);
    AbstractLifeSkillLogic mining = context.getAbstractLifeSkillLogic();
    if (null != mining)
    {
    mining.lifeSkillOperate();
    }

    System.out.println();

    //烹饪 注意这里只暴露一个LifeSkillContext2类
    LifeSkillContext2 context2 = new LifeSkillContext2(LifeSkillTypeEnum.COOKING);
    AbstractLifeSkillLogic cooking = context2.getAbstractLifeSkillLogic();
    if (null != cooking)
    {
    cooking.lifeSkillOperate();
    }
    看到没,
    确实是只暴露了一个类
    输出结果:

    但是这也是有弊端的,你发现我们每次都需要new一个上下文类,这样效率太低了。


    3.我们来改造下
    新建一个上下文类:
    **
    *
    * 生活技能上下文
    * @author lizhibiao
    * @date 2019/1/10 21:08
    */
    public class LifeSkillContext
    {
    private static AbstractLifeSkillLogic abstractLifeSkillLogic = null;


    public static int setLifeSkillLogic(LifeSkillTypeEnum typeEnum)
    {
    //先置null
    abstractLifeSkillLogic = null;

    switch (typeEnum)
    {
    case MINING:
    abstractLifeSkillLogic = new AbilityMining();
    return 0;
    case HERBS:
    abstractLifeSkillLogic = new AbilityHerbs();
    return 0;
    case COOKING:
    abstractLifeSkillLogic = new AbilityCooking();
    return 0;
    case CASTING:
    abstractLifeSkillLogic = new AbilityCasting();
    return 0;
    default:
    return -1;
    }
    }

    public static AbstractLifeSkillLogic getLifeSkillLogic()
    {
    return abstractLifeSkillLogic;
    }
    }

    测试类如下:
    /**
    * 测试类
    * @author lizhibiao
    * @date 2019/1/11 15:05
    */
    public class Main
    {
    private static final int SUCESSED = 0;

    public static void main(String[] args)
    {
    //采矿
    int result = LifeSkillContext.setLifeSkillLogic(LifeSkillTypeEnum.MINING);
    if (result == SUCESSED)
    {
    LifeSkillContext.getLifeSkillLogic().lifeSkillOperate();
    }

    System.out.println();

    //烹饪
    result = LifeSkillContext.setLifeSkillLogic(LifeSkillTypeEnum.COOKING);
    if (result == SUCESSED)
    {
    LifeSkillContext.getLifeSkillLogic().lifeSkillOperate();
    }

    }
    }

    测试结果如下:


    看到没,这里我们只需要暴露一个LifeSkillContext类,并且我们不需要每次都去new一个上下文!!


  • 相关阅读:
    SVN与TortoiseSVN实战:标签与分支
    IOS性能调优系列:使用Zombies动态分析内存中的僵尸对象
    IOS性能调优系列:使用Allocation动态分析内存使用情况
    IOS性能调优系列:使用Instruments动态分析内存泄漏
    IOS性能调优系列:Analyze静态分析
    2014年个人知乎收藏夹整理
    IOS开发环境更换后重新制作Provisioning Profile证书详解
    使用VS2010编译MongoDB C++驱动详解
    ACE服务端编程1:使用VS2010编译ACE6.0及从ACE5.6升级的注意事项
    std::string在多字节字符集环境下substr的实现方法
  • 原文地址:https://www.cnblogs.com/lizb0907/p/10256876.html
Copyright © 2011-2022 走看看