避免在使用层次结构参数的操作中进行静态绑定

2023-12-01

我发现了一个关于静态绑定的问题。

我的真实课程非常扩展,所以我将使用几个玩具课程来表达我的问题。

我们假设我们有以下层次结构。

public class Element{}

public class Element1 extends Element{}

public class Element2 extends Element{}

我有一个Stock使用不同的类Element专业化定义为Element等级制度。

public class Stock{

    public void operation(Element1 e1){
        System.out.println("Operation - " + e1.getClass().getName());
    }

    public void operation(Element2 e2){
        System.out.println("Operation - " + e2.getClass().getName());
    }
}

最后,我有一个StockManager它允许管理Stock.

public StockManager{

    Stock stock;
    public StockManager(Stock stock){
        this.stock=stock;
    }

    public void manage(List<Element> elements){
        for(Element element: elements){
            stock.operation(element);
        }
    }
}

当然,这段代码无法编译,因为Stock没有定义一个方法,其中包括Element作为论证。在这种情况下,我们可以使用不同的方法修复代码。

首先,我将能够定义一个方法来定义Element作为输入 arg,例如

public void operation(Element e){
    System.out.println("Operation - " + e.getClass().getName());
}

该方法可以定义一个开关来管理不同的具体元素(Element1, Element2)。然而,这对我来说是不可能的,因为开关违反了开/关原理,而且我有很多(很多)具体元素。

另一种选择,我可以使用类似的东西访客模式。 我可以发送Stock对象为具体元素。具体元素将负责使用Stock运营。因此,该类可以更改为:

public abstract class Element{
    public abstract void stockOperation(Stock stock);
}

public class Element1 extends Element{
    public abstract void stockOperation(Stock stock){
        stock.operation(this);
    }
}

public class Element2 extends Element{
    public abstract void stockOperation(Stock stock){
        stock.operation(this);
    }
}

And the StockManager.

public StockManager{

    Stock stock;
    public StockManager(Stock stock){
        this.stock=stock;
    }

    public void manage(List<Element> elements){
        for(Element element: elements){
            element.stockOperation(stock);
        }
    }
}

它允许在编译时确定具体元素的静态类型。并且动态绑定将负责调用stockOperation正确的具体元素的方法(Element1 or Element2)。但是!!,我在具体元素中有重复的代码,并且我将有几个具体元素。

因此,我想知道我们是否知道解决此问题的任何模式设计或任何最佳实践。 (另一种选择,可能使用反射,但我不想使用它)。


问题在于您将各个库存操作放置在库存对象中。无论您是否使用开关,只要您有另一种元素类型,您就需要通过添加新的重载来修改库存operation到它。正如您所说,您的 Stock 类应该禁止修改。

因此,您必须将所有库存操作归咎于 Element 对象本身。这基本上是您的第二个建议,但是您在每个不同的元素中进行实现。

public abstract class Element{
    public abstract void stockOperation(Stock stock);
}

public class Element1 extends Element{
    @Override
    public void stockOperation(Stock stock){
        System.out.println("Operation - Element1");
    }
}

public class Element2 extends Element{
    @Override
    public void stockOperation(Stock stock){
        System.out.println("Operation - Element2");
    }
}

您可能需要与库存对象进行通信才能进行实际操作。用传递给每个人的股票来做到这一点stockOperation,使方法可用,允许元素获取或设置库存对象内所需的任何内容,例如操作的结果。

这样,如果你有一个新的Element类型,你只需要在新的Element中编写新的操作,并且你可以保持相同的Stock类而不需要改变它。这是扩展而不是修改。

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

避免在使用层次结构参数的操作中进行静态绑定 的相关文章

