Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/390.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何重构使用;战略;? 问题_Java_Design Patterns_Refactoring_Strategy Pattern - Fatal编程技术网

Java 如何重构使用;战略;? 问题

Java 如何重构使用;战略;? 问题,java,design-patterns,refactoring,strategy-pattern,Java,Design Patterns,Refactoring,Strategy Pattern,我有一个很大的类(大约1500 LOC),它使用不同的“策略”将数据从一个对象转换到另一个对象。 我这里有一个该类的代表: public class FooService implements FooProcessing { FooRequestTransformer fooRequestTransformer; AnotherService anotherService; InstanceVar1 iVar1; InstanceVar2 iVar2; .

我有一个很大的类(大约1500 LOC),它使用不同的“策略”将数据从一个对象转换到另一个对象。 我这里有一个该类的代表:

public class FooService implements FooProcessing {
    FooRequestTransformer fooRequestTransformer;
    AnotherService anotherService;
    InstanceVar1 iVar1;
    InstanceVar2 iVar2;    
...
此类使用一个接口(类外部):

interface TransformerStrategy {
    public FooRequest transform(FooResponse response);
}
传递到此方法中(在FooService类中):

入口点在这里,它使用
getResponse()
方法并匿名创建
TransformerStrategy

public List<Foo> getFooForSomeFlow1(Param1 param1, Param2 param2, ...){
    FooResponse fooResponse = anotherService.baz(fooRequest);

    TransformerStrategy myTransformerStrategy = new TransformerStrategy() {
        public FooRequest transform(FooResponse fooResponse) {
            fooRequestTransformer.transform(param1, param2, iVar1, iVar2) 
        }
    }

    FooResponse fooResponse = getResponse(fooResponse, myTransformerStrategy);
    ...//other code
}
其中一条评论说,“为了测试目的,将匿名类转换为内部类”。然而,他们只改变了其中的一个,而留下了其余的人。这就像他们开始了重构的过程,在中间停止了。

因此,我想我可以完成重构过程,将所有匿名类移到内部类,然后最终移出这些类,并将
StrategyProvider
移到外部类。 问题是“将匿名转换为内部”增加了更多的样板文件(请参见上面的
ABCTransformerStrategy
;我必须将所有数据传递给构造函数),我不确定通过执行此重构过程我能获得多少收益

我有两个问题:

  • 我应该继续这样做吗
  • 或者,我是否可以应用另一种设计模式来更合适并真正简化此代码

  • 谢谢

    如果您想提供一组相关对象,您可以始终使用
    抽象工厂
    。这不是一个简单的设计模式,但最适合您


    看看这个:

    您的提供者类实际上是一个,这正是我要建议的

    通过将逻辑从
    getFooForSomeFlow1
    和类似方法中移出,您创建了非常松散耦合的代码,这总是需要的

    仅仅出于个人偏好,我会使用一种方法来返回实例,该方法将
    int
    值作为鉴别器。这些int可以是provider类中的静态最终变量,如:

    public static final int ABCTransformerStrategy = 1;
    
    此外,通过将工厂类抽象化,您将不再需要在每次需要使用时实例化该类,从而使代码更加简洁

    编辑


    正如所建议的,使用
    Enum
    将值转换为它们所表示的具体类是一种更理想、语义更正确的方法。

    根据您提供的代码示例,它表面上很复杂。为什么不简单

    public List<Foo> getFooForSomeFlow1(Param1 param1, Param2 param2, ...)
    {
        FooResponse fooResponse = anotherService.baz(fooRequest);
    
        FooRequest  fooRequest = fooRequestTransformer
                                     .transform(param1, param2, iVar1, iVar2); 
    
        FooResponse fooResponse2 = anotherService.bar(fooRequest);
        ...//other code
    }
    
    公共列表getFooForSomeFlow1(Param1 Param1,Param2 Param2,…)
    {
    FooResponse-FooResponse=anotherService.baz(fooRequest);
    FooRequest=fooRequestTransformer
    .转换(param1、param2、iVar1、iVar2);
    FooResponse fooResponse2=anotherService.bar(fooRequest);
    …//其他代码
    }
    

    除非您没有向我们展示其他正在发生的事情。

    将每个方法转换为它自己的类(即方法作为对象),这与原始重构的过程类似。如果您需要在对象实现时集中访问所有这些方法。根据您的描述,这听起来像是在从一种类型转换为另一种类型,因此让抽象工厂接受两个
    参数,并将适当的方法作为类组合的对象实例返回给调用方。

    我尝试了Unreputable的方法,并在
    getResponse()上尝试了“Inline方法”方法,但它内联了一些重复的代码(这就是为什么我们首先将重复的代码提取到
    getResponse()
    )。我应该澄清一下,在我的问题中,
    getResponse()
    中的代码比我显示的要多。
    至于创建工厂,我无法证明在类中引入更多样板文件和LOC是合理的,特别是因为我必须将大量数据传递到工厂方法和/或内部类中

    我们所做的是用如下方法包装匿名内部类:

    private TransformerStrategy createTransformerStrategyWithABCValues(Param1 param1, Param2 param2, IVar ivar, IVar1 ivar2) {
        return new TransformerStrategy() {
            public FooRequest transform(FooResponse response) {
                return FooRequestTransformer.transform(
                        param1,
                        param2,
                        iVar1,
                        iVar2);
            }
        };
    }
    
    现在调用方法如下所示:

    public List<Foo> getFooForSomeFlow1(Param1 param1, Param2 param2, ...){
        FooResponse fooResponse = anotherService.baz(fooRequest);
        TransformerStrategy myTransformerStrategy = createTransformerStrategyWithABCValues(param2, param2, iVar1, iVar2);
        FooResponse fooResponse = getResponse(fooResponse, myTransformerStrategy);
        ...//other code
    }
    
    公共列表getFooForSomeFlow1(Param1 Param1,Param2 Param2,…){
    FooResponse-FooResponse=anotherService.baz(fooRequest);
    TransformerStrategy myTransformerStrategy=创建TransformerStrategyWithABCValues(参数2、参数2、iVar1、iVar2);
    FooResponse FooResponse=getResponse(FooResponse,myTransformerStrategy);
    …//其他代码
    }
    
    在这个过程中,我们发现这5种策略有一些重复,因此我们可以将其归纳为3种策略。我们去掉了StrategyProvider类以及提供的内部类


    使用这种方法,现在调试/维护起来比较容易,我们能够从代码中删除大量重复的内容。

    对不起,当我意识到.np时删除了,我删除了我的评论,并进一步澄清了问题。使用
    int
    的首选替代方法是使用
    Enum
    来确定需要创建哪个具体实例。同意。我现在会考虑我的答案:)
    private TransformerStrategy createTransformerStrategyWithABCValues(Param1 param1, Param2 param2, IVar ivar, IVar1 ivar2) {
        return new TransformerStrategy() {
            public FooRequest transform(FooResponse response) {
                return FooRequestTransformer.transform(
                        param1,
                        param2,
                        iVar1,
                        iVar2);
            }
        };
    }
    
    public List<Foo> getFooForSomeFlow1(Param1 param1, Param2 param2, ...){
        FooResponse fooResponse = anotherService.baz(fooRequest);
        TransformerStrategy myTransformerStrategy = createTransformerStrategyWithABCValues(param2, param2, iVar1, iVar2);
        FooResponse fooResponse = getResponse(fooResponse, myTransformerStrategy);
        ...//other code
    }