[オブジェクト向けプログラミング入門]抽象例
32986 ワード
例
開発
非抽象実装
public enum CloudId {
DROPBOX,
BOX,
}
public class FileInfo {
private CloudId cloudId;
private String fileId;
private String name;
private long length;
}
// 추상화하지 않은 구현
public class CloudFileManager {
// 파일 목록 조회
public List<FileInfo> getFileInfos(CloudId cloudId){
if(cloudId == CloudId.DROPBOX){
DropboxClient db = //...;
List<DbFile> dbFiles = db.getFiles();
List<FileInfo> result = new ArrayList<>();
for(DbFile dbFile : dbFiles){
FileInfo fi = new FileInfo();
fi.setCloudId(CloudId.DROPBOX);
fi.setFileId(fi.getFileId());
result.add(fi);
}
return result;
} else if (cloudId == CloudId.BOX){
BoxClient bc = //...;
}
}
// 다운로드
public void download(FileInfo file, File localTarget){
if(cloudId == CloudId.DROPBOX){
DropboxClient db = //...;
FileOutputStream out = new FileOutputStream(localTarget);
db.copy(file.getCloudId(), out);
out.close();
} else if (cloudId == CloudId.BOX){
BoxClient bc = //...;
InputStream is = bc.getInputStream(file.getId());
FileOutputStream out = new FileOutputStream(localTarget);
CopyUtil.copy(is, out);
}
}
}
ここでは、複数の異なるクラウドをサポートし、クラウド間でコピーする機能を追加できます.// 추상화하지 않은 구현 : 새로운 클라우드를 지원
public List<FileInfo> getFileInfos(CloudId cloudId){
if(cloudId == CloudId.DROPBOX){
DropboxClient db = //...;
List<DbFile> dbFiles = db.getFiles();
List<FileInfo> result = new ArrayList<>();
for(DbFile dbFile : dbFiles){
FileInfo fi = new FileInfo();
fi.setCloudId(CloudId.DROPBOX);
fi.setFileId(fi.getFileId());
result.add(fi);
}
return result;
} else if (cloudId == CloudId.BOX){
BoxClient bc = //...;
} else if (cloudId == CloudId.NCLOUD){
// ...
} else if (cloudId == CloudId.DCLOUD){
// ...
} else if (cloudId == CloudId.SCLOUD){
// ...
}
}
// 추상화하지 않은 구현 : 클라우드간 복사
public FileInfo copy(FileInfo fileInfo, CloudId to){
CloudId from = fileInfo.getCloudId();
if(to == CloudId.DROPBOX){
if (cloudId == CloudId.BOX){
//...;
} else if (cloudId == CloudId.NCLOUD){
// ...
} else if (cloudId == CloudId.DCLOUD){
// ...
} else if (cloudId == CloudId.SCLOUD){
// ...
}
} else if(){
//...
} // ....
}
上記の抽象的でない実装で機能を追加しようとすると、if-elseが非常に混乱していることがわかります.現在は実装を省略しているが,実装すれば上記のコードは非常に複雑になる.
また、そこで新しいクラウドをサポートしている場合は、複数の複雑なコードを変更する必要があるという意外な状況に再び遭遇します.
開発時間がなぜ増加したのか
抽象的な話。
複数のクラウドの共通点は、1クラウドファイルシステム
これを抽象化してください.
抽象的な実装
DROPBOXに対して実施
public class DropBoxFileSystem implements CloudFileSystem {
private DropBoxClient dbClient = new DropBoxClient();
@override
public List<CloudFile> getFiles(){
List<DbFile> dbFiles = dbClient.getFiles();
// DropBoxCloudFile List가 아닌 인터페이스를 사용
List<CloudFile> results = new ArrayList<>();
for(DbFile dbFile : dbFiles){
DropBoxCloudFile cf = new DropBoxCloudFile(dbFile, dbClient);
results.add(cf);
}
return results;
}
}
public class DropBoxCloudFile implements CloudFile {
private DropBoxClient dbClient;
private DbFile dbFile;
public DropBoxCloudFile(DbFile dbFile, DropBoxClient dbClient){
this.dbFile = dbFile;
this.dbClient = dbClient;
}
// getId, getName, getLength....
}
上のコードから、DropBoxFileSystemとDropBoxCloudFileがインタフェースを実現していることがわかります.ファイルリスト、ダウンロード機能の実装
public List<CloudFile> getFileInfos(CloudId cloudId){
CloudFileSystem fileSystem = CloudFileSystemFactory.getFileSystem(cloudId);
return fileSystem.getFiles();
}
public void download(CloudFile file, File localTarget){
file.write(new FileOutputStream(localTarget));
}
これらの機能は、特定のクラスではなくインタフェースを使用することで柔軟性を向上させます.BOXクラウドのサポートを追加
クラウドファイルとクラウドファイルシステムの具体的なクラスを実現すればよい.
その後、CloudFileSystem FactoryでCloudIdに該当するCloudFileSystemを戻せばよい.
BOXクラウドを追加し、ファイルリストとダウンロード機能を表示します.
public List<CloudFile> getFileInfos(CloudId cloudId){
CloudFileSystem fileSystem = CloudFileSystemFactory.getFileSystem(cloudId);
return fileSystem.getFiles();
}
public void download(CloudFile file, File localTarget){
file.write(new FileOutputStream(localTarget));
}
非特定クラスのインタフェースが使用されているため、変更する必要はありません.ファイルコピー機能
public void copy(CloudFile file, CloudId cloudId){
CloudFileSystem fileSystem = CloudFileSystemFactory.getFileSystem(cloudId);
fileSystem.copyFrom(file);
}
各CloudFileSystemクラスの実装が異なっていてもインタフェースのみに依存するため,内部を知らなくても実装できる.抽象結果
public class CloudFileManager {
public List<CloudFile> getFileInfos(CloudId cloudId){
CloudFileSystem fileSystem = CloudFileSystemFactory.getFileSystem(cloudId);
return fileSystem.getFiles();
}
public void download(CloudFile file, File localTarget){
file.write(new FileOutputStream(localTarget));
}
public void copy(CloudFile file, CloudId cloudId){
CloudFileSystem fileSystem = CloudFileSystemFactory.getFileSystem(cloudId);
fileSystem.copyFrom(file);
}
}
コア機能は抽象化されたタイプのみ実現できます.したがって、CloudFileManagerコードを変更することなく、新しいクラウドサポートを追加できます.
これがOCP(Open Closed Principle)です
新しいクラウドをサポートする拡張機能はオープンであり、CloudFileManagerの変更は閉じられています.
Reference
この問題について([オブジェクト向けプログラミング入門]抽象例), 我々は、より多くの情報をここで見つけました https://velog.io/@kshired/객체-지향-프로그래밍-입문-추상화의-예시テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol