2015-07-03 32 views
4

查看以下模型:最佳做法使用代码的接口,但隐藏从最终用户的内部方法

interface Context { 
    BeanFactory getBeanFactory(); // public method 
    void refresh(); // public method 
    void destroy(); // public method 
} 

interface BeanFactory { 
    <T> T getBean(String id); // public method 
    void destroyBeans(); // should be private method for user, but visible for Context 
} 

class ContextImpl implements Context { 
    private BeanFactory beanFactory; 

    @Override 
    public void destroy() { 
     beanFactory.destroyBeans(); 
    } 
} 

ContextImpl使用BeanFactory界面,这就是为什么方法destroyBeans()是摆在那里。但我不希望它在那里,因为它是内部API,应该隐藏给用户。

我想到使用AbstractBeanFactory参考与Context内的受保护destroyBeans()方法。这将解决暴露方法给最终用户的问题,但将用抽象类替换接口。

另一个变体是创建另一个接口,它将扩展最终用户界面,并在Context中使用它。这将破坏用户创建自己的BeanFactory实现的能力。

我想知道是否有一个知名解决方案的问题或只是看到另一种选择。

+1

对我来说,在界面中假设有私有方法是没有意义的。顾名思义,它是一个“INTERFACE”,内部实现(我的意思是私有方法)不应该成为恕我直言。 – Alp

+0

你可以有两个接口,一个包含getBean()方法,另一个接口扩展它并添加'destroyBeans()'。 – biziclop

回答

2

您可以在一个又一个的面向用户的方法分离成一个面向用户的界面,休息。

interface Context { 
    BeanFactory getBeanFactory(); // public method 
    void refresh(); // public method 
    void destroy(); // public method 
} 

interface BeanFactory { 
    <T> T getBean(String id); // public method 
} 

interface DestroyableBeanFactory extends BeanFactory { 
    void destroyBeans(); // should be private method for user, but visible for Context 
} 

class ContextImpl implements Context { 
    private DestroyableBeanFactory beanFactory; 

    // internally we demand a DestroyableBeanFactory but we only 
    // expose it as BeanFactory 
    public BeanFactory getBeanFactory() { 
     return beanFactory; 
    } 
    @Override 
    public void destroy() { 
     beanFactory.destroyBeans(); 
    } 
} 

更新:如果你担心呼叫者您铸造BeanFactoryDestroyableBeanFactory,并呼吁它destroyBeans(),你可以返回一个只读视图,而不是:

class ContextImpl implements Context { 
    private DestroyableBeanFactory beanFactory; 

    // to be extra safe, we create a read-only wrapper 
    // for our bean factory 
    public BeanFactory getBeanFactory() { 
     return new BeanFactory() { //written as an anon inner class for brevity, ideally you should cache this read-only wrapper instance 
      public <T> T getBean(String id) { 
       return beanFactory.getBean(id); 
      } 
     }; 
    } 
    ... 
    } 

通过这种方式访问​​beanFactory字段的值的唯一方法是通过反射(或者可选地,序列化)。但是,如果你只是想防御顽皮的开发者偷偷摸摸而不是恶意攻击者,那么你应该没问题。

+0

暴露'BeanFactory'而不是'DestroyableBeanFactory' +1 – maskacovnik

+0

这是迄今为止最好的,但是用户可以施放引用并调用方法。如果我们使接口包本地化,用户将无法创建BeanFactory实现。这就是为什么我想看到其他变体,例如使用其他技术,如助手类。 – AdamSkywalker

+0

@AdamSkywalker在一天结束时,用户可以使用反射来调用任何方法。如果你需要完全隐藏这个,你可以使用组合而不是继承。我也会掀起一个例子。 – biziclop

1

看看这个问题:Protected in Interfaces
这是关于保护方法,但有很好的解释了这个问题。
我会用新的抽象类,因为这:

abstract ABeanFactory { 
    abstract <T> T getBean(String id); 
    final void destroyBeans(){} 
} 

或使用这样的第二个接口:

interface Context { 
    BeanFactoryPrivate getBeanFactory(); 
    void refresh(); // public method 
    void destroy(); 
} 

interface BeanFactory { 
    <T> T getBean(String id); 
} 

interface BeanFactoryPrivate extends BeanFactory{ 
    void destroyBeans(); 
} 

class ContextImpl implements Context { 
    private BeanFactoryPrivate beanFactory; 

    @Override 
    public void destroy() { 
     beanFactory.destroyBeans(); 
    } 
} 

未测试