prefer 組合 to 繼承

做时间的好朋友發表於2024-03-23

核心不要多繼承,要透過組合的模式進行組合,解耦, 非強繫結

需求

我已有一個CodingService的介面,同時有一個CodingServiceImpl的實現類,介面中定義了createReository,pullCode,pushCode三個方法,CodingServiceImpl 實現類裡面進行了實現,現在想透過prefer 組合 to 繼承的思想,將介面中的3個方法抽取出來變成單獨的功能模組,方法依賴的引數變成獨立功能模組裡的屬性,然後透過Builder構造者模式把方法引數傳遞進功能模組的屬性裡。功能模組執行沒有任何引數的do方法。請幫我設計一下,並給出實踐案例

實際程式碼

為了遵循組合優於繼承的原則,並且利用構建者模式來構造物件,我們可以將CodingService介面中的方法createRepository, pullCode, pushCode分別抽象成三個獨立的功能模組。每個功能模組都會有一個內部的Builder類用於構建該模組的例項,這些模組將會有一個無參的do方法來執行相應的操作。

以下是根據上述描述設計的程式碼實現:

首先定義一個基礎的介面CodingOperation,所有的操作類都要實現這個介面:

public interface CodingOperation {
    void doOperation();
}

然後為每個操作定義一個模組,每個模組都包含一個Builder類:
建立Repository模組

public class RepositoryCreationModule implements CodingOperation {
    private String repositoryName;
    private String owner;

    private RepositoryCreationModule(Builder builder) {
        this.repositoryName = builder.repositoryName;
        this.owner = builder.owner;
    }

    @Override
    public void doOperation() {
        // 實現建立倉庫的邏輯
        System.out.println("Creating repository " + repositoryName + " for owner " + owner);
    }

    public static class Builder {
        private String repositoryName;
        private String owner;

        public Builder repositoryName(String repositoryName) {
            this.repositoryName = repositoryName;
            return this;
        }

        public Builder owner(String owner) {
            this.owner = owner;
            return this;
        }

        public RepositoryCreationModule build() {
            return new RepositoryCreationModule(this);
        }
    }
}

建立程式碼模組

public class CodePullModule implements CodingOperation {
    private String sourceBranch;
    private String destinationBranch;

    private CodePullModule(Builder builder) {
        this.sourceBranch = builder.sourceBranch;
        this.destinationBranch = builder.destinationBranch;
    }

    @Override
    public void doOperation() {
        // 實現拉取程式碼的邏輯
        System.out.println("Pulling code from " + sourceBranch + " to " + destinationBranch);
    }

    public static class Builder {
        private String sourceBranch;
        private String destinationBranch;

        public Builder sourceBranch(String sourceBranch) {
            this.sourceBranch = sourceBranch;
            return this;
        }

        public Builder destinationBranch(String destinationBranch) {
            this.destinationBranch = destinationBranch;
            return this;
        }

        public CodePullModule build() {
            return new CodePullModule(this);
        }
    }
}

推送程式碼模組

public class CodePushModule implements CodingOperation {
    private String branchName;
    private String commitMessage;

    private CodePushModule(Builder builder) {
        this.branchName = builder.branchName;
        this.commitMessage = builder.commitMessage;
    }

    @Override
    public void doOperation() {
        // 實現推送程式碼的邏輯
        System.out.println("Pushing code to branch " + branchName + " with message '" + commitMessage + "'");
    }

    public static class Builder {
        private String branchName;
        private String commitMessage;

        public Builder branchName(String branchName) {
            this.branchName = branchName;
            return this;
        }

        public Builder commitMessage(String commitMessage) {
            this.commitMessage = commitMessage;
            return this;
        }

        public CodePushModule build() {
            return new CodePushModule(this);
        }
    }
}

現在進行測試

public class CodingServiceClient {
    public static void main(String[] args) {
        RepositoryCreationModule repositoryCreation = new RepositoryCreationModule.Builder()
                .repositoryName("MyRepo")
                .owner("Myself")
                .build();
        repositoryCreation.doOperation();

        CodePullModule codePull = new CodePullModule.Builder()
                .sourceBranch("develop")
                .destinationBranch("feature")
                .build();
        codePull.doOperation();

        CodePushModule codePush = new CodePushModule.Builder()
                .branchName("feature")
                .commitMessage("Added new feature")
                .build();
        codePush.doOperation();
    }
}

好處:
這樣的設計允許我們將每個操作封裝在自己的模組中,同時透過構建者模式提供了一種清晰的方式來構造這些模組。每個模組都是獨立的,它們可以被獨立地建立和複用,也便於單獨測試和維護

相關文章