Methods.class中的代码重用vs策略模式和依赖注入 [英] code reuse in Methods.class vs strategy pattern and dependency injection

查看:206
本文介绍了Methods.class中的代码重用vs策略模式和依赖注入的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

状态: Fendy和Glen Best的回答同样可以接受

场景: p>

如果我在很多类 中)



必须重复使用的代码可以是任何合理的事情(需要适当的注意)静态和非静态上下文和方法制作技术)。它可以是一种算法,一个DB方法做连接,操作,关闭。任何东西。


  1. 制作类似 MyMethods.class >将所有这些方法放在中。



    1.a。 MyMethods.someMethod(); c $ c>



    1.b。设置方法 非静态,并在调用它们时 实例化整个类通过 MyMethods mm = MyMethods(); mm.someMethod();


  2. 使用 https://en.wikipedia.org/wiki/Strategy_pattern (附带的代码)。


  3. 使用依赖注入,在 https ://en.wikipedia.org/wiki/Dependency_injection#Java


问题:


  1. 测试 http://en.wikipedia.org/wiki/Unit_testing 不可能使用这种方法,会使换出后麻烦。如果您想测试课程并使用依赖



    1.a的模拟版本是否会出现并发来电或多个课程的问题?特别是在 JDBC静态方法只是一个例子?



    1.b。我认为内存负载太多了,因为整个类实例化两种方法


  2. 不要想在这个问题的上下文中使用框架。在我的头上,解释一下,或者任何优点/缺点



p> 请求:请只回答你是否有经验,深知并深入了解,可以全面,与你的答案,帮助我和社区作为一个整体! / strong>



代码:

  / **实现具体策略的类应该实现这一点。 
* Context类使用它来调用具体的策略。 * /
interface Strategy {
int execute(int a,int b);
}

