๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ

๐Ÿ”ญComputer Science๐Ÿ”ญ/JAVA

์ผ๊ธ‰ ์ปฌ๋ ‰์…˜(First Class Collection)์— ๋Œ€ํ•ด ์•Œ์•„๋ณด์ž ๐Ÿ’ก

tocoble์„ ๋ณด๋‹ค๊ฐ€ ์ผ๊ธ‰ ์ปฌ๋ ‰์…˜์„ ์•Œ๊ฒŒ ๋˜์—ˆ๊ณ  ์ด์— ๋Œ€ํ•ด ์•Œ๊ฒŒ๋œ ๋‚ด์šฉ์„ ์ •๋ฆฌํ•ด๋‘๋ ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค.

1. ์ผ๊ธ‰ ์ปฌ๋ ‰์…˜ ๊ทœ์น™

๋จผ์ €, ์ผ๊ธ‰ ์ปฌ๋ ‰์…˜์˜ ๊ทœ์น™์— ๋Œ€ํ•ด์„œ ์•Œ์•„๋ด…์‹œ๋‹ค.

  • ํด๋ž˜์Šค๋Š” ์ปฌ๋ ‰์…˜์„ ์ œ์™ธํ•˜๊ณ  ๋‹ค๋ฅธ ์–ด๋–ค ๋ฉค๋ฒ„ ๋ณ€์ˆ˜๊ฐ€ ์—†์–ด์•ผ ํ•จ

์ปฌ๋ ‰์…˜์„ Wrappingํ•˜๋ฉด์„œ Wrappingํ•œ Collection์™ธ ๋‹ค๋ฅธ ๋ฉค๋ฒ„ ๋ณ€์ˆ˜๊ฐ€ ์—†๋Š” ์ƒํƒœ๋ฅผ ๋œปํ•จ

 

2.  ์˜ˆ์‹œ

SafariService

์‚ฌํŒŒ๋ฆฌ์„œ๋น„์Šค๊ฐ€ ๋™๋ฌผ๋“ค์„ List ์ž๋ฃŒ๊ตฌ์กฐ๋กœ ์ง์ ‘ ๊ด€๋ฆฌํ•œ๋‹ค๊ณ  ๊ฐ€์ •ํ•ด๋ด…์‹œ๋‹ค.

 

๋งŒ์•ฝ ์šฐ๋ฆฌ๊ฐ€ ์—๋ฒ„๋žœ๋“œ์˜ ์‚ฌํŒŒ๋ฆฌ ์„œ๋น„์Šค๋ฅผ ์šด์˜ํ•œ๋‹ค๋ฉด ์—ฌ๋Ÿฌ ๋™๋ฌผ๋“ค์„ ๊ด€๋ฆฌํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์‚ฌํŒŒ๋ฆฌ์— ์žˆ๋Š” ๋™๋ฌผ๋“ค์€ ์ •ํ•ด์ง„ ์ตœ์†Œ ์—๋„ˆ์ง€๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์–ด์•ผํ•ฉ๋‹ˆ๋‹ค.

 

์ด๋ฅผ ์œ„ํ•ด์„œ SafariService๋Š” ๊ด€๋ฆฌํ•˜๋Š” ๋™๋ฌผ๋“ค์ด ์กฐ๊ฑด์— ๋ถ€ํ•ฉํ•˜๋Š”์ง€ ํ™•์ธํ•˜๋Š” ๋กœ์ง์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

class SafariService {
    private static final int MINIMUM_ENERGY = 25;

    public void openSafari() {
        List<Animal> animals = createAnimals();
        validateLowEnergy(animals, MINIMUM_ENERGY);
        validateSize(animals);
    }

    public List<Animal> createAnimals() {
        Animal tiger = new Animal("ํ˜ธ๋ž‘์ด", 30);
        Animal cat = new Animal("๊ณ ์–‘์ด", 20);
        Animal dog = new Animal("๊ฐœ", 10);
        return List.of(tiger, cat, dog);
    }

    private void validateSize(List<Animal> animals) {
        if (animals.size() >= 100) {
            throw new IllegalArgumentException("100๋งˆ๋ฆฌ ์ด์ƒ์˜ ๋™๋ฌผ์ด ์žˆ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.");
        }
    }

