初学Java之第六(魔域-文字rpg)
作者:互联网
Zork
前言
学习目标:本次学习讲初步涉及到Code Refactoring、I/O Streams、Composition and Inheritance等方面知识。
提示:以下是本篇文章正文内容,下面案例可供参考
游戏界面及特性介绍
游戏名:仙侠传
地图:
|拜火高窟| | |十里田|——|餘杭村|//|無垠荒漠| | | | |玄鐵鎮|//|檾山仙市|——|玄玉藥房| 北 东 西 南
道具系统: 四种不同道具,其中一种可以触发隐藏剧情
通关:15级通关
可存档读档;
附送大logo;
一、Code Refactoring
重构(名词):对软件内部结构的一种调整,目的是在不改变软件可观察行为的前提下,提高其可理解性,降低其修改成本。
重构(动词):使用一系列重构手法,在不改变软件可观察行为的前提下,调整其结构。怎样才算是合格的重构呢? 至少需要做到以下几点:
消除味道:一个重构应该是从识别一个坏味道(Bad Smell)开始,以消除一个坏味道结束,任何不以消除坏味道为目标的重构都是耍流氓。
始终工作:即重构定义中的“在不改变软件可观察行为的前提下”,说白了就是重构过程不能破坏甚至改变软件外在功能。
持续集成:不需要为重构单建分支,重构过程可以做到Feature开发在同一分支上持续集成持续交付。
随时中止:例如一个方法重命名,需要修改100个调用点,当改到50个的时候有个紧急的Feature,我可以随时暂停重构,立即切换到Feature开发上,且不需要回滚已做的重构。
断点续传:还是上边的例子,假如我已经完成了紧急Feature的开发,可以随时继续之前的重构,完成剩下50个调用点的重命名。
过程可逆:对于重构,经常有人会问:你怎么保证重构就会更好而不是更坏呢?重构的伟大就在于他跳出了对错之争,将关注点放到如何快速平滑安全的变化上,当然也包括反向重构。
根据重构定义所述,我将所有跟角色有关的代码利用继承和组合进行了重构,主要从creature、player、enemy中进行。
二、Composition and Inheritance
1.继承
继承:
“is-a”的关系;
B是基类A的一个派生类;
逻辑上要求:“一个B对象也是一个A对象”。(父类更通用,子类更具体)
功能:有了继承以后,我们定义一个类的时候,可以在一个已经存在的类的 基础上,还可以定义自己的新成员。
格式:class 子类名 extends 父类名 {}
优点:
提高了代码的复用性
提高了代码的维护性(通过少量的修改,满足不断变化的具体要求)
让类与类产生了一个关系,是多态的前提
缺点:
破坏封装,子类依赖父类
只能继承一个父类,必须包含所有方法,增加系统复杂性
复用父类方法
代码如下(示例-继承):
定义一个类 Car 来描述所有汽车通用的刹车行为 brake(),
然后通过某种方式(继承/组合)来为不同的型号的汽车提供不同的刹车行为。
public class Car {
public void brake() {
// 提供一个默认的刹车实现
...
}
}
public class CarModelA extends Car {
public void brake() {
aStyleBrake();// A 风格的刹车行为
}
}
public class CarModelB extends Car {
public void brake() {
bStyleBrake(); // B 风格的刹车行为
}
}
2.组合
组合:
“has-a”关系;
类C中“有”成员变量k,k是类D的对象,则C和D是复合关系;
一般逻辑上要求:“D对象是C对象的固有属性或组成部分”。
功能:使用组合需要在当前类C中建立成员变量k,且变量k得是类D的对象
格式:
class 子类名
private 其他子类名 成员变量
优点:
不破坏封装,整体和局部耦合度低
支持扩展,随意增加复合类
动态选择复合类方法
缺点:
- 容易产生过多的对象,且为了能组合多个对象,必须仔细对接口进行定义。
代码如下(示例-复合):
// 先写接口
public interface IBrakeBehavior {
public void brake();
}
public class AStyleBrake implements IBrakeBehavior {
public void brake() {
aStyleBrake(); // A 风格的刹车行为
}
}
public class BStyleBrake implements IBrakeBehavior {
public void brake() {
bStyleBrake(); // B 风格的刹车行为
}
}
public class Car {
protected IBrakeBehavior brakeBehavior;
public void brake() {
brakeBehavior.brake();
}
public void setBrakeBehavior(final IBrakeBehavior brakeType) {
brakeBehavior = brakeType;
}
}
三、I/O Streams
Java.io 包几乎包含了所有操作输入、输出需要的类。所有这些流类代表了输入源和输出目标。
Java.io 包中的流支持很多种格式,比如:基本类型、对象、本地化字符集等等。
一个流可以理解为一个数据的序列。输入流表示从一个源读取数据,输出流表示向一个目标写数据。
Java 为 I/O 提供了强大的而灵活的支持,使其更广泛地应用到文件传输和网络编程中。
代码如下(示例):
public static final String PLAYER_ARCHIVE_FILE = "res/archive.player"; //角色存档
public static final String PLACES_ARCHIVE_FILE = "res/archive.places"; //地点存档
public static final String BAG_ARCHIVE_FILE = "res/archive.bag"; //背包存档
/**
* 读档
*/
@SuppressWarnings("unchecked")
private void readArchive() {
File playArchive = new File(PLAYER_ARCHIVE_FILE);
File placesArchive = new File(PLACES_ARCHIVE_FILE);
File bagArchive = new File(BAG_ARCHIVE_FILE);
if (!playArchive.exists() || !placesArchive.exists()) {
println("错误存档不存在或者不完整,请检测" + PLAYER_ARCHIVE_FILE + "以及" + PLACES_ARCHIVE_FILE + "以及" + BAG_ARCHIVE_FILE);
return;
}
try (FileInputStream fis = new FileInputStream(playArchive);
FileInputStream fis2 = new FileInputStream(placesArchive);
FileInputStream fis3 = new FileInputStream(bagArchive);
ObjectInputStream ois = new ObjectInputStream(fis);
ObjectInputStream ois2 = new ObjectInputStream(fis2);
ObjectInputStream ois3 = new ObjectInputStream(fis3)) {
player = (Player) ois.readObject();
currPlace = (Place) ois2.readObject();
bag = (ArrayList<String>) ois3.readObject();
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
}
/**
* 存档
*/
private void archive() {
File playerArchive = new File(PLAYER_ARCHIVE_FILE);
File placesArchive = new File(PLACES_ARCHIVE_FILE);
File bagArchive = new File(BAG_ARCHIVE_FILE);
try (FileOutputStream fos = new FileOutputStream(playerArchive);
ObjectOutputStream oos = new ObjectOutputStream(fos);
FileOutputStream fos2 = new FileOutputStream(placesArchive);
ObjectOutputStream oos2 = new ObjectOutputStream(fos2);
FileOutputStream fos3 = new FileOutputStream(bagArchive);
ObjectOutputStream oos3 = new ObjectOutputStream(fos3)) {
if (!playerArchive.exists()) {
playerArchive.createNewFile();
}
if (!placesArchive.exists()) {
placesArchive.createNewFile();
}
oos.writeObject(player);
oos2.writeObject(currPlace);
oos3.writeObject(bag);
} catch (IOException e) {
e.printStackTrace();
}
println("正在存档...成功!");
}
总结
此次项目和Presentation使我了解了很多东西,对java知识有了更深一步的了解,不过希望两个星期回顾的时候还能看得懂自己的代码,对Composition、I/O Streams的用法两天之后再回头看一次。
标签:魔域,Java,File,重构,FILE,ARCHIVE,rpg,new,public 来源: https://blog.csdn.net/weixin_53987369/article/details/113490413