首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在特定代码上实现单一责任原则

在特定代码上实现单一责任原则
EN

Stack Overflow用户
提问于 2016-11-14 09:24:20
回答 2查看 89关注 0票数 2

如何将这些代码分解为遵循单一责任原则?尽管我理解了SOLID principles,并且阅读了很多资料,特别是Bob叔叔关于SOLID principles的文章,但不幸的是,我无法将以下代码分成两个不同的类来遵循单一责任原则。我将非常感谢StackOverflow的帮助

/**是唯一充分利用实体超类的子类(没有其他类需要在基于瓦片的地图中移动)。包含与玩家关联的所有游戏。**/

代码语言:javascript
复制
package com.neet.DiamondHunter.Entity;

import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import com.neet.DiamondHunter.Manager.Content;
import com.neet.DiamondHunter.Manager.JukeBox;
import com.neet.DiamondHunter.TileMap.TileMap;
public class Player extends Entity {
    // sprites
    private BufferedImage[] downSprites;
    private BufferedImage[] leftSprites;
    private BufferedImage[] rightSprites;
    private BufferedImage[] upSprites;
    private BufferedImage[] downBoatSprites;
    private BufferedImage[] leftBoatSprites;
    private BufferedImage[] rightBoatSprites;
    private BufferedImage[] upBoatSprites;

    // animation
    private final int DOWN = 0;
    private final int LEFT = 1;
    private final int RIGHT = 2;
    private final int UP = 3;
    private final int DOWNBOAT = 4;
    private final int LEFTBOAT = 5;
    private final int RIGHTBOAT = 6;
    private final int UPBOAT = 7;

    // gameplay
    private int numDiamonds;
    private int totalDiamonds;
    private boolean hasBoat;
    private boolean hasAxe;
    private boolean onWater;
    private long ticks;

    // player status
    private int healthPoints;
    private boolean invincible;
    private boolean powerUp;
    private boolean speedUp;


    public Player(TileMap tm) {

        super(tm);

        width = 16;
        height = 16;
        cwidth = 12;
        cheight = 12;

        moveSpeed = 2;

        numDiamonds = 0;

        downSprites = Content.PLAYER[0];
        leftSprites = Content.PLAYER[1];
        rightSprites = Content.PLAYER[2];
        upSprites = Content.PLAYER[3];
        downBoatSprites = Content.PLAYER[4];
        leftBoatSprites = Content.PLAYER[5];
        rightBoatSprites = Content.PLAYER[6];
        upBoatSprites = Content.PLAYER[7];

        animation.setFrames(downSprites);
        animation.setDelay(10);

    }

    private void setAnimation(int i, BufferedImage[] bi, int d) {
        setAnimation(i, bi, d, false);
    }

    private void setAnimation(int i, BufferedImage[] bi, int d, boolean slowMotion) {
        currentAnimation = i;
        animation.setFrames(bi);
        animation.setDelay(d);
        slowMotion = true;
    }

    public void collectedDiamond() { numDiamonds++; }
    public int numDiamonds() { return numDiamonds; }
    public int getTotalDiamonds() { return totalDiamonds; }
    public void setTotalDiamonds(int i) { totalDiamonds = i; }

    public int getx() { return x; }
    public int gety() { return y; }
    public int getRow() { return rowTile; }
    public int getCol() { return colTile; }

    public void gotBoat() { hasBoat = true; tileMap.replace(22, 4); }
    public void gotAxe() { hasAxe = true; }
    public boolean hasBoat() { return hasBoat; }
    public boolean hasAxe() { return hasAxe; }

    public int getHealthPoints() { return healthPoints; }

    // Used to update time.
    public long getTicks() { return ticks; }

    // Keyboard input. Moves the player.
    public void setDown() {
        super.setDown();
    }
    public void setLeft() {
        super.setLeft();
    }
    public void setRight() {
        super.setRight();
    }
    public void setUp() {
        super.setUp();
    }

    // Keyboard input.
    // If Player has axe, dead trees in front
    // of the Player will be chopped down.
    public void setAction() {
        final boolean pressUPKEY = currentAnimation == UP && tileMap.getIndex(rowTile - 1, colTile) == 21;
        final boolean pressDOWNKEY = currentAnimation == DOWN && tileMap.getIndex(rowTile + 1, colTile) == 21;
        final boolean pressLEFTKEY = currentAnimation == LEFT && tileMap.getIndex(rowTile, colTile - 1) == 21;
        final boolean pressRIGHTKEY = currentAnimation == RIGHT && tileMap.getIndex(rowTile, colTile + 1) == 21;
        if(hasAxe) {
            if(pressUPKEY) {
                tileMap.setTile(rowTile - 1, colTile, 1);
            }
            if(pressDOWNKEY) {
                tileMap.setTile(rowTile + 1, colTile, 1);
            }
            if(pressLEFTKEY) {
                tileMap.setTile(rowTile, colTile - 1, 1);
            }
            if(pressRIGHTKEY) {
                tileMap.setTile(rowTile, colTile + 1, 1);
            }
            JukeBox.play("tilechange");
        }
    }