    private void validateLowEnergy(List<Animal> animals, int minimumEnergy) {
        for (Animal animal : animals) {
            if (animal.getEnergy() < minimumEnergy)
                throw new IllegalArgumentException("์ตœ์†Œ ์—๋„ˆ์ง€๊ฐ€ ๋ถ€์กฑํ•ฉ๋‹ˆ๋‹ค.");
        }
    }
}

public class Animal {
    private String name;
    private int energy;

    public Animal(String name, int energy) {
        this.name = name;
        this.energy = energy;
    }

    public String getName() {
        return name;
    }

    public int getEnergy() {
        return energy;
    }
}

์œ„ ์ฝ”๋“œ์—์„œ ์‚ฌํŒŒ๋ฆฌ๋Š” ์˜คํ”ˆ ์‹œ ๋™๋ฌผ๋“ค์˜ ์ตœ์†Œ ์—๋„ˆ์ง€ ์กฐ๊ฑด๊ณผ ์ตœ๋Œ€ ๋™๋ฌผ ์ˆ˜ ์กฐ๊ฑด์— ๋ถ€ํ•ฉํ•˜๋Š”์ง€ ์ฒดํฌํ•ฉ๋‹ˆ๋‹ค.

-> ์„œ๋น„์Šค ๋ฉ”์„œ๋“œ์—์„œ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์ด ์ฒ˜๋ฆฌ๋จ

 

์šฐ๋ฆฌ๋Š” ๋™๋ฌผ ์ƒ์„ฑ์„ ์œ„ํ•ด์„  [์ตœ์†Œ ์—๋„ˆ์ง€, ์ตœ๋Œ€ ๋™๋ฌผ ์ˆ˜] ์กฐ๊ฑด์„ ๋งŒ์กฑํ•ด์•ผํ•œ๋‹ค๋Š” ์‚ฌ์‹ค์„ ์•Œ๊ณ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ๋ฌธ์ œ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.

ํ•˜์ง€๋งŒ, ๋‹ค๋ฅธ ๊ณณ์—์„œ Animal์„ ์ƒ์„ฑํ•˜๋Š” ์‚ฌ๋žŒ์€ ์ด๋ฅผ ๋ชจ๋ฅผ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

 

์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ๊ฐ์ฒด ์ƒ์„ฑ ์‹œ ์›ํ•˜๋Š” ์กฐ๊ฑด์„ ์ฒดํฌํ•˜๋Š” ์ž๋ฃŒ๊ตฌ์กฐ๋ฅผ ์ง์ ‘ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. (์ผ๊ธ‰ ์ปฌ๋ ‰์…˜)

class AnimalsManager {
    private static final int MINIMUM_ENERGY = 25;
    
    private final List<Animal> animals;

    public AnimalsManager(List<Animal> animals) {
        validateLowEnergy(animals, MINIMUM_ENERGY);
        validateSize(animals);
        this.animals = animals;
    }

    private void validateSize(List<Animal> animals) {
        if (animals.size() >= 100) {
            throw new IllegalArgumentException("100๋งˆ๋ฆฌ ์ด์ƒ์˜ ๋™๋ฌผ์ด ์žˆ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.");
        }
    }

    private void validateLowEnergy(List<Animal> animals, int minimumEnergy) {
        for (Animal animal : animals) {
            if (animal.getEnergy() < minimumEnergy)
                throw new IllegalArgumentException("์ตœ์†Œ ์—๋„ˆ์ง€๊ฐ€ ๋ถ€์กฑํ•ฉ๋‹ˆ๋‹ค.");
        }
    }
}

์œ„ ์ฝ”๋“œ๋Š” ์ปฌ๋ ‰์…˜์„ Wrappingํ•˜๊ณ  ์žˆ๊ณ  ์ƒ์„ฑ ์‹œ ํ•„์š”ํ•œ ๊ฒ€์ฆ ๋กœ์ง๋„ ์ˆ˜ํ–‰ํ•ด์ค๋‹ˆ๋‹ค.

Animal๊ณผ ๊ด€๋ จ๋œ ๋น„์ฆˆ๋‹ˆ์Šค๋กœ์ง์„ ํฌํ•จํ•œ ์ž๋ฃŒ๊ตฌ์กฐ๊ฐ€ ์ผ๊ธ‰ ์ปฌ๋ ‰์…˜์œผ๋กœ ๋งŒ๋“ค์–ด์กŒ๋‹ค๊ณ  ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

