Java8与游戏开发(四)

要让游戏开发的过程更加Effective,必须遵从一些原则,其实就是平时的开发经验总结出来。

一、优先使用工厂模式来创建对象。对于那些可选字段很多的对象,优先使用builder模式。

二、谨慎地使用单例模式,Java可以用Enum实现单例模式。

三、谨慎地使用缓存。

大数据量的缓存,有三种方式避免内存的过度使用:

  1. WeakHashMap,更加复杂的缓存,可以用java.lang.ref的类

  2. SheduledThreadPoolExcecutor后台线程定时清除。

  3. LinkedHashMap利用removeEldestEntry

  4. Caffeine

Caffeine基于W-TinyLFU算法,理论上比LRU算法有更高的命中率,应用了Java8的CompletableFuture,Spring就是使用Caffeine作为自己缓存框架。

四、使用不可变类保证线程安全。

1.构造方法的参数如果是可变类对象,成员对象包含这些可变类对象的引用,使用保护性拷贝作为可变成员对象的引用:

class A{

private final Date start;

public A(Date start){
  
  this.start = start.clone();
  
}

2.可变集合作为成员对象的时候,修饰为private,并且提供get方法返回Clone或者unmodifyList.

3. 用final修饰class或者用private修饰构造函数,防止扩展性修改。

五、优先使用位运算来编写hashCode方法,必要时在对象内存缓存hashCode的计算结果,提高性能。

public interface IntPredicate{
    boolean test(i);
}

//无装箱的实现,性能更好
IntPredicate evenNumbers = (int i) -> i % 2 == 0;
evenNumbers.test(1000);

//装箱的实现
Predicate<Integer> oddNumbers = (Integer i) -> i % 2 == 1;
oddNumbers.test(1000);

六、优先使用接口而不是抽象类。

Java是单继承的,如果用抽象类,不容易扩展,使用抽象类的主要原因是有一些成员对象可以被继承,父类的方法实现可以被重用,但是Java8的接口是可以编写默认方法实现的,所以优先使用接口。

七、优先使用泛型设计。

八、优先使用EnumSet和EnumMap存储枚举类型的数据。

EnumSet和EnumMap都是都是用一个bit来表示数据是否存在的,性能比使用普通的Set和Map要高。

九、优先使用标记接口而不是标记注解,不要过度使用注解。

对于性能要求高的函数,可以用注释代替参数检查。

十、避免过长的参数列表。

方法的参数太多,有三种解决方案:

  1. 分解成多个方法,每个方法只需要这些参数的一个子集。

  2. 创建辅助类HelperClass,一般是静态内部类,保存参数的组合,每一个参数的组合作为辅助方法的单个参数。

  3. 定义参数对象ParamOject代表所有参数,从对象的构建到方法调用都是用builder模式。

十一、优先使用Enum作为参数提高代码可读性。

十二、避免在精确计算的场合使用float和double。

货币系统、交易系统、使用BigDecimal、BigInteger、int或者long。

十三、优先使用基本类型,而不是装箱类型。

  1. 装箱类型为null时容易引起麻烦。

  2. 比较两个装箱类型容易出错,一般不能直接用==比较。

  3. 反复地装箱拆箱,性能会有所下降。

Java的泛型必须是装箱类型,所以必然会导致装箱过程,但是Java8已经为我们设计了一些表面装箱过程的函数式接口:

public interface IntPredicate{
    boolean test(i);
}

//无装箱的实现,性能更好
IntPredicate evenNumbers = (int i) -> i % 2 == 0;
evenNumbers.test(1000);

//装箱的实现
Predicate<Integer> oddNumbers = (Integer i) -> i % 2 == 1;
oddNumbers.test(1000);

十四、如果其他类型更合适,避免使用String类型。

十五、谨慎地优化。

不要因为性能而牺牲合理的结构,努力编写好的程序,速度自然会有所提高。

十六、谨慎地处理异常、存储日志、检查参数。

  1、本不应该出现的错误或者不应该继续执行的地方直接抛异常。

        避免在程序中使用受检异常,减少程序复杂度。

        对可恢复执行的情况使用受检异常,对继续执行无益或者违反规范的情况使用运行时异常或者error。

  2、重要的业务逻辑打日志 。

  3、检查参数合法性,而不是让错误发生。

        一般使用Assert断言来检查参数合法性,但是推荐Google的Guava类库Preconditions,Spring的Assert工具类。

        对于那些已经有了隐式的参数检查,就不需要再次检查了。

十七、谨慎地使用ConcurrentHashMap。

get的次数远远多于put的情况,对HashMap使用双重检查锁机制就能胜任,ConcurrentHashMap的优势就体现不出来。

十八、延迟初始化。

1.使用Holder静态内部

private static class FieldHolder {    

    static final FieldType field = computeFieldValue();
}
private static FieldType computeFieldValue() {    

    return new FieldType();
}

2.双重检查锁

private volatile FieldType field4;

FieldType getField4() {    

     FieldType result = field4;   
     
     if (result == null) {  
     
          synchronized (this) { 
              
              result = field4;
                         
             if (result == null) {
             
                 field4 = result = computeFieldValue();
                 
             }
         }
     }    
     return result;
}

private static FieldType computeFieldValue() {

     return new FieldType();
}

十九、避免使用Serializable接口,应该考虑使用其他的序列化方式。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值