    public void update() {

        ticks++;
        boolean current = onWater;
        onWater = CheckIfOnWater();

        //if going from land to water
        if(!current && onWater){
            JukeBox.play("splash");
        }

        // set animation
        setAnimationDown();
        setAnimationLeft();
        setAnimationRight();
        setAnimationUp();

        // update position
        super.update();

    }

    public void setAnimationUp() {
        if(up) {

            if(onWater && currentAnimation != UPBOAT) {
                setAnimation(UPBOAT, upBoatSprites, 10);
            }
            else if(!onWater && currentAnimation != UP) {
                setAnimation(UP, upSprites, 10);
            }
        }
    }

    public void setAnimationRight() {
        if(right) {

            if(onWater && currentAnimation != RIGHTBOAT) {
                setAnimation(RIGHTBOAT, rightBoatSprites, 10);
            }
            else if(!onWater && currentAnimation != RIGHT) {
                setAnimation(RIGHT, rightSprites, 10);
            }
        }
    }

    public void setAnimationLeft() {
        if(left) {


            if(onWater && currentAnimation != LEFTBOAT) {
                setAnimation(LEFTBOAT, leftBoatSprites, 10);
            }
            else if(!onWater && currentAnimation != LEFT) {
                setAnimation(LEFT, leftSprites, 10);
            }
        }
    }

    public void setAnimationDown() {
        if(down) {
            if(onWater && currentAnimation != DOWNBOAT) {
                setAnimation(DOWNBOAT, downBoatSprites, 10);
            }
            else if(!onWater && currentAnimation != DOWN) {
                setAnimation(DOWN, downSprites, 10);
            }
        }
    }

    public boolean CheckIfOnWater(){
        int index = tileMap.getIndex(ydest / tileSize, xdest / tileSize);
        if(index == 4) {
            return true;
        }
        else {
            return false;
        }

    }

    // Draw Player.
    public void draw(Graphics2D g)
    {
        super.draw(g);
    }

}
EN

回答 2

Stack Overflow用户

发布于 2016-11-14 18:23:04

尝试在模型视图控制器样式中实现您的组件,例如,移动所有与更新yourapp.view包中的视图相关的代码,并将当前类播放器的代码移动到一个新类中,例如,GameBoard或GameView或诸如此类,其中该类的单一响应是更新在游戏板屏幕中绘制动画/图像等的模型表示。另一个类,例如,PlayerMovement和move,所有与de键盘事件相关的代码,目前在你的Player类中,这个类的响应性是捕捉让玩家移动的键。

移动所有与游戏命令和期望相关的代码,并移动到另一个包yourapp.controller或动作或任何东西,并创建新的类,例如PlayerController,GameController或任何东西,其中该类的单一响应性是接收玩家更新游戏模型状态的请求,寻址命令并告诉模型类将被更新,并告诉de view类,每次模型改变时获得新的模型状态;例如,当玩家在游戏板中有一个新的位置时,或者一些missil或一些角色死亡的位置等。

例如,将您的模型类放在其他包(例如yourapp.character或actors或其他任何包)中,并移动与创建新类的模型状态相关的代码,这些新类表示游戏角色或角色,或者定义游戏的行为或角色的活动元素。例如,玩家或一艘船或一门大炮等。这个类他们的责任只是定义游戏角色及其特征和行为,例如在游戏板中的位置,他们的武器,他们的力量,是活的还是死的等等,以及其他需要在游戏中扮演的角色的信息。

尝试在第二阶段识别并应用GoF模式,这可以帮助您重构代码,使其更加符合可靠的原则。

票数 1
EN

Stack Overflow用户

发布于 2016-11-15 06:39:27

关于SRP的另一种思考是每个单元应该有一个单一的更改原因。

以你的课程为例,将来可能会改变它的原因是什么:

  • 精灵更改。
  • 动画更改。
  • 游戏更改。
  • 玩家状态逻辑更改。

其中的每一个你都组织了字段,所以你自己发现了它们。现在,只需更进一步,为每个类创建类。这样,您就可以在不接触影响游戏的代码的情况下更改动画。这一点:

example)

  • Makes conflicts

  • Makes
  • 使更改更安全(在没有好的测试套件的情况下副作用更少)
  • 使工作更容易,您需要阅读的代码更少,只需阅读您感兴趣的部分
  • 使您的团队更容易审查更改(他们将知道您在更改动画时没有影响游戏,对于example)
  • Makes来说,团队更容易在系统的不同部分上工作,合并的机会更小)您可以轻松地将一个组件替换为另一个实现,例如,通过用另一个

替换精灵组件来重新设置游戏的皮肤

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/40580693

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档