工厂方法如何返回接口和抽象类的实例?

2023-12-11

执行服务Service 和 Service 是接口,因此只有抽象方法,这意味着它们的方法没有实现。那么我们如何调用,例如future.get(), es.submit(), and es.shutdown()接口类型引用的方法?例如,为什么我们可以做以下事情?

Future f = ...
f.get();

这是一个更具体的例子:

import java.util.concurrent.*;
class Factorial implements Callable<Long> {
    long n;
    public Factorial(long n) {
        this.n = n;
    }

    public Long call() throws Exception {
        if (n <= 0) {
            throw new Exception("for finding factorial, N should be > 0");
        }
        long fact = 1;
        for(long longVal = 1; longVal <= n; longVal++) {
            fact *= longVal;
        }
        return fact;
    }
}

class CallableTest {
    public static void main(String []args) throws Exception {
        long N = 20;

        Callable<Long> task = new Factorial(N);
        ExecutorService es = Executors.newSingleThreadExecutor();
        Future<Long> future = es.submit(task);

        System.out.printf("factorial of %d is %d", N, future.get());
        es.shutdown();
    }
}

这个问题得到了一些否决,因为从某种意义上来说,它有点基本,但我认为它实际上有点有趣。毕竟,像这样的工厂类Executors在您的示例中,可以指定它返回Executors。但是,正如您所指出的,这只是一个接口,您实际上需要一个实例实施 Executor如果您能够调用这些方法。为什么工厂不必告诉我们退回物品的实际类型?

如果您以前没有见过这个,可能不清楚如何做这样的事情。要记住的重要一点是,如果您有一个实现接口的类,那么声明为返回接口类型的方法可以返回该类的实例。也就是说,你可以这样做:

interface Foo { /* ... */ }

class Bar implements Foo { /* ... */ }

class Factory {
  Foo makeFoo() { 
    return new Bar( /*... */ );
  }
}

makeFoo被声明返回一个Foo, but Foo是一个接口;你实际上无法拥有它的实例。您只能拥有以下类的实例实施 Foo. Bar确实实施Foo,所以你可以返回一个实例Bar.

我们可以这样做的原因是,当需要调用对象上的方法时,该方法的实现是在我们引用的实际对象中找到的。查找方法的方式实际上有点复杂。但从概念上讲,你可能会这样想:如果你告诉我你是一个Foo,然后我可以要求您运行中声明的任何方法Foo, but you准确地决定您对该方法做什么。我只能用你的Foo输入确定我可以要求您执行哪些方法。这非常重要,也是为什么我们可以重写子类中的方法。这些被称为虚拟方法。这如此重要的原因之一是,它使我们能够使用接口,在其中我们可以透露有关我们的实现的最少量信息(我们可以选择说“我实现Foo,但这就是我告诉你的关于我自己的全部),但仍然遵守合同(即,我保证实际实现中声明的所有方法Foo).

下面的示例更深入一些,并捕获了您所看到的更多工厂模式Executors.

Code

public class InterfacesExample {

    /**
     * An interface with one method.
     */
    interface Frobber {
        /**
         * Frob the object.
         * @param object the object
         */
        void frob( Object object );
    }

    /**
     * A factory class with one method for creating printing frobber.
     */
    public static class Frobbers {
        /**
         * Returns a Frobber whose {@link Frobber#frob(Object)} method
         * prints its argument
         * @return a printing Frobber
         */
        public static Frobber newPrintingFrobber() {
            // This returns an instance of an anonymous class
            // that implements the Frobber interface.  It has 
            // to provide an implementation of frob(Object),
            // though.
            return new Frobber() {
                @Override
                public void frob( final Object object ) {
                    System.out.println( "Frobbing "+object+"..." );
                }
            };
        }

        /**
         * Returns a Frobber whose {@link Frobber#frob(Object)} method
         * prints the prefix and its argument
         * @param prefix an object
         * @return a prefixing printing Frobber
         */
        public static Frobber newPrefixingPrintingFrobber( final Object prefix ) {
            return new PrefixingPrintingFrobber( prefix );
        }

        /**
         * A private, but not anonymous class.  Instances shouldn't be
         * made with its constructor, but rather through the factory 
         * method {@link Frobbers#newPrefixingPrintingFrobber(Object)}. 
         */
        private static class PrefixingPrintingFrobber implements Frobber {
            final Object prefix;

            public PrefixingPrintingFrobber( Object prefix ) { 
                this.prefix = prefix;
            }

            @Override
            public void frob( final Object object ) {
                System.out.println( "Frobbing "+prefix+":"+object+"..." );
            } 

        }
    }

    /**
     * Create some frobbers with the factory and test them out.
     */
    public static void main( final String[] args ) {
        final Frobber f1 = Frobbers.newPrintingFrobber();
        f1.frob( 42 );

        final Frobber f2 = Frobbers.newPrefixingPrintingFrobber( "boing" );
        f2.frob( 36 );
    }
}

Output

Frobbing 42...
Frobbing boing:36...
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

工厂方法如何返回接口和抽象类的实例? 的相关文章