์ด์ œ SafariService ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ๋‹ค๋ฅธ ์„œ๋น„์Šค์—์„œ๋„ ๋™์ผํ•œ ๊ฒ€์ฆ๋กœ์ง๊ณผ ํ•จ๊ป˜ ๋™๋ฌผ์„ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

3. ๋ถˆ๋ณ€

  • ์ผ๊ธ‰ ์ปฌ๋ ‰์…˜์€ ์ปฌ๋ ‰์…˜์˜ ๋ถˆ๋ณ€์„ ๋ณด์žฅ

๋งŒ์•ฝ, Service์— List ํ˜•ํƒœ๋กœ ์ปฌ๋ ‰์…˜์ด ๋ฐ”๋กœ ๋…ธ์ถœ๋œ๋‹ค๋ฉด final๋กœ ์„ ์–ธํ•ด๋„ ์žฌํ• ๋‹น๋งŒ ๋ชปํ•˜๊ฒŒ ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

List์— ์ƒˆ๋กœ ์ถ”๊ฐ€ํ•˜๊ณ  ์‚ญ์ œํ•˜๋Š” ๊ฒƒ์€ final๋งŒ์œผ๋กœ ๋ง‰์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

 

์ด๋Ÿฌํ•œ ๋ฌธ์ œ๋Š” '์ผ๊ธ‰ ์ปฌ๋ ‰์…˜'๊ณผ ๊ฐ™์€ ๋ฐฉ๋ฒ•์œผ๋กœ ํ•ด๊ฒฐํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.

class AnimalsManager {
    private final List<Animal> animals;
    private static final int MINIMUM_ENERGY = 25;

    public AnimalsManager(List<Animal> animals) {
        validateLowEnergy(animals, MINIMUM_ENERGY);
        validateSize(animals);
        this.animals = animals;
    }
    
	...
    
    public long overSpecificEnergySum(int energy) {
        return animals.stream()
                .filter(animal -> animal.getEnergy() >= energy)
                .mapToLong(Animal::getEnergy)
                .sum();
    }
}

AnimalManger๋Š” Animal ๋ฆฌ์ŠคํŠธ์— ๋Œ€ํ•œ ์ •๋ณด๋ฅผ ์™ธ๋ถ€์— ๋…ธ์ถœํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

๋˜ํ•œ, ์ปฌ๋ ‰์…˜์˜ ๊ฐ’์„ ๋ณ€๊ฒฝํ•˜๊ฑฐ๋‚˜ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ๋Š” ๋ฉ”์„œ๋“œ๋ฅผ ์ œ๊ณตํ•˜์ง€ ์•Š์œผ๋ฏ€๋กœ '๋ถˆ๋ณ€ ์ปฌ๋ ‰์…˜'์ด ๋ณด์žฅ๋ฉ๋‹ˆ๋‹ค.

-> '์ผ๊ธ‰ ์ปฌ๋ ‰์…˜'์„ ํ†ตํ•ด '๋ถˆ๋ณ€ ์ปฌ๋ ฅ์…˜' ๋งŒ๋“ค๊ธฐ

 

 

๊ทธ๋Ÿผ ์ด์ œ SafariService์—์„œ Animal ๋ฆฌ์ŠคํŠธ๋ฅผ ๊ทธ๋Œ€๋กœ ๋…ธ์ถœํ•˜๋Š” ์ฝ”๋“œ๋ฅผ ์‚ดํŽด๋ด…์‹œ๋‹ค.

class SafariService {
    private static final int MINIMUM_ENERGY = 25;

    public void openSafari() {
        List<Animal> animals = createAnimals();
        validateLowEnergy(animals, MINIMUM_ENERGY);
        validateSize(animals);

		// animals์— ๋ฐ”๋กœ ์ ‘๊ทผํ•ด์„œ ์ถ”๊ฐ€/์‚ญ์ œ ๋‚ด๋ถ€ ํ•„๋“œ ์ ‘๊ทผ ๊ฐ€๋Šฅ
        animals.add(new Animal("์‚ฌ์ž", 100));
        long sum = animals.stream()
                .filter(animal -> animal.getEnergy() >= 20)
                .mapToLong(Animal::getEnergy)
                .sum();
    }
    
    ...
    
 }

