草庐IT

java - Methods.class 中的代码重用 vs 策略模式和依赖注入(inject)

coder 2024-03-10 原文

关闭。这个问题需要更多focused .它目前不接受答案。












想改善这个问题吗?更新问题,使其仅关注一个问题 editing this post .

2年前关闭。




Improve this question




Status: Fendy 和 Glen Best 的回答是 同样可以接受 并受到我的尊重,但既然可以接受并给予赏金,我选择 Fendy 的答案。

Scenario:

如果我有 一些代码 多次重复使用多类 (很少有明显的微小参数更改)和并发线程,采用哪种方法?

必须重用的代码可以是任何理智的东西(适当注意静态和非静态上下文以及方法制作技术)。它可以是一个算法,一个做连接、操作、关闭的数据库方法。任何事物。

  • 创建一些类,如 MyMethods.class将所有这些方法放入其中 .

    1.a.制作 方法 static并直接调用(由所有类和并发线程)作为 MyMethods.someMethod();
    1.b.制作 方法 non-static而当时给他们打电话, instantiate全类来自 MyMethods mm = MyMethods(); mm.someMethod();
  • 使用 策略模式 声明于 https://en.wikipedia.org/wiki/Strategy_pattern (此处附有代码)。
  • 使用 依赖注入(inject) 声明于 https://en.wikipedia.org/wiki/Dependency_injection#Java

  • Problems:
  • 有人会说单元测试 http://en.wikipedia.org/wiki/Unit_testing 不可能用这种方法,将使 换出问题后者。如果你想测试你的类(class)并使用 模拟版依赖

    1.a. 会不会有问题并发调用或多个类?特别是在 JDBC static methods举个例子?

    1.b.我认为它会做得太多内存负载作为 全类会instanticated很多次只是为了调用一两个方法
  • 这超出了我的理解,请解释一下和/或任何优点/缺点
  • 不要使用框架 在这个问题的上下文中.. 那是我无法理解的方式,请解释一下和/或任何优点/缺点
  • 等待任何其他策略或建议(如果有)。

  • Request:请仅在您有经验并深入了解其含义并且能够通过您的回答全面帮助我和整个社区的情况下回答!

    Code:
    /** The classes that implement a concrete strategy should implement this.
    * The Context class uses this to call the concrete strategy. */
    interface Strategy {
        int execute(int a, int b); 
    }
    
    /** Implements the algorithm using the strategy interface */
    class Add implements Strategy {
        public int execute(int a, int b) {
            System.out.println("Called Add's execute()");
            return a + b;  // Do an addition with a and b
        }
    }
    
    class Subtract implements Strategy {
        public int execute(int a, int b) {
            System.out.println("Called Subtract's execute()");
            return a - b;  // Do a subtraction with a and b
        }
    }
    
    class Multiply implements Strategy {
        public int execute(int a, int b) {
            System.out.println("Called Multiply's execute()");
            return a * b;   // Do a multiplication with a and b
        }    
    }
    
    // Configured with a ConcreteStrategy object and maintains
    // a reference to a Strategy object 
    class Context {
        private Strategy strategy;
    
        public Context(Strategy strategy) {
            this.strategy = strategy;
        }
    
        public int executeStrategy(int a, int b) {
            return this.strategy.execute(a, b);
        }
    }
    
    /** Tests the pattern */
    class StrategyExample {
        public static void main(String[] args) {
            Context context;
    
            // Three contexts following different strategies
            context = new Context(new Add());
            int resultA = context.executeStrategy(3,4);
    
            context = new Context(new Subtract());
            int resultB = context.executeStrategy(3,4);
    
            context = new Context(new Multiply());
            int resultC = context.executeStrategy(3,4);
    
            System.out.println("Result A : " + resultA );
            System.out.println("Result B : " + resultB );
            System.out.println("Result C : " + resultC );
        }
    }
    

    最佳答案

    你的问题其实有两层意思。

    that has to be reused many times in many classes



    它可以是设计模式(可重用组件)或内存成本(类实例化)的上下文。从两个不同的角度讲:

    内存成本 (我在这方面的经验很少,但让我分享我的经验)

    本节实际上只涵盖了 2 种实例化。

    首先是静态(或组合根中的 DI 实例化)
  • Eager 实例化,意味着所有类将在应用程序启动时实例化
  • 仅一次实例化

  • 非静电
  • 延迟实例化,意味着类只会在需要时才实例化
  • 每次使用一次实例化

  • 简而言之,如果类很多,静态成本会很高,如果请求很高(例如在 for 循环中),非静态成本会很高。但它不应该使您的应用程序繁重。不过,java/csharp 中的大多数操作都是创建对象。

    类重用性

    1 - 大型单体代码(一个神级几乎可以做所有事情)

    好处:
  • 易于搜索代码(仍然取决于),您知道每个逻辑都在那里,所以您只需要查看那个大类
  • 如果它是静态的,你可以在任何地方调用它而不必担心实例化

  • 缺点:
  • 对一种方法的任何修改都会在其他地方产生错误风险
  • 违反SRP,意味着这个类可以被各种原因改变,不仅仅是一个
  • 尤其是在版本控制中,如果修改发生在分离的分支上更难合并,导致代码同步费力

  • 1a/静态类/单例模式

    好处:
  • 易于使用
  • 可以在任何地方使用(只需引用和调用,就完成了)
  • 不需要实例化对象

  • 缺点:
  • 很难单元测试(很难mock,后面你会发现准备测试环境需要时间。尤其是数据
  • 如果有状态(有状态),则在调试期间很难确定当前状态。而且,很难确定哪个函数改变了状态,在任何地方都可以改变
  • 往往有很多参数(可能在 5-11 左右)

  • 关于静态类的一些观点:see this question

    2 策略模式

    实际上这与 3 或 composition over inheritance 具有相同的设计.

    3 依赖注入(inject)

    好处:
  • 易于模拟和单元测试
  • Must be stateless .如果类是无状态的,调试和单元测试更容易
  • 支持重构

  • 缺点:
  • 对于那些不熟悉接口(interface)的人来说很难调试(每次重定向到方法时,它都会转到接口(interface)的)
  • 创建分层,这将导致映射

  • 有状态/无状态

    我认为状态在您的应用程序设计中起着重要的作用。通常开发人员会尽量避免在业务逻辑代码中出现状态,例如:
    // get data
    if(request.IsDraft){
      // step 1
      // step 2
    }
    else{
      // step 1
      // step 3
    }
    

    开发者倾向于把逻辑放在其他 stateless类,或至少方法,例如:
    // get data
    if(request.IsDraft){
        draftRequestHandler.Modify(request);
    }
    else{
        publishedRequestHandler.Modify(request);
    }
    

    它将提供更好的可读性,并且更容易修改和单元测试。有一种设计模式 state pattern or hierarchial state machine pattern也是,特别是处理这样的一些情况。

    单一职责原则

    恕我直言,如果遵循这一原则,则 yield 最大。优点是:
  • 在版本控制中,更改很清楚哪些类被修改以及为什么
  • 在 DI 中,可以连接几个较小的类,从而在使用和单元测试方面创造灵活性
  • 增加模块化、低耦合、高内聚

  • TDD(测试驱动开发)

    这种设计不能保证您的代码没有错误。在设计阶段和分层工作中花费时间的缺点是,它具有以下好处:
  • 易于模拟单元测试的对象
  • 由于单元测试和模块化,更容易重构
  • 更易于维护/扩展

  • 一些有用的来源

    Service Locator Anti Pattern

    Using Decorator for cross-cutting concern

    我的 2 美分:

    The benefit of using interface (also apply for composition ofer inheritance)

    Doing top down design / DI design

    最后的想法

    这些设计和策略不是决定您的应用程序结构的关键。决定它的仍然是建筑师。我更喜欢遵循一些原则,例如 SOLID、KISS 和 GRASP,而不是决定什么是最好的结构。据说依赖注入(inject)遵循了大部分原则,但是过多的抽象和错误的组件设计也会导致滥用单例模式。

    关于java - Methods.class 中的代码重用 vs 策略模式和依赖注入(inject),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17315289/

    有关java - Methods.class 中的代码重用 vs 策略模式和依赖注入(inject)的更多相关文章

    1. ruby - 如何从 ruby​​ 中的字符串运行任意对象方法? - 2

      总的来说,我对ruby​​还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用

    2. ruby - 其他文件中的 Rake 任务 - 2

      我试图在一个项目中使用rake,如果我把所有东西都放到Rakefile中,它会很大并且很难读取/找到东西,所以我试着将每个命名空间放在lib/rake中它自己的文件中,我添加了这个到我的rake文件的顶部:Dir['#{File.dirname(__FILE__)}/lib/rake/*.rake'].map{|f|requiref}它加载文件没问题,但没有任务。我现在只有一个.rake文件作为测试,名为“servers.rake”,它看起来像这样:namespace:serverdotask:testdoputs"test"endend所以当我运行rakeserver:testid时

    3. ruby-on-rails - Ruby net/ldap 模块中的内存泄漏 - 2

      作为我的Rails应用程序的一部分,我编写了一个小导入程序,它从我们的LDAP系统中吸取数据并将其塞入一个用户表中。不幸的是,与LDAP相关的代码在遍历我们的32K用户时泄漏了大量内存,我一直无法弄清楚如何解决这个问题。这个问题似乎在某种程度上与LDAP库有关,因为当我删除对LDAP内容的调用时,内存使用情况会很好地稳定下来。此外,不断增加的对象是Net::BER::BerIdentifiedString和Net::BER::BerIdentifiedArray,它们都是LDAP库的一部分。当我运行导入时,内存使用量最终达到超过1GB的峰值。如果问题存在,我需要找到一些方法来更正我的代

    4. ruby-on-rails - Rails 3 中的多个路由文件 - 2

      Rails2.3可以选择随时使用RouteSet#add_configuration_file添加更多路由。是否可以在Rails3项目中做同样的事情? 最佳答案 在config/application.rb中:config.paths.config.routes在Rails3.2(也可能是Rails3.1)中,使用:config.paths["config/routes"] 关于ruby-on-rails-Rails3中的多个路由文件,我们在StackOverflow上找到一个类似的问题

    5. ruby-on-rails - Rails - 子类化模型的设计模式是什么? - 2

      我有一个模型:classItem项目有一个属性“商店”基于存储的值,我希望Item对象对特定方法具有不同的行为。Rails中是否有针对此的通用设计模式?如果方法中没有大的if-else语句,这是如何干净利落地完成的? 最佳答案 通常通过Single-TableInheritance. 关于ruby-on-rails-Rails-子类化模型的设计模式是什么?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.co

    6. ruby-on-rails - Railstutorial : db:populate vs. 工厂女孩 - 2

      在railstutorial中,作者为什么选择使用这个(代码list10.25):http://ruby.railstutorial.org/chapters/updating-showing-and-deleting-usersnamespace:dbdodesc"Filldatabasewithsampledata"task:populate=>:environmentdoRake::Task['db:reset'].invokeUser.create!(:name=>"ExampleUser",:email=>"example@railstutorial.org",:passwo

    7. ruby - 如何在 buildr 项目中使用 Ruby 代码? - 2

      如何在buildr项目中使用Ruby?我在很多不同的项目中使用过Ruby、JRuby、Java和Clojure。我目前正在使用我的标准Ruby开发一个模拟应用程序,我想尝试使用Clojure后端(我确实喜欢功能代码)以及JRubygui和测试套件。我还可以看到在未来的不同项目中使用Scala作为后端。我想我要为我的项目尝试一下buildr(http://buildr.apache.org/),但我注意到buildr似乎没有设置为在项目中使用JRuby代码本身!这看起来有点傻,因为该工具旨在统一通用的JVM语言并且是在ruby中构建的。除了将输出的jar包含在一个独特的、仅限ruby​​

    8. ruby - 解析 RDFa、微数据等的最佳方式是什么,使用统一的模式/词汇(例如 schema.org)存储和显示信息 - 2

      我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i

    9. ruby-on-rails - Rails 源代码 : initialize hash in a weird way? - 2

      在rails源中:https://github.com/rails/rails/blob/master/activesupport/lib/active_support/lazy_load_hooks.rb可以看到以下内容@load_hooks=Hash.new{|h,k|h[k]=[]}在IRB中,它只是初始化一个空哈希。和做有什么区别@load_hooks=Hash.new 最佳答案 查看rubydocumentationforHashnew→new_hashclicktotogglesourcenew(obj)→new_has

    10. ruby-on-rails - Rails - 一个 View 中的多个模型 - 2

      我需要从一个View访问多个模型。以前,我的links_controller仅用于提供以不同方式排序的链接资源。现在我想包括一个部分(我假设)显示按分数排序的顶级用户(@users=User.all.sort_by(&:score))我知道我可以将此代码插入每个链接操作并从View访问它,但这似乎不是“ruby方式”,我将需要在不久的将来访问更多模型。这可能会变得很脏,是否有针对这种情况的任何技术?注意事项:我认为我的应用程序正朝着单一格式和动态页面内容的方向发展,本质上是一个典型的网络应用程序。我知道before_filter但考虑到我希望应用程序进入的方向,这似乎很麻烦。最终从任何

    随机推荐