egret+java小游戏服务端03重构pojo类(简单工厂+单一职责接口)


前言

前面构建整个架构的时候没有设定Player的抽象接口,玩家的指令解析后调用的方法也不是Player中的函数,这对后续的维护和扩展非常不友好。
由于player由Room类中的players存放,因此所有IPlayer均不作为Spring的Component使用


一、重构pojo接口及实现类

1.抽象底层IPlayer接口

public interface IPlayer extends Runnable {

    public void move(Instruct instruct);
    public void moveOut(Instruct instruct);

}

每个Player对象都实现了Runnable接口用于需要长时间调用的函数(如跑动等)的线程的创建。

INormalPlayer

public interface INormalPlayer extends IPlayer {
}

IPolice

//警察接口
public interface IPolice extends IPlayer {

    //射击
    public void shut(Instruct instruct);

    //抓捕
    public void arrest(Instruct instruct);
}

Thief

//小偷接口
public interface IThief extends IPlayer {
    //偷窃
    public void steal(Instruct instruct);
}

2.实现类

public class PlayerPeople implements IPlayer {

    private double x;
    private double y;
    private int uid;
    private int token;
    private boolean move = false;
    private double angle;
    private float speed = 30;
    private long time;

    public PlayerPeople(double x, double y, int uid, int token, boolean move, double angle, float speed) {
        this.x = x;
        this.y = y;
        this.uid = uid;
        this.token = token;
        this.move = move;
        this.angle = angle;
        this.speed = speed;
    }

    @Override
    public void move(Instruct instruct) {
        if (this.move != true) {
            this.move = true;
            //新建一个线程
            new Thread(this).start();//后续重构改为线程池...
        }else {
            //跑动线程已存在不需要再创建

        }
        this.time = System.currentTimeMillis();//由于前后端时间差过大,这里先设为当前时间
        this.angle = (double) instruct.getObj();
    }

    @Override
    public void moveOut(Instruct instruct) {
        this.move = false;
    }

    @Override
    public void run() {
        //这里执行需要长期计算的指令逻辑(如跑动等)

        //("跑动线程")
        long timeDiffer = 0;
        while(this.move){
            try {
                Thread.sleep(3);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            synchronized ((Long)time) {
                timeDiffer = System.currentTimeMillis() - time;
                time = System.currentTimeMillis();
                this.x = (this.x + (timeDiffer * this.speed * 0.1F * Math.sin(Math.PI / 180 * this.angle)));
                this.y = (this.y - (timeDiffer * this.speed * 0.1F * Math.cos(Math.PI / 180 * this.angle)));
            }
        }

    }
}

这里仅给出PlayerPeople的实现类,其他的实现类暂时都继承于该类并实现其对应的接口
例如

public class Police extends PlayerPeople implements IPolice {

    public Police(double x, double y, int uid, int token, boolean move, double angle, float speed) {
        super(x, y, uid, token, move, angle, speed);
    }

    @Override
    public void shut(Instruct instruct) {

    }

    @Override
    public void arrest(Instruct instruct) {

    }
}

二、简单工厂模式创建Player

1.创建Player枚举类型

public enum Players {

    NormalPlayer(30),
    Police(60),
    Thief(100);

    //选择中的几率(前减后)
    private int probability;
    private static Random random = new Random();
    Players(int probability) {
        this.probability = probability;
    }

    public static Players getRandomPlayer() {
        int r = random.nextInt(99)+1;
        for (Players p : values()){
            if (p.probability > r){
                return p;
            }
        }
        //如果失败了则随机返回
        return values()[random.nextInt(values().length)];
    }

}

这里玩家身份随机生成,逻辑如代码所示。

2.创建PlayerFactory工厂类

//简单工厂创建Player
public class PlayerFactory {
    public static IPlayer createPlayer(Class<? extends IPlayer> clazz)
            throws IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchMethodException {
        return (IPlayer) clazz.getDeclaredConstructor().newInstance();
    }
}

传入的是一个Class类对象

3.在MsgManage中调用工厂创建

public static void join(Instruct instruct){
        //在Room里面加入...
        try {
            Class clazz = Class.forName(Players.getRandomPlayer().toString());
            Room.players.put(instruct.getUid() + "" , PlayerFactory.createPlayer(clazz));
        }catch (Exception e){
            System.out.println("随机生成Player异常");
        }
    }

总结

1.使用枚举类型保存所有的玩家身份类型,并通过静态方法随机生成一个玩家身份。
2.使用工厂模式生成单一职责的接口继承类,符合代码开闭原则,对后续玩家身份的扩展有很大的进步。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值