์œ„ ์ฝ”๋“œ์ฒ˜๋Ÿผ SafariService์—์„œ๋Š” animals๊ฐ€ ์ถ”๊ฐ€/์‚ญ์ œ/๋ณ€๊ฒฝ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. (๋ถˆ๋ณ€ ์ปฌ๋ ‰์…˜์ด ์•„๋‹˜)

 

4. ์ƒํƒœ์™€ ํ–‰์œ„๋ฅผ ํ•œ๊ณณ์—์„œ ๊ด€๋ฆฌ

 

๋‹ค์‹œํ•œ๋ฒˆ ์•„๋ž˜์˜ Service ์ฝ”๋“œ๋ฅผ ๋ณด๋ฉด [ํŠน์ •์—๋„ˆ์ง€ ์ด์ƒ ๋™๋ฌผ์˜ ์—๋„ˆ์ง€ ์ดํ•ฉ]์„ ๊ตฌํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

์ด๋ฅผ Service์—์„œ ๊ด€๋ฆฌํ•˜๋ฉด ๋‹ค๋ฅธ ์„œ๋น„์Šค์—์„œ [ํŠน์ •์—๋„ˆ์ง€ ์ด์ƒ ๋™๋ฌผ์˜ ์—๋„ˆ์ง€ ์ดํ•ฉ]์„ ๊ตฌํ•  ๋•Œ 1. ์ค‘๋ณต ๋กœ์ง์ด ์ƒ๊ธฐ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

๋˜ํ•œ, 2. ๊ณ„์‚ฐ๋กœ์ง ๋ณ€๊ฒฝ ์‹œ ๊ด€๋ฆฌํ•ด์•ผํ•  ํฌ์ธํŠธ๊ฐ€ ์ฆ๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.

3. ์„œ๋น„์Šค๋งˆ๋‹ค ๊ณ„์‚ฐ๋กœ์ง์ด ์„œ๋กœ ๋‹ฌ๋ผ์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

class SafariService {
    private static final int MINIMUM_ENERGY = 25;

    public void openSafari() {
        List<Animal> animals = createAnimals();
        validateLowEnergy(animals, MINIMUM_ENERGY);
        validateSize(animals);

		// animals์— ๋ฐ”๋กœ ์ ‘๊ทผํ•ด์„œ ์ถ”๊ฐ€/์‚ญ์ œ ๋‚ด๋ถ€ ํ•„๋“œ ์ ‘๊ทผ ๊ฐ€๋Šฅ
        animals.add(new Animal("์‚ฌ์ž", 100));
        long sum = animals.stream()
                .filter(animal -> animal.getEnergy() >= 20)
                .mapToLong(Animal::getEnergy)
                .sum();
    }
    
    ...
    
 }

๊ทธ๋ ‡๊ธฐ ๋•Œ๋ฌธ์— ์ฝ”๋“œ๋ฅผ '์ผ๊ธ‰ ์ปฌ๋ ‰์…˜'์ฒ˜๋Ÿผ ์ƒํƒœ์™€ ๋กœ์ง์„ ํ•จ๊ป˜ ๋‘๋Š” ํ˜•์‹์œผ๋กœ ๋งŒ๋“ค์–ด์•ผ ๋ณ€๊ฒฝ ๋˜๋Š” ์œ ์ง€๋ณด์ˆ˜ ์‹œ ๊ด€๋ฆฌ ํฌ์ธํŠธ๊ฐ€ ์ค„์–ด๋“ญ๋‹ˆ๋‹ค.

 

์˜ค๋Š˜์€ jojoldu๋‹˜์ด ์ •๋ฆฌํ•ด์ฃผ์‹  ๋ธ”๋กœ๊ทธ๋ฅผ ์ฝ๊ณ  ์–ด๋””์— ์ ์šฉํ•  ์ˆ˜ ์žˆ์„ ์ง€ ์ƒ๊ฐํ•˜๋ฉด์„œ ๊ธ€์„ ์ ์–ด๋ณด์•˜์Šต๋‹ˆ๋‹ค. Enum๊ณผ ์ผ๊ธ‰ ์ปฌ๋ ‰์…˜์€ ๊ฐ์ฒด ์ง€ํ–ฅ ์ฝ”๋“œ๋กœ ๊ฐ€๊ธฐ ์œ„ํ•ด ์ค‘์š”ํ•œ ๋ถ€๋ถ„์ด๋ฏ€๋กœ ๊ผญ ์ตํžˆ๊ณ  ๊ฐ€์•ผํ•  ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.