/ **使用策略接口实现算法* /
class Add implements Strategy {
public int execute(int a,int b){
System.out.println(Called Add's execute());
return a + b; //用a和b做一个加法b
}
}

class Subtract implements Strategy {
public int execute(int a,int b){
System.out.println(Called Subtract's execute());
return a - b; //用a和b进行减法b
}
}

类乘法实现Strategy {
public int execute(int a,int b){
System.out.println(Called Multiply's execute());
return a * b; //与a和b进行乘法b
}
}

//使用ConcreteStrategy对象进行配置并维护
//对策略对象的引用
class Context {
private策略策略;

public Context(策略策略){
this.strategy = strategy;
}

public int executeStrategy(int a,int b){
return this.strategy.execute(a,b);
}
}

/ **测试模​​式* /
class StrategyExample {
public static void main(String [] args){
上下文上下文;

//根据不同策略的三个上下文
context = new上下文(new Add());
int resultA = context.executeStrategy(3,4);

context = new上下文(new Subtract());
int resultB = context.executeStrategy(3,4);

context = new上下文(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);
}
}


解决方案

问题其实有两个含义。



$ b


$ b

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



内存成本(我没有这方面的经验,但让我分享我的经验)

$



第一个是静态的(或组合根中的DI实例化) / strong>




  • 热门实例化,表示所有类将在应用程序启动时实例化

  • 仅实例



非静态


  • 延迟实例化,意味着类只在需要时实例化

  • 一次实例化每次使用



  • 简而言之,如果类很多,static会花费很高,如果请求很高,非静态会花费很高(例如,在for循环中)。但它不应该使你的应用程序重。



    类重用性



    1 - 巨型整体代码(一个神级可以做的几乎一切)



    优点:


    1. 很容易搜索代码(仍然依赖),你知道每个逻辑都在那里,所以你只需要看看那个大类



    2. 缺点:


      $

      b $ b


      1. 任何一种方法的修改都会在其他地方造成错误风险

      2. 违反SRP,意味着此类可以因各种原因只有一个

      3. 特别是在版本控制中,如果在分离的分支中发生修改,则很难合并,从而导致同步代码。

      1a / static class / singleton pattern



      优点:


      1. 易于使用

      2. 可随时随地使用(只需参考和致电即可使用)

      3. 实例化对象

      缺点:


      1. 难以单元测试(这是很难模拟,而在后面的时间,你会发现它需要时间准备测试环境。尤其是数据

      2. 如果有状态(有状态),在调试期间很难确定当前状态。此外,很难确定哪个功能改变了状态,可以随处改变。

      3. 倾向于有很多参数(可能在5-11左右)

      有关静态类的一些观点: p>



      3依赖注入

      实际上,这与3或 / strong>



      优点:




      • 易于模拟和单元测试

      • 必须是无状态的。如果类是无状态的,则调试和单元测试更容易

      • 支持重构



      缺点:




      • 很难调试那些不熟悉接口的人(每次重定向到该方法,

      • 创建将导致映射的分层



      状态/无状态



      我认为各国在你的应用程序设计中扮演着重要的规则。通常开发人员尝试避免在业务逻辑代码中有状态,例如:

        //获取数据
      if .IsDraft){
      //步骤1
      //步骤2
      }
      else {
      //步骤1
      //步骤3
      }

      开发人员倾向于将逻辑放在其他无状态类,或至少如下方法:

        //获取数据
      if(request.IsDraft) {
      draftRequestHandler.Modify(request);
      }
      else {
      publishedRequestHandler.Modify(request);
      }

      它将提供更好的可读性,更容易修改和单元测试。还有一个设计模式状态模式或层次状态机模式,特别是为了处理这种情况。



      单一责任原则



      IMHO,这个原则是最有利的,如果遵循。优点是:


      1. 在版本控制中,更改清楚了哪些类已被修改以及为什么

      2. <
      3. 增加模块化,低耦合和高凝聚力

      4. 在DI中,可以连接几个较小的类, ol>

        TDD(测试驱动开发)



        此设计不保证您的代码没有错误。在设计阶段和分层努力中花费时间的缺点是:


        1. 容易模拟对象进行单元测试

        2. 更容易因为单元测试和模块化而重构

        3. 更容易维护/扩展


        b $ b

        一些有用的来源



        服务定位器反模式



        使用装饰器进行交叉关注



        我的2美分:



        使用接口的好处(也适用于组合继承)



        自上而下的设计/ DI设计



        最后的想法



        这些设计和策略不是决定您的应用程序结构的关键。它仍然是建筑师将决定它。我喜欢遵循一些原则,如SOLID,KISS和GRASP,而不是决定什么是最好的结构。据说依赖注入遵循这些原则中的大多数,但太多的抽象和不正确的组件设计将导致与单例模式的滥用相同。


        Status: Answers of Fendy and Glen Best are equally acceptable and honored by me but since one can be accepted and bounty be given, I choose Fendy's answer.

        Scenario:

        If I have some code that has to be reused many times in many classes (rarely with minor parameter changes which is obvious) and concurrent threads, Which approach to go for?

        The code that has to be reused can be any sane thing (with appropriate care of static and non-static context in mind and method making techniques). It can be an algorithm, A DB method doing connect,operate,close. Anything.

        1. Make some class like MyMethods.class and put all those methods in it.

          1.a. Make methods static and call (by all classes and concurrent threads) directly as MyMethods.someMethod();

          1.b. Make methods non-static and at the time to call them, instantiate the whole class by MyMethods mm = MyMethods(); mm.someMethod();

        2. Use Strategy pattern stated at https://en.wikipedia.org/wiki/Strategy_pattern (code attached here with).

        3. Use dependency injection stated at https://en.wikipedia.org/wiki/Dependency_injection#Java

        Problems:

        1. Some people would say Unit test http://en.wikipedia.org/wiki/Unit_testing wont be possible with this approach, will make trouble in swaping out latter. if you want to test your class and use a mock version of the dependency

          1.a. Will there be any problems with concurrent calls or multiple classes? specially in JDBC static methods for just an example?

          1.b. I think it would make too much memory load as a whole class would be instanticated many times just to call one or two methods

        2. Thats way over my head, do explain that and or any advantages/disadvantages

        3. I do Not want to use a framework in context to this question.. Thats way over my head, do explain that and or any advantages/disadvantages

        4. Awaiting any other strategies or recommendations, if any.

        Request: Please only answer if you are experienced and know the implications deeply and can comprehensively, with your answer, help me and the community as a whole!

        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 );
            }
        }
        

