• 利用封装、继承对Java代码进行优化


    注:本文实例分别可以在oldcastle(未优化的代码)和newcastle(优化后的代码)中查看,网址见文末

    城堡游戏:

    城堡中有多个房间,用户通过输入north, south, east, west等来确认去哪一个房间(此时窗口会有提示转到哪个房间),如果此时多出一个房间,需要使用up, down才能到达,修改代码则需要代码具有可扩展性,对原来的代码进行优化来实现这个功能。

    优化前代码思路:

    oldcastle

    优化变量使代码具有可扩展性

    主要思想:

    • Room中变量全部变为private类型,使代码变得安全。

    • 利用Hash表将方向变量实现灵活性。

      private HashMap<String, Room> exits = new HashMap<String, Room>();
      

      本文Hash表用到的方法:

      HashMap<Key, Value>
      HashMap.keySet()	// 返回所有的key值
      HashMap.put(K, V)	// 用于往HashMap中加元素
      HashMap.get(K)		// 返回对应的V值
      

    利用封装降低代码间耦合性

    主要思想:

    ​ 给Room类实现新方法,把方向的细节彻底隐藏在Room类内部,增添的方向与外部无关。

    先看这段代码,在Game中出现了2次。

    /*Game.java*/
    /*在printWelcome, goRoom中需要显示当前和选择时*/
    System.out.println("现在你在" + currentRoom);
    System.out.print("出口有:");
    if(currentRoom.northExit != null)
        System.out.print("north ");
    if(currentRoom.eastExit != null)
        System.out.print("east ");
    if(currentRoom.southExit != null)
        System.out.print("south ");
    if(currentRoom.westExit != null)
        System.out.print("west ");
    System.out.println();
    

    修改思路:

    Game类中添加显示出口的方法:

    /*Game.java*/
    public void showPrompt(){
      	System.out.println("现在你在" + currentRoom);
    	System.out.print("出口有:");
    	/*打印所有出口,getExitDesc()是Room中记录出口的新方法*/
    	System.out.println(currentRoom.getExitDesc());	
    	System.out.println();
    }
    

    Room类增加getExitDesc()方法:

    /*Room.java*/
    public String getExitDesc() {
        StringBuffer sb = new StringBuffer();	// StringBuffer类是字符串变量,常用于对字符串扩充和修改
        for (String dir : exits.keySet()) {		// 遍历所有的方向
            sb.append(dir);						// 扩充操作
            sb.append(' ');
        }
        return sb.toString();
    }
    

    goRoom中的转移房间代码与RoomsetExit有极高的耦合性:

    /*Game.java*/
    private void goRoom(String direction) {
      	Room nextRoom = null;
    	if (direction.equals("north")) {
          nextRoom = currentRoom.northExit;
        }
        if (direction.equals("east")) {
          nextRoom = currentRoom.eastExit;
        }
        if (direction.equals("south")) {
          nextRoom = currentRoom.southExit;
        }
        if (direction.equals("west")) {
          nextRoom = currentRoom.westExit;
        }
    }
    
    /*Room.java*/
    public void setExits(Room north, Room east, Room south, Room west) 
    {
        if(north != null)
          northExit = north;
        if(east != null)
          eastExit = east;
        if(south != null)
          southExit = south;
        if(west != null)
          westExit = west;
    }
    

    修改思路

    Room类修改setExit方法,并增加getExit方法。

    /*Room.java*/
    /*	
     * 录入房间空间位置的方式改变,由原来的对一个房间的四个方向分别定义,改为对一个房间
     * 自定义方向以及该方向上  的新房间,这样有利于增添上下以及新的位置,具有可扩展性。
     */
    public void setExit(String dir, Room room) {
        exits.put(dir, room);			// 向exit中添加元素
    }
    
    public Room getExit(String direction) {
        return exits.get(direction);	// 返回对应的Room
    }
    

    Room修改之后对goRoom的修改就简单许多:

    /*Game.java*/
    private void goRoom(String direction) {
      	Room nextRoom = null;
    	Room nextRoom = currentRoom.getExit(direction);
    }
    

    以框架+数据以及继承提高可扩展性

    对于Gamemain方法存在这样一段代码:

    public static void main(String[] args) {
        while (true) {
            String line = in.nextLine();
            String[] words = line.split(" ");
            if (words[0].equals("help")) {
              game.printHelp();
            } else if (words[0].equals("go")) {
              game.goRoom(words[1]);
            } else if (words[0].equals("bye")) {
              break;
            }
        }
    }
    

    思考:能否脱离if-else来实现用户的命令。

    修改思路之创造新的类

    定义一个Handler类来处理命令,用户命令分为go, help, bye三类,此时用Hash表来保存用户命令与Handler之间的关系,则Handler需要三个子类分别处理三种命令:
    Handler

    /*Handler.java*/
    public class Handler {
      	/*为了解决在HandlerGO操作中需要用到main方法里game,在Handler中创建Game来记录Game.java里的game.*/
        protected Game game;
    
        public Handler(Game game){
            this.game = game;
        }
    
        public void doCmd(String word) {
        }
    
        public boolean isBye() {
            return false;
        }
    
        public boolean isHelp() {
            return false;
        }
    }
    
    /*HandlerGo.java*/
    public class HandlerGo extends Handler {
        public HandlerGo(Game game) {
            super(game);
        }
    
        @Override
        public void doCmd(String word) {
            game.goRoom(word);
        }
    }
    
    /*HandlerHelp.java*/
    public class HandlerHelp extends Handler {
        public HandlerHelp(Game game) {
            super(game);
        }
    
        @Override
        public boolean isHelp() {
            return true;
        }
    }
    
    /*HandlerBye.java*/
    public class HandlerBye extends Handler {
        public HandlerBye(Game game) {
            super(game);
        }
    
        @Override
        public boolean isBye() {
            return true;
        }
    }
    
    /*Game.java*/
    /*用Hash表保存命令与Handler之间的关系*/
    private HashMap<String, Handler> handlers = new HashMap<String, Handler>();
    /*构造器需要做相应的变化*/
    public Game() {
        handlers.put("go", new HandlerGo(this));
        handlers.put("bye", new HandlerBye(this));
        handlers.put("help", new HandlerHelp(this));
        createRooms();
    }
    /*为命令操作创造新的方法*/
    public void play(){  
        Scanner in = new Scanner(System.in);
        while (true) {
            String line = in.nextLine();
            String[] words = line.split(" ");
        	/*
        	 * 利用Hash表<K, V>的特性,如果用户输入"help",通过handler.get()得出handler类型
        	 * 下面这句就相当于:Handler handler = new HandlerHelp(this);
        	 */
            Handler handler = handlers.get(words[0]);
            String value = "";
            if(words.length > 1)
              	value = words[1];
            if(handler != null)
            {
              	/*此时handler为HandlerHelp型,没有value值*/
                handler.doCmd(value);
                if(handler.isBye())
                  	break;
              	/*HandlerHelp继承了Handler中的isHelp()方法并将其覆盖,此时handler.isHelp()返回true.*/
                if(handler.isHelp())
                  	this.printHelp();
            }
        }
    }
    
    public static void main(String[] args) {
        Game game = new Game();
        game.printWelcome();
        game.play();
    }
    

    源代码可以这个网页查看:

    github/duyue6002/城堡游戏

  • 相关阅读:
    CSS 背景
    CSS padding 属性
    CSS border 属性和 border-collapse 属性
    CSS margin 属性
    IEnumerable<T> 接口和GetEnumerator 详解
    discuz! X3.4特殊字符乱码解决方案
    Discuz通过修改文章标题更好的实现SEO的方法
    关于Discuz x3.3页面空白解决方法
    discuz x3.3标题的最少字数限制设置方法
    discuz网站前端代码优化思路
  • 原文地址:https://www.cnblogs.com/duyue6002/p/6814617.html
Copyright © 2020-2023  润新知