Java8与游戏开发(七)

游戏系统会有大量的配置信息,包括从数据库中读取的配置,还有从各种文件中读取的配置,都伴随着抛出NullPointerException的可能,如果能够减少空指针,系统会更加稳定。

Java8的Optional能够很好地表示可选数据,但是对于错误导致的数据缺失,无法提供有用的信息,如果仅仅使用Exception来表示错误,又会失去了使用Optional的所有好处。

一个可行的方案,就是定义三种对象来描述数据缺失:Success、Failure、Empty。

/**
 * 当结果源自错误时候,Java8的Optional<>无法得到引起缺失的原因,这个类能区分不同情况引起的数据缺失问题,包含了错误的具体信息。
 * 
 * 1.计算错误、异常或者逻辑错误引起的数据缺失,Failure
 * 
 * 2.非错误引起的数据缺失(可选数据),Empty
 * 
 * 3.成功时,包装结果值,Success
 *
 * @author 林子豪
 *
 * @param <V> 结果值的数据类型
 */
public abstract class ResultOption<V> {

	@SuppressWarnings("rawtypes")
	private static ResultOption empty = new Empty();

	private ResultOption() {}

	// 空对象
	private static class Empty<V> extends ResultOption<V> {

		private Empty() {}

		@Override
		public V getOrElse(V defaultValue) {
			return defaultValue;
		}

		@Override
		public V getOrElse(Supplier<V> defaultValue) {
			return defaultValue.get();
		}

		@Override
		public <U> ResultOption<U> map(Function<V, U> f) {
			return empty();
		}

		@Override
		public <U> ResultOption<U> flatMap(Function<V, ResultOption<U>> f) {
			return empty();
		}

		@Override
		public String toString() {
			return "Empty()";
		}

		@Override
		public ResultOption<V> mapFailure(String detail) {
			return this;
		}

		@Override
		public void ifSuccess(Consumer<V> effect) {
			// 什么也不做
		}

		@Override
		public void ifSuccessOrThrow(Consumer<V> effect) {
			// 数据的缺失不应该作为错误 ,什么也不做
		}

		@Override
		public ResultOption<RuntimeException> ifSuccessOrException(Consumer<V> effect) {
			return empty();
		}

		@Override
		public ResultOption<String> ifSuccessOrDetail(Consumer<V> effect) {
			return empty();
		}

		@Override
		public V getOrElseThrow() {
			throw new IllegalStateException("get() called on empty.");
		}

		@Override
		public V getOrElseThrow(String message) {
			throw new IllegalStateException(message);
		}

		@Override
		public ResultOption<ResultCode> ifSuccessOrResultCode(Consumer<V> effect) {
			return empty();
		}

		@Override
		public ResultCode getCode() {
			return ResultCode.DATA_EMPTY;
		}

		@Override
		public String getDetail() {
			return "";
		}

		@Override
		public ResultCode andThen(Function<V, ResultCode> f) {
			return ResultCode.DATA_EMPTY;
		}

	}

	// fail对象
	private static class Failure<V> extends ResultOption<V> {

		private final ResultCode resultCode;

		//如果要返回额外的信息,可以往detail里面塞数据
		private final String detail;

		private Failure(ResultCode resultCode) {
			this.resultCode = resultCode;
			this.detail = resultCode.name();
		}

		private Failure(int code) {
			this.resultCode = ResultCode.getCode(code);
			this.detail = resultCode.name();
		}

		private Failure(ResultCode resultCode, String detail) {
			this.resultCode = resultCode;
			this.detail = WebUtil.getString(detail, resultCode.name());
		}

		private Failure(int code, String detail) {
			this.resultCode = ResultCode.getCode(code);
			this.detail = WebUtil.getString(detail, resultCode.name());
		}

		private Failure(Exception exception) {
			this.resultCode = ResultCode.EXCEPTION;
			this.detail = WebUtil.getString(exception.getMessage(), resultCode.name());
		}

		private Failure(Exception exception, String detail) {
			this.resultCode = ResultCode.EXCEPTION;
			this.detail = WebUtil.getString(detail, resultCode.name());
		}

