为输入的重叠排列/组合创建可重用的类

问题描述 投票:0回答:1

我遇到了一个设计问题,我有不同的实现来保存数据和处理不同工具的其他事情。我使用工厂设计来保存数据,并从数据库中获取数据。

class SaveDataService {
  public void saveData(Data data) {
  }

  public List<Tool> getTools() {
    return List.of();
  }
}

class FishToolSaveDataService extends SaveDataService {
  @Override
  public void saveData(Data data) {
  }

  @Override
  public List<Tool> getTools() {
    return List.of(Tool.FISH);
  }
}

class DogSaveDataService extends SaveDataService {
  @Override
  public void saveData(Data data) {
  }

  @Override
  public List<Tool> getTools() {
    return List.of(Tool.DOG);
  }
}
class Data {
  JsonNode data;
  int version;
}

enum Tool {
  FISH,
  DOG
}

所以,My Factory 映射器基于枚举工具

现在我为每个工具维护一个版本,但每个版本的保存实现都会发生变化。如何在不使用 if else 检查 saveData(Data data) 方法实现的情况下维护它。

我尝试了简单的 if/else 检查版本的 saveData 方法,但如果我有五个不同的版本并且两个不同的工具具有相同的不同版本保存逻辑,它会延长很长时间。那是在复制我的代码。

我如何设计这个版本以便我可以重用我的代码?

我总共有 15 个工具实现,我从总共 3 个工具的第 2 版开始,但将来会出现更多版本和更多工具。

java oop design-patterns factory-pattern ooad
1个回答
0
投票

看来问题陈述是能够创建可以容纳不同工具类型和版本组合的逻辑的类。这是一个复杂的问题陈述,只能通过示例来回答。

首先创建一个接口来表示保存特定版本的逻辑:

public interface VersionDataService {
    public void saveVersionData(Data data);
}

为不同的版本定义一些具体/通用的逻辑。

public class AlphaVersionDataService {

    public void saveVersionData(Data data) {

         //logic for saving data for alpha versions
    }
}

public class BetaVersionDataService {

    public void saveVersionData(Data data) {

         //logic for saving data for beta versions
    }
}

现在您可能需要根据非通用的工具类型执行特定逻辑。为此,您可以创建更专业的子类,如下所示:

public class GammaFishVersionDataService {

    public void saveVersionData(Data data) {

         //logic for saving data for Gamma Version for Fishes only
    }
}

public class GammaDogVersionDataService {

    public void saveVersionData(Data data) {

         //logic for saving data for Gamma Version for Dogs only
    }
}

我们现在创建一个

VersionDataServiceFactory
来放置地图。该地图将包含针对不同排列/组合预先创建的
VersionDataService
对象。 (请参阅最后的示例,稍后会更有意义)

class VersionDataServiceFactory {

   private Map<String,VersionDataService> versionDataServicesMap;

   public VersionDataService(Map<String,VersionDataService> versionDataServicesMap) {
       this.versionDataServicesMap= versionDataServicesMap;
   }

   public VersionDataService get(int version,Tool tool) {
      //returns the pre-created object for the given version and tool combination
      return versionDataServicesMap.get(version,tool)
   }
}


class SaveDataService {

  protected VersionDataServiceFactory versionDataServiceFactory;
 
  public SaveDataFactory(SaveDataFactory versionDataServiceFactory) {
     this.versionDataServiceFactory = versionDataServiceFactory;
  }
  
  //other methods unchanged...
  
}

class FishToolSaveDataService extends SaveDataService {

    @Override
    public void saveData(Data data) {
       //get the VersionDataService instance based on the version and tool type.
       VersionDataService versionDataService = versionDataServiceFactory.get(data.getVersion(),Tool.FISH);
       //save the data.
       versionDataService.saveVersionData(data);
    }

    @Override
    public List<Tool> getTools() {
       return List.of(Tool.FISH);
    }
}

现在让我们把所有这些放在一起:

AlphaVersionDataService alpha = new AlphaVersionDataService();
GammaDogVersionDataService gammaDog = new GammaDogVersionDataService();
Map<String,VersionDataService> versionDataServicesMap = new HashMap<>();

String alphaDogKey = Tool.Dog.toString()+"1"; //just a key combination for tool type + version
String alphaFishKey = Tool.Fish.toString()+"1"; //just a key combination for tool type + version
String gammaDogKey = Tool.Dog.toString()+"2"; //just a key combination for tool type + version
map.put(alphaDogKey,alpha);
map.put(alphaFishKey,alpha);//notice how we used the same alpha object for two different Tools? This is how we saved code duplication without using if-else :)
map.put(gammaDogKey,gammaDog);

VersionDataServiceFactory factory = new VersionDataServiceFactory(versionDataServicesMap);

SaveDataService saveDataService = new FishToolDataService(factory);
saveDataService.save(data); 

注意

alpha
对象是如何在 Fish 和 Dog alpha 版本中重复使用的。这解决了您在不使用 if-else 的情况下为不同工具类型重用代码的目标。另请注意,当调用
saveDataService.save(data);
时,它会自动为给定的工具类型和版本组合获取正确的
VersionDataService
实现。


注意:这是一个稍微复杂的设计问题。该代码尚未经过测试,但仅表示可以遵循的方法。还有很多可以做的改进,例如使用

Decorator
模式来避免为每个版本 + 工具组合创建太多的子类或使用
AbstractFactory
模式,或定义一个名为
VersionDataKey
的类来表示工厂地图的关键等等;但这些方面是有意留给读者(包括你)去发现的,因为涵盖这些方面会使这个答案太长。

© www.soinside.com 2019 - 2024. All rights reserved.