1. 程式人生 > >OOP程式設計思想:類的設計原則

OOP程式設計思想:類的設計原則

設計原則

如果寫不出設計優良的類,就發揮不出OOP的優勢。發揮不出OOP的優勢,很容易就會成為量產型程式設計師。

下面給出一份糟糕的簡易文字遊戲的程式碼,然後進行優化

//Room.java
public class Room {
    public String description;
    public Room northExit;
    public Room southExit;
    public Room eastExit;
    public Room westExit;

    public Room(String description) 
    {
        this
.description = description; } 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; } @Override public String toString() { return description; } } //Game.java import java.util.Scanner; public class Game { private Room currentRoom; public Game() { createRooms(); } private void createRooms() { Room outside, lobby, pub, study, bedroom; // 製造房間
outside = new Room("城堡外"); lobby = new Room("大堂"); pub = new Room("小酒吧"); study = new Room("書房"); bedroom = new Room("臥室"); // 初始化房間的出口 outside.setExits(null, lobby, study, pub); lobby.setExits(null, null, null, outside); pub.setExits(null, outside, null, null); study.setExits(outside, bedroom, null, null); bedroom.setExits(null, null, null, study); currentRoom = outside; // 從城堡門外開始 } private void printWelcome() { System.out.println(); System.out.println("歡迎來到城堡!"); System.out.println("這是一個超級無聊的遊戲。"); System.out.println("如果需要幫助,請輸入 'help' 。"); System.out.println(); } // 以下為使用者命令 private void printHelp() { System.out.print("迷路了嗎?你可以做的命令有:go bye help"); System.out.println("如:\tgo east"); } 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; } if (nextRoom == null) { System.out.println("那裡沒有門!"); } else { currentRoom = nextRoom; 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(); } } public static void main(String[] args) { Scanner in = new Scanner(System.in); Game game = new Game(); game.printWelcome(); 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; } } System.out.println("感謝您的光臨。再見!"); in.close(); } }
消除程式碼複製

明顯看到下面這段程式碼在Game.java中有重複

        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.java
public void printchoice(){
    System.out.println("現在你在" + currentRoom);
    System.out.print("出口有:");
    ......
}
用封裝來降低耦合
//Room.java
public class Room {
    private String description;
    private Room northExit;
    private Room southExit;
    private Room eastExit;
    private Room westExit;

    public Room(String description){
        this.description = description;
    }

    public  String showExit(){
        StringBuffer re =new StringBuffer();
        if(this.eastExit!=null){
            re.append("east ");
        }
        if(this.westExit!=null){
            re.append("west ");
        }
        if(this.southExit!=null){
            re.append("south ");
        }
        if(this.northExit!=null){
            re.append("north ");
        }
        return re.toString();
    }

    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;
    }

    public  Room nextRoom(String obj){
        Room re=null;
        if(obj.equals("north"))
            re = this.northExit;
        else if(obj.equals("east"))
            re = this.eastExit;
        else if(obj.equals("south"))
            re = this.southExit;
        else if(obj.equals("west"))
            re = this.westExit;
        return re;
    }

    @Override
    public String toString(){
        return description;
    }
}

當然此時的Game.java

import java.util.Scanner;

public class Game {
    private Room currentRoom;

    public Game(){
        createMap();
    }

    private void createMap(){
        Room outside, lobby, pub, study, bedroom;

        //  製造房間
        outside = new Room("城堡外");
        lobby = new Room("大堂");
        pub = new Room("小酒吧");
        study = new Room("書房");
        bedroom = new Room("臥室");

        //  初始化房間的出口
        outside.setExits(null, lobby, study, pub);
        lobby.setExits(null, null, null, outside);
        pub.setExits(null, outside, null, null);
        study.setExits(outside, bedroom, null, null);
        bedroom.setExits(null, null, null, study);

        currentRoom = outside;  //  從城堡門外開始
    }

    private  void printChoice(){
        System.out.println("現在你在" + currentRoom);
        System.out.print("出口有:");
        String info = currentRoom.showExit();
        if(info != null){
            System.out.printf(info);
        }
        else{
            System.out.print("you have jump into a trap.over.");
        }
        System.out.println();
    }

    private void printWelcome() {
        System.out.println();
        System.out.println("歡迎來到城堡!");
        System.out.println("這是一個超級無聊的遊戲。");
        System.out.println("如果需要幫助,請輸入 'help' 。");
        System.out.println();
        printChoice();
    }

    // 以下為使用者命令

    private void printHelp(){
        System.out.print("迷路了嗎?你可以做的命令有:go bye help");
        System.out.println("如:\tgo east");
    }

    private void goRoom(String direction){
        Room nextRoom = currentRoom.nextRoom(direction);
        if (nextRoom == null) {
            System.out.println("那裡沒有門!");
        }
        else {
            currentRoom = nextRoom;
            printChoice();
        }
    }

    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        Game game = new Game();
        game.printWelcome();
        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;
                }
        }

        System.out.println("感謝您的光臨。再見!");
        in.close();
    }

}
以框架+資料代替硬編碼提高程式可擴充套件性

可擴充套件性的指的是程式碼的某些部分不需要經過修改就能適應將來可能的變化

低耦合:類與類間的關係越鬆越好
聚合:一個類或一個方法應該負責一個聚合的任務,一個方法應該實現一個邏輯操作,而一個類應該代表一定型別的實體。以此來實現重用

用介面來實現聚合
用容器增加靈活性

//Room.java
import java.util.HashMap;

public class Room {
    private String description;
    private HashMap<String,Room> exit = new HashMap<String, Room>();

    public Room(String description){
        this.description = description;
    }

    public void setExit(String direction , Room room){
        exit.put(direction,room);
    }

    public  String showExit(){
        StringBuffer re =new StringBuffer();
        for(String s :exit.keySet()){
            re.append(s);
            re.append(" ");
        }
        return re.toString();
    }

    public  Room nextRoom(String obj){
        Room re=null;
        re = exit.get(obj);
        return re;
    }

    @Override
    public String toString()
    {
        return description;
    }
}

//Game.java中的設定地圖部分
private void createMap(){
        Room outside, lobby, pub, study, bedroom;

        //  製造房間
        outside = new Room("城堡外");
        lobby = new Room("大堂");
        pub = new Room("小酒吧");
        study = new Room("書房");
        bedroom = new Room("臥室");

        //  初始化房間的出口
        outside.setExit("west",lobby);
        outside.setExit("south",study);
        outside.setExit("north", pub);
        lobby.setExit("east",  outside);
        pub.setExit("west", outside);
        study.setExit("west",outside);
        study.setExit("south",bedroom);
        bedroom.setExit("north",study);
        //此處我們可隨意增加down,up,等等的新的Room關係,而不用修改Room類
        //容器使得Room類更加靈活
        currentRoom = outside;  //  從城堡門外開始
    }

還有一處硬編碼為命令的判斷,即go,bye,help。
此處修改略為困難,待繼續學習有了更好的方法後再來填坑