随机推荐

  • 在不编码的情况下设置 ASP.NET Core TagHelper 属性

    我想添加integrity属性到我的标签助手中的脚本标签 它包含一个 我不想编码的标志 这是我的标签助手 HtmlTargetElement Attributes script public class MyTagHelper TagHel
  • 任务集-python

    我有一台双四核机器 所以 我的CPU列表是0 7 我正在尝试从 python 运行任务集 mapping 2 2 2 2 2 for i in range 0 len mapping cmd taskset c str mapping r
  • 如何在 Python Turtle 中定位文本?

    例如 write First Last True align right 但具有特定的 x y 坐标 随着使用像这样的命令setposition aka goto setx or sety 在你呼叫之前定位你的乌龟write the mov
  • ggplot2 热图,带有范围值的颜色

    我想在 ggplot2 中制作热图 我的玩具数据和代码是 set seed 12345 dat lt data frame Row rep x LETTERS 1 5 times 10 Col rep x LETTERS 1 10 each
  • Flutter:obviousText,如何停止显示键入的字符

    当在使用 obliqueText true 的字段中输入文本时 每个输入的字符都会在转换为项目符号之前短暂显示 你如何阻止这种行为 这是fixed在网络 桌面上 但没有在移动设备上执行此操作的选项 您可以按照此建议创建自定义 TextEdi
  • 如何使用 jQuery 将 html 表格单元格更改为文本输入

    所以我有一个表格 如下所示 tbody thead tr th Date Registered th th Name th th Organisation th th Email th th Job Title th th LSA th t
  • 一旦我限制我的 Google API 密钥,它就不再起作用

    我有一个正在使用的 Google API 密钥 并且在 Google 地图上运行良好 我现在尝试在我的 Android 应用程序中使用 Google 地图距离矩阵 API 并且只有当我不将密钥限制在 Android 应用程序上时 我才能使其
  • WordPress 中的正则表达式错误分隔符

    我是正则表达式的新手 我有一个简单的疑问 我在 wordpress 中找到了这段代码 self preg replace wp admin i self 根据php net 上的文档 不允许作为分隔符 有人可以解释一下代码吗 你尝试过吗 从
  • 将文档字符串设置为 def 内的表达式

    我想设置func doc 作为表达式 within def def f My function help Set the docstring def g My function help An expression so not read
  • Azure DevOps:代表另一个用户创建评论

    我正在寻找一种代表另一个用户 模拟另一个用户 向工作项添加评论的方法 VssConnection connection new VssConnection new Uri url new VssClientCredentials WorkI
  • PHP - 关于将 reCAPTCHA 与 jQuery 结合使用的问题

    这是一个教程 说明如何将 jQuery 表单验证与 reCAPTCHA 结合起来 http snipplr com view 15563 jquery validating recaptcha with ajax 根据我的理解 上面的教程实
  • 如何排列图像 3x3?

    我有九张图像 如果我必须将它们排列为 3x3 这意味着 3 行和 3 列 最好的方法是什么 我应该使用 CSS 吗 3x3 图像网格 该 CSS 允许您 垂直居中图像 水平居中图像 允许各种尺寸的图像 小于网格尺寸的图像保持原始尺寸 不会出
  • WPF 数据模板教程

    我陷入了如何在 WPF 中使用 DataTamplete 的困境 有人知道一些教程或者有一系列教程来教如何使用它 我正在使用 MVVM 模式 所以如果你知道 mvvm 示例中的教程会更好 Tks 谷歌搜索 wpf datatempalte
  • jQuery“data”属性未经过 W3C 验证

    我想知道为什么这段 html 由于 data 属性而无法验证 XHTML 1 0 过渡 我已经四处寻找答案 并且我没有使用 jQuery 元数据插件 如果这很重要的话 有什么方法可以让它验证 或者转义它 这样验证器就看不到它吗 div Be
  • [Windows、Qt5、QMediaPlayer、QMediaPlaylist]:当前视频源更改时短暂的黑屏

    我正在使用 Qt5 QMediaPlayer 编写一个视频播放器 以随机播放一些视频 如下所示 int main int argc char argv QApplication a argc argv QMediaPlaylist play
  • 嵌入式Redis尝试连接真实Redis服务器,导致异常

    我正在尝试使用嵌入式 redisdev弹簧简介 我也有一个cloud连接到真实 Redis 的配置文件 但是 我的嵌入式 Redis 配置似乎尝试连接到真正的 Redis 这是我运行时遇到的错误dev轮廓 Caused by redis c
  • 复制字体时 CopyHere 无法按预期工作

    我制作了一个脚本 该脚本应该将一堆字体复制到 Windows 字体文件夹中 当我运行它时 我收到了我想要复制的文件名的输出 但没有复制任何内容 当我删除 For 循环并指定文件名时它会起作用 任何帮助表示赞赏 Const FONTS H14
  • Vue-router 无法捕获 webpack 模板中带有点的路由

    我从以下位置启动了我的应用程序网页包模板并添加了路线 edit filename to it 问题是 包含点的文件名由 Express 处理 而不是由我的 Vue 应用程序处理 换句话说 edit 123与路线匹配但是 edit 123 j
  • AttributeError:“列表”对象没有属性“_sa_instance_state”

    我收到以下错误 我不知道如何修复它 我认为这与is bestfriend关系 File usr local lib python2 7 dist packages flask app py line 1836 in call return
  • 工厂方法如何返回接口和抽象类的实例?

    执行服务Service 和 Service 是接口 因此只有抽象方法 这意味着它们的方法没有实现 那么我们如何调用 例如future get es submit and es shutdown 接口类型引用的方法 例如 为什么我们可以做以下