        解决方案

        Your question actually has two meanings.

        that has to be reused many times in many classes

        It can be a context of design pattern (reusable component) or memory cost (class instantiation). Talking from two different perspective:

        Memory Cost (I had little experience on this, but let me share my experience)

        This section actually only cover 2 kind of instantiation.

        First is static (or DI instantiation in composition root)

        • Eager instantiation, means all class will be instantiated when application start
        • One time instantiation only

        Non-static

        • Lazy instantiation, means class will only be instantiated when needed
        • One time instantiation every use

        In short, static will cost high if the class is many, and non-static will cost high if the request is high (inside for loop, for example). But it should not make your application heavy. Most operation in java / csharp are creates objects though.

        Class Reusability

        1 - mega monolithic code (one god class able to do almost everything)

        Advantages:

        1. Easy to search for code (still depends though), you know that every logic lies there so you just need to look at that big class
        2. If it is static, you can just call it anywhere without worrying about the instantiation

        Disadvantages:

        1. Any modification for one method creates risk for error in other places
        2. Violates SRP, means this class can be changed by various reason, not only one
        3. Especially in versioning, it is harder to merge if modification happen in separated branches, resulting effort in synchronize code

        1a / static class / singleton pattern

        Advantages:

        1. Easy to use
        2. Can be used anywhere (just reference and call, and done)
        3. Not need to instantiate object

        Disadvantages:

        1. Hard to unit test (it is hard to mock, and at latter time, you will find it is taking time to prepare the test environment. Especially with data
        2. If stateful (has state), it is hard to determine current state, during debugging. Moreover, it is hard to determine which function changes the state, in can be changed from everywhere
        3. Tend to have much parameters (maybe around 5-11)

        Some point about static class: see this question

        2 strategy pattern

        Actually this has the same design with 3 or composition over inheritance.

        3 dependency injection

        Advantages:

        • Easy to mock and unit test
        • Must be stateless. It is easier to debug and unit test if the class is stateless
        • Support to be refactored

        The disadvantage:

        • Hard to debug for those who does not familiar with interfaces (everytime you redirect to the method, it goes to interface's)
        • Creates layering which will resulting to mapping

        State / Stateless

        I think states plays important rules in your application design. Usually developers try to avoid having states in business logic code, such as:

        // get data
        if(request.IsDraft){
          // step 1
          // step 2
        }
        else{
          // step 1
          // step 3
        }
        

        Developers tend to put the logic in other stateless class, or at least methods such as:

        // get data
        if(request.IsDraft){
            draftRequestHandler.Modify(request);
        }
        else{
            publishedRequestHandler.Modify(request);
        }
        

        It will provide in better readability, and easier for modification and unit tests. There is one design pattern state pattern or hierarchial state machine pattern too, especially to handle some cases like this.

        Single Responsibility Principle

        IMHO, this principle is has the most benefit if followed. The advantages are:

        1. In versioning, the changes are clear about which class has been modified and why
        2. In DI, several smaller classes can be wired up, creating flexibility in both usage and unit test
        3. Increase modularity, low coupling and high cohesion

        TDD (Test Driven Development)

        This design does not guarantee your code free of bugs. In cons of costing time at design phase and layering effort, it has the benefit of:

        1. Easy to mock object for unit test
        2. Easier to refactor because of unit test and modularity
        3. Easier to maintain / extend

        Some useful sources

        Service Locator Anti Pattern

        Using Decorator for cross-cutting concern

        My 2 cents:

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

        Doing top down design / DI design

        Final Thoughts

        Those designs and strategies are not the key which will determine your application structure. It still the architect who will determine it. I prefer to follow some principles such as SOLID, KISS and GRASP, rather than deciding what is the best structure. It is said that Dependency Injection follow the most of those principles, but too much abstraction and incorrect components design will resulting the same with the misuse of singleton pattern.

        这篇关于Methods.class中的代码重用vs策略模式和依赖注入的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