Developer Sang Guy

OCP (Open Close Principal) 개방 폐쇄 원칙 본문

Java

OCP (Open Close Principal) 개방 폐쇄 원칙

은크 2021. 5. 14. 18:44

OCP - 개방 폐쇄 원칙

소프트웨어 요소는 확장에는 열려 있으나 변경에는 닫혀 있어야 한다

 

말로 설명하기는 어려우니 바로 소스를 보면서 얘기해보자

 

아래 소스는 OCP를 지키지 못한 상황이다.

 

 

User 객체

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import java.util.Map;
 
public class User {
    
    private String name;
    private Map<String, Integer> pocket;
    
    public User(String name, Map<String, Integer> pocket) {
        
        this.name = name;
        this.pocket = pocket;
    }
    
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Map<String, Integer> getPocket() {
        return pocket;
    }
    public void setPocket(Map<String, Integer> pocket) {
        this.pocket = pocket;
    }
    
    @Override
    public String toString() {
        
        return "name : " + name + ", pocket : " + pocket.toString();
    }
}
cs

 

거래를 담당 할 Trade 객체

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class Trade {
    
    private BitCoin bitCoin = new BitCoin();
    
    public User buyBitCoin(User user, String coinName, Integer quantity) {
        
        return bitCoin.buy(user, coinName, quantity);
    }
    
    public User sellBitCoin(User user, String coinName, Integer quantity) {
        
        return bitCoin.sell(user, coinName, quantity);
    }
}
cs

 

BitCoin 객체

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import java.util.Map;
 
public class BitCoin {
    
    public User buy(User user, String coinName, Integer quantity) {
        
        Map<String, Integer> pocket = user.getPocket();
        pocket.put(coinName, quantity);
        
        return new User(user.getName(), pocket);
    }
    
    public User sell(User user, String coinName, Integer quantity) {
        
        Map<String, Integer> pocket = user.getPocket();
        pocket.put(coinName, pocket.get(coinName) - quantity);
        
        return new User(user.getName(), pocket);
    }
}
cs

 

위와 같은 상황에서 BitCoin 외 다른 코인을 거래하게 될 경우 아래와 같이 Trade 객체의 수정이 불가피하다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public class Trade {
    
    private BitCoin bitCoin = new BitCoin();
    private dogeCoin dogeCoin = new dogeCoin();
    
    public User buyBitCoin(User user, String coinName, Integer quantity) {
        
        return bitCoin.buy(user, coinName, quantity);
    }
    
    public User sellBitCoin(User user, String coinName, Integer quantity) {
        
        return bitCoin.sell(user, coinName, quantity);
    }
    
    public User buyDogeCoin(User user, String coinName, Integer quantity) {
        
        return dogeCoin.buy(user, coinName, quantity);
    }
    
    public User sellDogeCoin(User user, String coinName, Integer quantity) {
        
        return dogeCoin.sell(user, coinName, quantity);
    }
}
cs

 

DogeCoin이라는 코인을 추가(확장)하였지만 Trade 객체가 수정(변경)되어 위 소스는 OCP를 위반한 케이스다.

 

그러면 어떻게 Trade 객체의 수정없이 새로운 코인을 추가 할 수 있을까?

이 때 새로 추가 될 Coin에 대한 Interface의 등장으로 각 코인 객체들의 기능을 동일화하며 OCP 위반을 해소 할 수 있다.

 

새로 추가 된 Coin Interface

1
2
3
4
5
6
public interface Coin {
    
    User buy(User user, String coinName, Integer quantity);
    
    User sell(User user, String coinName, Integer quantity);
}
cs

 

Coin Interface가 적용 된 BitCoin

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import java.util.Map;
 
public class BitCoin implements Coin {
    
    @Override
    public User buy(User user, String coinName, Integer quantity) {
        
        Map<String, Integer> pocket = user.getPocket();
        pocket.put(coinName, quantity);
        
        return new User(user.getName(), pocket);
    }
    
    @Override
    public User sell(User user, String coinName, Integer quantity) {
        
        Map<String, Integer> pocket = user.getPocket();
        pocket.put(coinName, pocket.get(coinName) - quantity);
        
        return new User(user.getName(), pocket);
    }
}
cs

 

Coin Interface가 적용 된 DogeCoin

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import java.util.Map;
 
public class dogeCoin implements Coin {
    
    @Override
    public User buy(User user, String coinName, Integer quantity) {
        
        Map<String, Integer> pocket = user.getPocket();
        pocket.put(coinName, quantity);
        
        return new User(user.getName(), pocket);
    }
    
    @Override
    public User sell(User user, String coinName, Integer quantity) {
        
        Map<String, Integer> pocket = user.getPocket();
        pocket.put(coinName, pocket.get(coinName) - quantity);
        
        return new User(user.getName(), pocket);
    }
}
cs

 

변경 된 Trade 객체

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class Trade {
    
    private Coin coin;
    
    public Trade(Coin coin) {
        
        this.coin = coin;
    }
 
    public User buyCoin(User user, String coinName, Integer quantity) {
        
        return coin.buy(user, coinName, quantity);
    }
    
    public User sellCoin(User user, String coinName, Integer quantity) {
        
        return coin.sell(user, coinName, quantity);
    }
}
cs

 

위와 같이 변경 된 Trade 객체는 Coin Interface가 적용 된 코인이라면 모두 Buy, Sell 기능을 수행 할 수 있다.

 

Main

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import java.util.HashMap;
 
public class Main {
    
    public static void main(String[] args) {
        
        User user = new User("UserA"new HashMap<String, Integer>());
        
        /* BitCoin 거래 */
        Trade tradeBit = new Trade(new BitCoin());
        
        tradeBit.buyCoin(user, "BitCoin"155);
        System.out.println(user.toString());
        
        tradeBit.sellCoin(user, "BitCoin"20);
        System.out.println(user.toString());
        
        /* DogeCoin 거래 */
        Trade tradeDoge = new Trade(new dogeCoin());
        
        tradeDoge.buyCoin(user, "DogeCoin"547519);
        System.out.println(user.toString());
        
        tradeDoge.sellCoin(user, "DogeCoin"5000);
        System.out.println(user.toString());
    }
}
cs

 

결과 : 

1
2
3
4
name : UserA, pocket : {BitCoin=155}
name : UserA, pocket : {BitCoin=135}
name : UserA, pocket : {BitCoin=135, DogeCoin=547519}
name : UserA, pocket : {BitCoin=135, DogeCoin=542519}
cs

 

'Java' 카테고리의 다른 글

데이터 압축  (0) 2022.05.26
[Java]NonStaticInnerClass vs StaticInnerClass  (0) 2022.05.18
Java Graphql Client 구현  (0) 2022.03.30
Java Http Rest 통신 소스  (0) 2022.01.05
Java Singleton 객체 구현 및 주의 사항  (0) 2021.05.16
Comments