3

I have a service that uses repositories from multiple Git version control platforms as Gitlab, GitHub.. etc

I am using Jgit library in Java so I created a GitService which have the basic git commands

public class GITService {

  public void cloneRepo(){}

  public void push(){}
}

All platforms used this class, all worked good until pull request feature is added to my Github requests.

So I created a class to each platform, they all extend the GitService class

public class GitHubService extends GITService {
   
  public void createPullRequest()
}

public class GitLabService extends GITService {

}

And I created a Factory to choose which class to be used based on the requests coming.

public class GitServiceFactory(){
    public GitService getService(){}
}

There are two problems here in this design:

  1. I have a child which is Gitlab that doesn't have the feature of pullRequest. So I cannot put this method in the parent class because it could be uncommon for other platforms to have pull requests.
  2. My Factory returns GitService object, and thus I cannot use the method in child class. I saw that downcasting the object is a sign of bad design.

Any help would be appreciated to solve this. thanks.

eftshift0
  • 26,375
  • 3
  • 36
  • 60
Makook
  • 41
  • 5

1 Answers1

0

If we will stick with principle program to interfaces, not implementations, then there will be no reason to return object type.

I am sorry, I am not Java guy, but I've provided comments how C# code can be converted to Java.

So let's dive in code. At first, we need an abstraction of GitService:

public abstract class GitServiceBase
{
    public void CloneRepo() 
    { }

    public void Push()
    { }
}

and abstraction of IGitHubRequest:

public interface IGitHubRequest
{
    void CreatePullRequest();
}

and its concrete implementations:

public class GitHubService : GitServiceBase, IGitHubRequest  
                            // extends GITService in Java
{
    public void CreatePullRequest()
    {
        throw new NotImplementedException();
    }
}

public class GitLabService : GitServiceBase
{

}

And factory would look like this:

public enum GitServiceType 
{
    GitHub, GitLab
}

public class GitServiceFactory
{
    private Dictionary<GitServiceType, GitServiceBase> _gitServiceByType = new()
    {
        { GitServiceType.GitHub, new GitHubService() },
        { GitServiceType.GitLab, new GitLabService() }
    };

    public GitServiceBase GetInstanceByType(GitServiceType gitServiceType) =>
        _gitServiceByType[gitServiceType];
}

And then you can call you IGitHubRequest like this:

GitServiceBase gitHubService = new GitServiceFactory()
    .GetInstanceByType(GitServiceType.GitHub);
IGitHubRequest gitHubRequest = (GitHubService)gitHubService;
StepUp
  • 36,391
  • 15
  • 88
  • 148