		@Override
		public String toString() {
			return String.format("Failure(%s)", detail);
		}

		@Override
		public V getOrElse(V defaultValue) {
			return defaultValue;
		}

		@Override
		public V getOrElse(Supplier<V> defaultValue) {
			return defaultValue.get();
		}

		@Override
		public <U> ResultOption<U> map(Function<V, U> f) {
			return failure(resultCode, detail);
		}

		@Override
		public <U> ResultOption<U> flatMap(Function<V, ResultOption<U>> f) {
			return failure(resultCode, detail);
		}

		@Override
		public ResultOption<V> mapFailure(String detail) {
			return failure(resultCode, detail);
		}

		@Override
		public void ifSuccess(Consumer<V> effect) {
			// 什么也不做
		}

		@Override
		public void ifSuccessOrThrow(Consumer<V> effect) {
			throw new IllegalStateException(detail);
		}

		@Override
		public ResultOption<RuntimeException> ifSuccessOrException(Consumer<V> effect) {
			// 保持原来的异常信息,以便做其他处理
			return success(new IllegalStateException(detail));
		}

		@Override
		public ResultOption<String> ifSuccessOrDetail(Consumer<V> effect) {
			return success(detail);
		}

		@Override
		public V getOrElseThrow() {
			throw new IllegalStateException(detail);
		}

		@Override
		public V getOrElseThrow(String message) {
			throw new IllegalStateException(message);
		}

		@Override
		public ResultOption<ResultCode> ifSuccessOrResultCode(Consumer<V> effect) {
			return success(resultCode);
		}

		@Override
		public ResultCode getCode() {
			return resultCode;
		}

		@Override
		public String getDetail() {
			return detail;
		}

		@Override
		public ResultCode andThen(Function<V, ResultCode> f) {
			return resultCode;
		}

	}

	// success对象
	private static class Success<V> extends ResultOption<V> {

		private final V value;

		private Success(V value) {

			this.value = value;
		}

		@Override
		public String toString() {
			return String.format("Success(%s)", value.toString());
		}

		@Override
		public V getOrElse(V defaultValue) {
			return value;
		}

		@Override
		public V getOrElse(Supplier<V> defaultValue) {
			return value;
		}

		@Override
		public <U> ResultOption<U> map(Function<V, U> f) {
			try {
				return success(f.apply(value));
			} catch (Exception e) {
				return failure(e);
			}
		}

		@Override
		public <U> ResultOption<U> flatMap(Function<V, ResultOption<U>> f) {
			try {
				return f.apply(value);
			} catch (Exception e) {
				return failure(e);
			}
		}

		@Override
		public ResultOption<V> mapFailure(String detail) {
			return this;
		}

		@Override
		public void ifSuccess(Consumer<V> effect) {
			effect.accept(value);
		}

		@Override
		public void ifSuccessOrThrow(Consumer<V> effect) {
			ifSuccess(effect);
		}

		@Override
		public ResultOption<RuntimeException> ifSuccessOrException(Consumer<V> effect) {
			effect.accept(value);
			// 因为没有RuntimeException,所以返回empty()
			return empty();
		}

		@Override
		public ResultOption<String> ifSuccessOrDetail(Consumer<V> effect) {
			effect.accept(value);
			return empty();
		}

		@Override
		public V getOrElseThrow() {
			return this.value;
		}

		@Override
		public V getOrElseThrow(String message) {
			return this.value;
		}

		@Override
		public ResultOption<ResultCode> ifSuccessOrResultCode(Consumer<V> effect) {
			effect.accept(value);
			return empty();
		}

		@Override
		public ResultCode getCode() {
			return ResultCode.SUCCESS;
		}

		@Override
		public String getDetail() {
			return "";
		}

		@Override
		public ResultCode andThen(Function<V, ResultCode> f) {
			return f.apply(value);
		}

	}

	/ 静态方法

	@SuppressWarnings("unchecked")
	public static <V> ResultOption<V> empty() {
		return empty;
	}

	public static <T, V> ResultOption<T> failure(ResultOption<V> failure) {
		return new Failure<>(failure.getCode(), failure.getDetail());
	}