随机推荐

  • 停止 NSTimer 并关闭视图控制器(快速)

    我在用NSTimer在我的中查找更新firebase数据库 我已将代码放入我的viewDidLoad NSTimer scheduledTimerWithTimeInterval 5 0 target self selector selec
  • Leakcanary 使用 Otto 报告内存泄漏

    跟进我的最后一个问题 这是我无法摆脱的第二个内存泄漏 我读到我需要根据 Activity 和 Fragment 生命周期注册和注销我的静态 Otto 总线 因此我添加了对 onStop 和 onStart 的注册和注销调用 有一个按钮可以触
  • 如何对多列进行计数(不同)

    这不起作用 select count distinct colA colB from mytable 我知道我可以通过双重选择来简单地解决这个问题 select count from select distinct colA colB fr
  • ASP.NET:WCF 和无法加载文件或程序集“App_Web_hamznvwf”

    我最近开始使用支持 AJAX 的 WCF 并且一直受到这个 NET 缓存问题的困扰 无法加载文件或程序集 App Web hamznvwf 我的服务器每天会遇到 4 到 5 次这样的问题 Win 2003 看第一篇文章 因此 我将文件从服务
  • 远程服务器命令执行

    在远程服务器上执行 shell 命令并在不实际登录的情况下获取输出的最佳方法是什么 也许用 ssh 密钥 最好用python 你的意思是不登录manually 因为实际上允许您在根本不登录的情况下执行命令的服务器将带来巨大的安全风险 看起来
  • 使用 XML 数据类型读取存储在 SQL Server 2008 R2 中的 XML 文档

    我正在使用 SQL Server 2008 R2 和 ASP NET 3 5 我在 SQL 端以 XML 形式存储数据表 NET 列的数据类型为 XML 这是将 XML 存储在 SQL Server 的表列中的示例
  • 在 vb.net 中显示加载屏幕

    当长时间的进程正在运行时 我需要显示一个屏幕或其他内容 说 正在加载 或其他内容 我正在使用 Windows Media Encoder SDK 创建一个应用程序 需要一段时间来初始化编码器 我希望在启动编码器时弹出一个屏幕 显示 正在加载
  • AttachNotSupportedException:没有提供者安装 java 代理

    我在将 Java 应用程序附加到远程 Java 虚拟机时遇到问题 我在 Windows 7 上使用 java 8u45 并且我的附加代码非常简单 import java io IOException import java util Lis
  • 在 C++ 中将数组传递给函数

    include
  • JPA RollbackException 但不在单元测试中

    我有一个 java 项目 其中包含一组单元测试 这些单元测试使用 JPA2 执行简单的更新和删除 单元测试运行没有问题 我可以验证数据库中的更改 一切都很好 我尝试在处理程序 Smartfox 扩展 中复制 粘贴相同的函数 我收到回滚异常
  • 我应该针对哪个版本的 Android 进行开发? [关闭]

    这个问题不太可能对任何未来的访客有帮助 它只与一个较小的地理区域 一个特定的时间点或一个非常狭窄的情况相关 通常不适用于全世界的互联网受众 为了帮助使这个问题更广泛地适用 访问帮助中心 刚刚开始为 Android 开发 想法是创建一个在 A
  • Flask sqlalchemy 多对多插入数据

    我试图在这里建立多对多关系Flask SQLAlchemy 但似乎不知道如何填写 多对多标识符数据库 您能帮助我了解我做错了什么以及它应该是什么样子吗 class User db Model tablename users user id
  • 如何使用 Applescript 构建和运行 Xcode?

    我正在尝试让 Xcode 使用 Applescript 构建和运行我的项目 这是同样的问题如何使用 Applescript 构建和运行 Xcode 但我认为这个答案可能已经过时了 因为它在我的机器上不起作用 我明白了 execution e
  • iOS CALayerInvalidGeometry

    我的应用程序崩溃了 并显示以下消息 由于未捕获的异常 CALayerInvalidGeometry 而终止应用程序 原因 CALayer 位置包含 NaN 2 74665e 34 nan 这里有更详细的异常消息 CALayer positi
  • 为什么碰撞不起作用,cocos2d v3?

    我用 cocos2d v3 创建了像 flappybird 这样的简单游戏 接口类 interface GameScene CCScene
  • 什么时候使用 CRC 比 MD5/SHA1 更合适?

    何时适合使用 CRC 进行错误检测 而不是使用 MD5 或 SHA1 等更现代的哈希函数 前者更容易在嵌入式硬件上实现吗 CRC 可以很好地检测数据中可能出现的随机错误 例如网络干扰 线路噪声 失真等 CRC 的计算复杂度远低于 MD5 或
  • 默认显示 Visual Studio 扩展工具栏

    在 Visual Studio 扩展中 我在 vsct 文件中将工具栏定义为 menu type Toolbar menu
  • 在什么情况下使用 EJB?网站/网络应用程序开发需要它们吗?

    EJBS 是否用于数据库支持的网站 所有人都可以访问 没有什么是永远的required当然 如果你愿意 你可以构建一个 Web 应用程序作为背后的单个大型 C 函数CGI 也就是说 EJB 确实使 Web 应用程序开发变得更加容易 它们被纳
  • SwiftUI 父子绑定:@StateObject 中的 @Published 不起作用,而 @State 起作用

    我有一个来自的自定义模态结构这个问题 代码如下 某些属性在模态视图中进行了修改 并通过Binding 问题是 当房产来自 StateObject Published更改不会反映在模式视图中 当使用一个简单的 State 最小示例 完整代码
  • 避免在使用层次结构参数的操作中进行静态绑定

    我发现了一个关于静态绑定的问题 我的真实课程非常扩展 所以我将使用几个玩具课程来表达我的问题 我们假设我们有以下层次结构 public class Element public class Element1 extends Element