服务提供者框架

来源:互联网 发布:php遍历json对象 编辑:程序博客网 时间:2024/04/28 12:59
//服务接口public interface Service {public void move();}public class Train implements Service{public void move(){System.out.println(this.getClass().getName().substring(this.getClass().getName().lastIndexOf(".")+1)+" can run.");}}public class Plane implements Service {public void move(){System.out.println(this.getClass().getName().substring(this.getClass().getName().lastIndexOf(".")+1)+" can fly.");}}//服务提供者接口public interface Provider {Service newService();}public class TrainProvider implements Provider{@Overridepublic Service newService() {return new Train();}}public class PlaneProvider implements Provider {@Overridepublic Service newService() {return new Plane();}}public class Services {private Services(){}//私有化构造函数,禁止创建Services的实例//用Map存储service及其对应的名称private static final Map<String,Provider> providers=new ConcurrentHashMap<String,Provider>();public static final String DEFALUT_PROVIDER ="<def>";//注册provider的APIpublic static void registerDefaultProvider(Provider p){registerProvider(DEFALUT_PROVIDER,p);}public static void registerProvider(String name,Provider p){providers.put(name, p);}//获取service的APIpublic static Service newInstance(){return newInstance(DEFALUT_PROVIDER);}public static Service newInstance(String name){Provider p=providers.get(name);if(p==null)throw new IllegalArgumentException("No provider registered with name: "+name);return p.newService();}}//客户程序public class Client {public static void main(String[] args){//创建服务提供者Provider p1=new TrainProvider();Provider p2=new PlaneProvider();//注册服务Services.registerProvider("train", p1);Services.registerProvider("plane", p2);//获取服务Service s1=Services.newInstance("train");Service s2=Services.newInstance("plane");//使用服务s1.move();s2.move();}}


服务提供者接口(Service Provider Interface)可以不要,这个时候可以按照类名来注册服务,并且通过反射的方法对服务进行实例化。

public class Services {private Services(){}private static final Set<String> services=new LinkedHashSet<String>();public static final String DEFAULT_SERVICE_NAME="<def>";//注册服务的APIpublic static void registerDefaultService(){registerService(DEFAULT_SERVICE_NAME);}public static void registerService(String name){services.add(name);}//获取服务的APIpublic static Service newInstance(){return newInstance(DEFAULT_SERVICE_NAME);}public static Service newInstance(String name){if(!services.contains(name))throw new IllegalArgumentException("No provider registered with name: "+name);Service s=null;try{String package_path=Services.class.getName().substring(0,Services.class.getName().lastIndexOf(".")+1);s=(Service)Class.forName(package_path+name).newInstance();}catch(ClassNotFoundException e1){System.err.println("class not found.");System.exit(1);}catch(IllegalAccessException e2){System.err.println("class not accessible.");System.exit(1);}catch(InstantiationException e3){System.err.println("class not instantiable.");System.exit(1);}return s;}}public class Client {public static void main(String[] args){//注册服务Services.registerService("Train");Services.registerService("Plane");//获取服务Service s1=Services.newInstance("Train");Service s2=Services.newInstance("Plane");//使用服务s1.move();s2.move();}}

使用反射有3个缺点:

  1. 丧失了编译时类型检查的好处。上例中会产生3个运行时错误,如果不使用反射,这3个错误都会成不编译时错误。
  2. 代码冗长。由于要catch运行时错误,代码变得冗长。
  3. 性能损失。反射方法比普通方法的调用慢许多。
System.exit很少使用,它会终止整个VM,但是它对于命令行有效性的非法终止是很合适的。