你的API有“状态”吗?

我相信有不少人还不明白有状态和无状态(Stateful and Stateless)的概念,那么我们今天就来谈谈有状态和无状态,一方面不断总结提高自我,另一方面兼扫盲。

基本概念: 

有状态就是有数据存储功能。有状态对象(Stateful Bean),就是有实例变量的对象,可以保存数据,是非线程安全的。在不同方法调用间不保留任何状态。 
无状态就是一次操作,不能保存数据。无状态对象(Stateless Bean),就是没有实例变量的对象.不能保存数据,是不变类,是线程安全的。 

有状态的噩梦

在使用基于有状态类的API的时候,我们也许有机会调用很多跟状态有关的公共方法,这些调用方式到底符不符合时机这是一个很大的问题(我的代码写得足够的防御也最多就是抛异常罢了)。API的调用方需要做的事,1,忍受和处理异常 2,学习状态类工作机制。没办法 你要写一个基于状态类的API用户就得做那么多事,下面就是一个状态类的例子:
public abstract class Stateful {
	   public static Stateful create(String name) {
	        return createImpl(name);
	    }
	    public abstract void start(int totalAmount);
	    public abstract void progress(int howMuch);
	    public abstract void finish();
	    // FINISH: progress.api
	    Stateful() {
	    }	    
	    private static Stateful createImpl(String name) {
	        return new Impl(name);
	    }
	    private static final class Impl extends Stateful {
	        private final String name;
	        private int total = -1;
	        private int current;
	        public Impl(String name) {
	            this.name = name;
	        }
	        @Override
	        public void start(int totalAmount) {
	            total = totalAmount;
	        }
	        @Override
	        public void progress(int howMuch) {
	            if (total == -1) {
	                throw new IllegalStateException("Call start first!");
	            }
	            current = howMuch;
	        }
	        @Override
	        public void finish() {
	            total = -1;
	            current = 0;
	        }
	    }
}
试想如果你一下面这种顺序调用API
Stateful p = Stateful.create("bad idea");
            p.progress(10);
            p.finish();

你得到的会是一个RuntimeException,原因是你忘记启动它了,从常识来讲我们的确应该先启动它才能有进度。但是这只是一个简单的例子 ,我们不能保证所有的状态机业务都跟这个一样简单用常识都能排错!久而久之这样的API会报废掉,因为它要的太多了!

”无状态“的API

当我们把上述的状态机方法适当的归类,一个处于配置 另外一个属于过程,用配置去实例化过程。

public abstract class Stateless {
// BEGIN: progress.phases
    public static Stateless create(String name) {
        return createImpl(name);
    }
    public abstract InProgress start(int totalAmount);
    public abstract class InProgress {
        public abstract void progress(int howMuch);
        public abstract void finish();
        // FINISH: progress.phases
        InProgress() {
        }
    }    
    private static Stateless createImpl(String name) {
        return new Impl(name);
    }
    private static final class Impl extends Stateless {
        private final String name;
        public Impl(String name) {
            this.name = name;
        }
        @Override
        public InProgress start(int totalAmount) {
            return new InImpl(totalAmount);
        }
        private class InImpl extends InProgress {
            private final int total;
            private int current;
            public InImpl(int total) {
                this.total = total;
            }
            @Override
            public void progress(int howMuch) {
                current = howMuch;
            }
            @Override
            public void finish() {
                current = total;
            }
        }
    }
}

这样就解决了过程的初始化问题:
Stateless p = Stateless.create("Good idea!");
        InProgress progress = p.start(10);
        // without calling start(), there is no way to call progress() method
        progress.progress(10);
        progress.finish();

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值