복합 디자인 패턴

Feb 04 2023
얘들 아 !!!!!! 오늘날 코드베이스에는 수많은 디자인 패턴이 사용되기 때문에 우리는 그 중 “Composite”라는 하나의 패턴을 파악하려고 노력했습니다. 소개 잘 알려진 구조 설계 패턴 중 하나는 합성물입니다.

얘들 아 !!!!!!

오늘날 코드베이스에는 수많은 디자인 패턴이 사용되기 때문에 우리는 그 중 “Composite”라는 하나의 패턴을 파악하려고 노력했습니다.

소개

잘 알려진 구조 디자인 패턴 중 하나는 합성물입니다. 단일 인터페이스를 사용하여 개체를 만듭니다. 공통 인터페이스를 가진 개별 노드 또는 작은 구성 요소로 구성된 트리 구조와 다형성을 광범위하게 사용합니다. 작은 구성 요소로 더 정교한 구조를 간단하게 구성할 수 있습니다.

플러그 가능한 디자인 패턴에는 복합 패턴도 포함됩니다.

다이어그램 — 구조

코드 조각

핵심 요소

구성 요소: 트리의 각 노드가 채택한 표준 인터페이스입니다.

Primitive(Leaf): 자율적인 개체이며 자손이 없습니다.

복합: 여러 리프 구성 요소의 컨테이너입니다.

사례 연구에서 상황을 빠르게 검토해 보겠습니다.

프로젝트 첫 날: Google 드라이브에 파일을 업로드하는 기능과 같은 간단한 기능이나 모듈이 있는 프로젝트에서 작업 중이라고 가정해 보겠습니다.

매우 간단한 시나리오이므로 아래 코드를 검토하십시오.

struct File {
    var name: String
    var data: Data
}

class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        
        /// Problem On Day 1
        func finishedCreateFileProcess(file: File) {
            uploadToGoogleDrive(file: File(name: "test", data: Data()))
        }
        
        func uploadToGoogleDrive(file: File) {
            // Code to upload to Google Drive.
        }
    }
}

안녕하세요 Devs 클라이언트의 수많은 클라이언트가 파일 업로드 절차를 수정하기를 원합니다. Google 드라이브 및 Amazon S3 옵션에는 업로드 프로세스가 필요합니다.

개발자는 고객에게 문제가 없다고 확신했습니다. 그렇게 하고 가능한 한 빨리 알려드리겠습니다.

Xcode에서 몇 줄의 코드를 변경하면 Presto! 원활하게 실행됩니다.

struct File {
    var name: String
    var data: Data
}

class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        /// Two Weeks Later
        func finishedCreateFileProcess(file: File, shouldUploadToGD: Bool) {
            if shouldUploadToGD {
                uploadToGoogleDrive(file: File(name: "test", data: Data()))
            } else {
                uploadToAmazons3(file: File(name: "test", data: Data()))
            }
        }
        
        func uploadToGoogleDrive(file: File) {
            // Code to upload to Google Drive.
        }
        
        func uploadToAmazons3(file: File) {
            // Code to upload to Amazon S3
        }
    }
}

그러나 이야기는 여기서 끝나지 않습니다. 2주가 지난 후 클라이언트가 돌아와서 Dropbox와 같은 추가 스토리지 대안이 포함되도록 요청했습니다.

그리고 이번에는 개발자가 어떻게 대응할지 모두가 잘 알고 있습니다. 개발자들은 여전히 ​​작업을 시작하기 전에 최종 변경이 될 것이라고 생각합니다.

Xcode에서 코드를 작성한 다음 테스트합니다.

struct File {
    var name: String
    var data: Data
}

class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        /// Four Weeks Later
        enum StorageService: Int {
            case googleDrive = 0
            case amazonS3
            case dropbox
        }
        
        func finishedCreateFileProcess(file: File, uploadTo service: StorageService) {
            switch service {
            case .googleDrive:
                uploadToGoogleDrive(file: File(name: "test", data: Data()))
            case .amazonS3:
                uploadToAmazons3(file: File(name: "test", data: Data()))
            case .dropbox:
                uploadToDropBox(file: File(name: "test", data: Data()))
            }
        }
        
        func uploadToGoogleDrive(file: File) {
            // Code to upload to Google Drive.
        }
        
        func uploadToAmazons3(file: File) {
            // Code to upload to Amazon S3
        }
        
        func uploadToDropBox(file: File) {
            // Code to upload to DropBox
        }
    }
}

매번 개발자가 개발 프로세스에 좋지 않은 개폐 원칙을 위반했다는 점에 유의하십시오.

그리고 이번에도 클라이언트는 새로운 요구 사항을 가지고 있으며 이번에는 개발자가 복합 으로 시작하기 전에 올바른 패턴을 사용하여 완전히 리모델링하기로 결정했습니다 .

//
//  UseCase1.swift
//  CompositeDesignPattern
//
//  Created by Nikunj Modi on 30/01/23.
//

import Foundation

protocol StorageService {
    func upload()
}

class GoogleDriveStorage: StorageService {
    func upload() {
        // Here is the need to implement business logic.
        print("GoogleDriveStorage")
    }
}

class DropBoxStorage: StorageService {
    func upload() {
        // Here is the need to implement business logic.
        print("DropBoxStorage")
    }
}

class AmazonS3Storage: StorageService {
    func upload() {
        // Here is the need to implement business logic.
        print("AmazonS3Storage")
    }
}

class StorageComposite: StorageService {
    let service: [StorageService]
    
    init(services: [StorageService]) {
        self.service = services
    }
    
    func upload() {
        print("StorageComposite")
        for service in service {
            service.upload()
        }
    }
}

class ExampleViewModel {
    let service: StorageService
    
    init(service: StorageService) {
        self.service = service
    }
    
    func finishedCreatingFile(file: File) {
        self.service.upload()
    }
}
struct File {
    var name: String
    var data: Data
}

class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        let vm = ExampleViewModel(service: StorageComposite(services: [
            GoogleDriveStorage(),
            AmazonS3Storage(),
            DropBoxStorage()
        ]))
        vm.finishedCreatingFile(file: File(name: "test", data: Data()))
    }
}

https://theniks.github.io/Portfolio/

질문이나 의견이 있으시면 아래에 게시해 주십시오. 당신의 의견을 듣고 싶습니다.