在运行时实现接口

时间:2015-07-25 21:22:59

标签: java oop

我正在尝试创建一个API模块,它具有执行所需功能所需的所有功能。但是,只有最终开发人员需要完成的事情是根据他是否选择使用数据库或文件系统来实现该类

IContentProcess将在AssetManager中使用,它执行文件处理和其他功能。现在我正在AssetManager类中实现ContentProcess,但我真的希望使用我的jar文件的最终开发人员能够实现,以便他可以将文件保存在数据库或文件系统中。

我需要在AssetManager类中做些什么才能实现它?

public interface IContentProcessor
{

    public boolean deleteContent(String fileName) throws ResourceException;


    public boolean uploadContent(String fileName, InputStream contentStream) throws ResourceException;


    public InputStream downloadContent(String fileName) throws ResourceException;


    public boolean uploadContent(String fileName, BufferedImage imageStream) throws ResourceException;


    public boolean uploadContent(String fileName, String formatName, BufferedImage imageStream)
            throws ResourceException;


    public boolean moveContent(String fromFile, String toFile) throws ResourceException;


    public void validateFilePath(File newFile);
}

AssetManager

private IContentProcessor createContentProcessor()
    {
            ........
            return new ContentProcessorNFSImpl();

    }
    ......
        /**
         * Upload the given content.
         * 
         * @return
         */
        private boolean uploadContentStream(String filePath, InputStream contentStream)
        {
            IContentProcessor contentProcessor = createContentProcessor();
            try
            {
                return contentProcessor.uploadContent(filePath, contentStream);
            }
            catch (ResourceException rEx)
            {
                throw new SystemException(rEx.getMessage(), rEx);
            }
        }

2 个答案:

答案 0 :(得分:1)

您已使用spring对此进行了标记。您可以使用Spring dependency injection执行此操作。摆脱createContentProcessor()方法,改为使用Spring依赖注入。例如,您的课程将如下所示:

@Component
public class MyClass {

    // Will be set by Spring dependency injection
    @Autowired
    private IContentProcessor contentProcessor;

    // ...

    private boolean uploadContentStream(String filePath, InputStream contentStream)
    {
        try
        {
            return contentProcessor.uploadContent(filePath, contentStream);
        }
        catch (ResourceException rEx)
        {
            throw new SystemException(rEx.getMessage(), rEx);
        }
    }
}

然后,Spring配置将确定将使用IContentProcessor的特定实现。

如果你想在没有Spring的情况下这样做:你可以使用反射动态创建一个接口实例:

private IContentProcessor createContentProcessor() throws ClassNotFoundException,
        IllegalAccessException, InstantiationException {
    // You could get the class name from a config file
    String implClassName = "com.somepackage.ContentProcessorNFSImpl";

    // Load the class and create an instance
    // This requires the implementation to have a public no-args constructor
    return (IContentProcessor) Class.forName(implClassName).newInstance();
}

答案 1 :(得分:0)

API实施

提供一个setter方法来注入实现

public class AssetManager {
   ...
   private IContentProcessor contentProcessor
   ...

   // This method to be invoked by client to set (a.k.a inject) customer implemenation
   public void setContentProcesssor(IContentProcessor c) {
      this.contentProcessor = c;
   }
}

并从IContentProcessor contentProcessor = createContentProcessor();方法中删除uploadContentStream行。

开发人员(a.k.a API用户)代码

开发人员可以自由地实现IContentProcessor并使用setContentProcessor方法注入实现。您可以在库中提供一些预构建的实现,或者开发人员可以实现全新版本的IContentProcessor

AssetManager m = new AssetManager(...);
m.setContentProcessor(new ContentProcessorNFSImpl());
...
m.uploadContentStream(...);

此外,开发人员可以选择使用Spring Framework并在其代码中自动连接实现,而不是创建ContentProcessor的实例。