科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道基础软件J2ee程序中的面向对象设计(2)

J2ee程序中的面向对象设计(2)

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

面向对象程序设计比任何具体技术都重要。但是在使用种种模式的时候,也要防止过度设计,增加不必要的复杂性、浪费时间和经费。

作者:中国IT实验室 来源:中国IT实验室 2007年8月23日

关键字: J2EE 面向对象设计

  • 评论
  • 分享微博
  • 分享邮件

九、使用反射(Using Reflection)

    反射可以让程序在运行时加载、实例化、操作类。反射还可以强化很多设计模式,比如工厂模式(Factory),就没有必要将类名写在程序中,可以直接配置到文件中。
    反射和Swithches(Reflection and Switches)
public void vetoableChange(PropertyChangeEvent e) throws PropertyVetoException {
    if (e.getPropertyName() .equals ("email")) {
        String email = (String) e.getNewValue();
        validateEmail (email, e);
    }
    ...
    } else if (e.getPropertyName() .equals ("age")) {
        int age = ((Integer) e.getNewValue()).intValue();
        validateAge(age, e);
    }
    ...
  }
        是一个正常的属性检查的代码,但是如果我们需要增加或者删除一个属性,我们就需要修改这些判断,这意味着我们需要重新测试。但是如果我们使用反射,就可以非常优雅的解决怎么问题
  public AbstractVetoableChangeListener() throws SecurityException {
    Method[] methods = getClass() .getMethods();
    for (int i = 0; i < methods.length; i++) {

        if (methods[i] .getName() .startsWith(VALIDATE_METHOD_PREFIX) &&
            methods[i] .getParameterTypes() .length == 2 &&
                PropertyChangeEvent.class.isAssignableFrom(methods[i].
                    getParameterTypes() [1])) {
            // We've found a potential validator
            Class[] exceptions = methods[i] .getExceptionTypes();
            // We don't care about the return type, but we must ensure that
            // the method throws only one checked exception, PropertyVetoException
            if (exceptions.length == 1 &&
                    PropertyVetoException.class.isAssignableFrom(exceptions[0])) {
                // We have a valid validator method
                // Ensure it's accessible (for example, it might be a method on an
                // inner class)
                methods[i].setAccessible(true);
                String propertyName = Introspector.decapitalize(methods[i].getName().
                substring(VALIDATE_METHOD_PREFIX.length()));
                validationMethodHash.put(propertyName, methods[i]);
                System.out.println(methods[i] + " is validator for property " +
                    propertyName);
            }
        }
    }
  }
public final void vetoableChange(PropertyChangeEvent e)
        throws PropertyVetoException {

    Method m = (Method) validationMethodHash.get(e.getPropertyName());

    if (m != null) {
        try {
            Object val = e.getNewValue();
            m.invoke(this, new Object[] { val, e });

        } catch (IllegalAccessException ex) {
            System.out.println("WARNING: can't validate. " +
                "Validation method "' + m + "' isn't accessible");

        } catch (InvocationTargetException ex) {
            // We don't need to catch runtime exceptions
            if (ex.getTargetException() instanceof RuntimeException)
                throw (RuntimeException) ex.getTargetException();
            // Must be a PropertyVetoException if it's a checked exception
            PropertyVetoException pex = (PropertyVetoException)
                ex.getTargetException();
            throw pex;
        }
    }
  }
         虽然,使用反射的代码要比正常的代码复杂了一点,但是他只需要测试一遍,就可以应对可能的修改,这样才能说是框架性的代码!反射是Java的核心API,所以必须掌握。 
    反射和工厂模式(Reflection and the Factory Design Pattern)
    public Object getObject(String classname, Class requiredType)
        throws FactoryException {
    try {
        Class clazz = Class.forName(classname);
        Object o = clazz.newInstance();
        if (! requiredType.isAssignableFrom(clazz))
            throw new FactoryException("Class "' + classname +
                                                     "' not of required type " + requiredType);
        // Configure the object...
        return o;
    } catch (ClassNotFoundException ex) {

        throw new FactoryException("Couldn't load class "' + classname + ""', ex);
    } catch (IllegalAccessException ex) {
        throw new FactoryException("Couldn't construct class "' + classname + "': is the no arg constructor public?", ex);
    } catch (InstantiationException ex) {
        throw new FactoryException("Couldn't construct class "' + classname +
                                     "': does it have a no arg constructor", ex);
    }
  }
使用:    MyInterface mo = (MyInterface)
    beanFactory.getObject("com.mycompany.mypackage.MyImplementation",
    MyInterface.class);
  
     使用反射时,一般都会导致我们不能确定代码是否能够正常被执行,这是就要求我们必须提供更详细的错误信息,以方便以后的处理。
    动态代理(Java 1.3 Dynamic Proxies)
    第11章(Infrastructure and Application Implementation)会详细介绍,是一个和AOP(Aspect Oriented Programming )相关的东西。

十、使用JavaBean取得灵活性(Using JavaBeans to Achieve Flexibility)

    使用JavaBeans可以让对象很容易的使用代码之外的配置。不过最好能过使用下面的这些类:
  1. PropertyEditor

  2. PropertyChangeListener

  3. VetoableChangeListener

  4. Introspector 

十一、通过程序级的注册避免单例模式(Avoid a Proliferation of Singletons by Using an Application Registry)
    传统的单例模式有很多的缺点,比如单例类将被硬编码于代码中,单例类必须自己配制,复杂的程序可能需要很多单例类,单例类不支持接口,单例类不能被继承,不能被及时的更新状态。所有的这一些都大大局限了单例类的使用。
    不过通过程序上下文(application context)可以很好的解决这些问题,首先它可以是一个正常的Java类,这就避免了所有上面的问题。他只要在程序初始化时,取得然后在程序的其他地方直接使用。甚至还可以直接配置到JNDI中。
    我觉得最大的优点就是他的可以动态配置性,这要比将他硬性写在代码中好太多。
十二、重构(Refactoring)
    重构不应该仅仅局限于代码的重构,错误消息,log,文档都应该是重构的对象。
    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章