	public static <V> ResultOption<V> failure(int code) {
		return new Failure<>(code);
	}

	public static <V> ResultOption<V> failure(ResultCode resultCode) {
		return new Failure<>(resultCode);
	}

	public static <V> ResultOption<V> failure(int code, String detail) {
		return new Failure<>(code, detail);
	}

	public static <V> ResultOption<V> failure(ResultCode resultCode, String detail) {
		return new Failure<>(resultCode, detail);
	}

	public static <V> ResultOption<V> failure(Exception exception) {
		return new Failure<>(exception);
	}

	public static <V> ResultOption<V> failure(Exception exception, String detail) {
		return new Failure<>(exception, detail);
	}

	public static <V> ResultOption<V> success(V value) {
		return new Success<>(value);
	}

	public static <V> ResultOption<V> of(V value) {
		return value != null ? success(value) : empty();
	}

	public static <V> ResultOption<V> of(V value, ResultCode code) {
		return value != null ? success(value) : failure(code);
	}

	public static <V> ResultOption<V> of(V value, String reason) {
		return value != null ? success(value) : failure(ResultCode.DATA_EMPTY, reason);
	}

	public static <V> ResultOption<V> of(V value, ResultCode code, String reason) {
		return value != null ? success(value) : failure(code, reason);
	}

	public static <V> ResultOption<V> of(Optional<V> jdkOptional) {
		return jdkOptional.isPresent() ? success(jdkOptional.get()) : empty();
	}

	public static <V> ResultOption<V> of(Optional<V> jdkOptional, ResultCode resultCode) {
		return jdkOptional.isPresent() ? success(jdkOptional.get()) : failure(resultCode);
	}

	public static <V> ResultOption<V> of(Optional<V> jdkOptional, ResultCode resultCode, String detail) {
		return jdkOptional.isPresent() ? success(jdkOptional.get()) : failure(resultCode, detail);
	}

	///实例方法
	public ResultOption<V> filter(Function<V, Boolean> p) {
		return flatMap(x -> p.apply(x) ? this : failure(ResultCode.CONDITION_NOT_MATCH, "Condition not matched"));
	}

	public ResultOption<V> filter(Function<V, Boolean> p, String message) {
		return flatMap(x -> p.apply(x) ? this : failure(ResultCode.CONDITION_NOT_MATCH, message));
	}

	public boolean exists(Function<V, Boolean> p) {
		return map(p).getOrElse(false);
	}

	public ResultOption<V> orElse(Supplier<ResultOption<V>> defaultValue) {
		return map(x -> this).getOrElse(defaultValue);
	}

	public boolean isSuccess() {
		return this instanceof Success;
	}

	public boolean isNotSuccess() {
		return !(this instanceof Success);
	}

	public boolean isEmpty() {
		return (this instanceof Empty);
	}

	public boolean isFailure() {
		return (this instanceof Failure);
	}

	// 抽象方法

	public abstract V getOrElseThrow();

	public abstract V getOrElseThrow(String message);

	public abstract V getOrElse(final V defaultValue);

	public abstract V getOrElse(final Supplier<V> defaultValue);

	public abstract <U> ResultOption<U> map(Function<V, U> f);

	public abstract <U> ResultOption<U> flatMap(Function<V, ResultOption<U>> f);

	//转化成Failure对象
	public abstract ResultOption<V> mapFailure(String detail);

	// consumer就是作用,可以修改外界的任何东西
	public abstract void ifSuccess(Consumer<V> effect);

	public abstract void ifSuccessOrThrow(Consumer<V> effect);

	//数据缺失的时候返回具体错误信息
	public abstract ResultOption<String> ifSuccessOrDetail(Consumer<V> effect);

	//数据缺失的时候返回具体的异常对象,而不是直接抛出异常
	public abstract ResultOption<RuntimeException> ifSuccessOrException(Consumer<V> effect);

	//数据缺失的时候返回具体的错误码
	public abstract ResultOption<ResultCode> ifSuccessOrResultCode(Consumer<V> effect);

	public abstract ResultCode andThen(Function<V, ResultCode> f);

	public abstract ResultCode getCode();

	public abstract String getDetail();

}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值