반응형

스니펫: 특수한 목적을 위한 코드

디자인: 문제에 대한 해결책

스탠다드: 문제를 해결하는 대표적인 방식 포괄적임

패턴: 유효성이 검증된 효율적이고 확장 가능한 해결책

참가자: 디자인 패턴에서 사용되는 클래스

비기능적 조건: 메모리 최적화와 사용성, 성능등이 여기에 속함. 솔루션 전체에 영향을 미치는 핵심적인 요소

 

생성패턴

- 객체가 생성되는 방식을 중시

- 객체 생성관련 상세 로직을 숨긴다

- 코드는 생성하려는 개체형과 독립적

 

구조 패턴

- 클래스와 객체를 더 큰 결과물로 합칠 수 있는 구조로 설계

- 구조를 간결화하고 클래스와 객체간의 상호관계 파악

- 클래스 상속과 컴포지션을 중시

 

행위패턴

- 객체간의상호작용과 책임을 중시

- 객체는 상호작용하지만 느슨하게 결합돼야한다.

 

- 파이선 디자인 패턴 출처.

반응형
반응형

1. 파이썬 버전은 3.8, 3.9, 3.10 만 지원함

2. tmizeon은 zoneinfo가 default임

3. UniqueConstraint가 생김.

 

흠....그 외에는 아직 장고 초심자여서.. 바뀐것이 어떤의미인지 잘모르겠음.

 

 

 

 

https://www.youtube.com/watch?v=bE23wioMGao 

 

https://docs.djangoproject.com/en/4.0/releases/4.0

반응형
반응형
from collections import deque

n, m = map(int,input().split())
temp = []
for _ in range(n):
    aaa = input()
    aa = []
    for a in aaa:
        aa.append( int(a))

    temp.append(aa)

# print(temp)
dx = [0, 0, -1, 1]
dy = [-1, 1, 0, 0]


visited=[(0,0)]
round = 0
stack = deque ()
stack.append((0,0, 0) )
pointX = 0
pointY = 0
while pointX != n-1 or pointY != m-1:
    pointX, pointY, round =stack.popleft()
    for i in range(4):
        temp_pointX  =pointX+ dx[i]
        if temp_pointX <0 or temp_pointX> n-1:
            continue
        temp_pointY  =pointY+ dy[i]
        if temp_pointY <0 or temp_pointY >m-1:
            continue
        if temp[temp_pointX][temp_pointY] ==0:
            continue
        else:
            temp[temp_pointX][temp_pointY] = 0
            stack.append((temp_pointX, temp_pointY, round+1) )


print(round+1)
반응형
반응형

정의

the factory method pattern is a creational pattern that uses factory methods to deal with the problem of creating objects without having to specify the exact class of the object that will be created. 

-- 영어 위키백과

Factory method는 부모(상위) 클래스에 알려지지 않은 구체 클래스를 생성하는 패턴이며. 자식(하위) 클래스가 어떤 객체를 생성할지를 결정하도록 하는 패턴이기도 하다.

-- 한국어 위키백과

 

이런식으로 정의만 보면 절대 이해가 안간다.

바로 예시로 들어가보자.

 

일단 피자가게 사장님이 되었다고 해보자.

1.햄머슈룸 피자

2. 디럭스피자

3. 해산물 피자를 메뉴로 준비하였다.

 

class HamAndMushroomPizza():
    def __init__(self):
        self.__price = 8.50
        
    def put_toping(self):
    	self.topping = "HAM"

class DeluxePizza():
    def __init__(self):
        self.__price = 10.50
        
    def add_toping(self):
    	self.topping = "meat"

class SeafoodPizza():
    def __init__(self):
        self.__price = 11.50
    
    def add_toping(self):
    	self.topping = "meat"
        
    def add_cheese_crust(self):
    	self.cheese_crust = True

 

만약 이렇게 될시에, 소비자가 주문하려고 할때, 각각의 객체생성 방법에 대해 알고 있어야한다.

ham_mushroom_pizza = HamAndMushroomPizza()
delux_pizza = DeluxePizza()
seafood_pizza = SeafoodPizza()

 

이때, pizzaFactory를 하나 만들어준다면 어떻게 될까?

class PizzaFactory: 
    "The Factory Class"

    @staticmethod
    def create_pizza(pizza_type: str):
        if pizza_type == 'HAM_MUSHROOM_PIZZA_TYPE':
            return HamAndMushroomPizza()
        if pizza_type == 'DELUXE_PIZZA_TYPE':
            return DeluxePizza()
        if pizza_type == 'SEAFOOD_PIZZA_TYPE':
            return SeafoodPizza()
        return None


pizza = PizzaFactory().create_pizza("HAM_MUSHROOM_PIZZA_TYPE")

pizza.put_toping()

소비자는 피자 팩토리만 알면, 복잡한 객체생성방법에 대해 알 필요가 없게된다.

지금 예시는 간단해서 필요성을 못느낄수도 있지만,

각 피자에 따라 직접 토핑을 집어넣어줘야 피자가 생성됐다면?

팩토리라는 클라스의 필요성을 느낄수 있을 것이다.

 

 

이렇게만 바뀌면 객체지향적이라고 할 수 있을까?

SOLID원칙중 open/close원칙에 비추어 확인해보도록 하자.

 

 

class PizzaFactory: 
    "The Factory Class"

    @staticmethod
    def create_pizza(pizza_type: str):
        if pizza_type == 'HAM_MUSHROOM_PIZZA_TYPE':
            return HamAndMushroomPizza()
        if pizza_type == 'DELUXE_PIZZA_TYPE':
            return DeluxePizza()
        if pizza_type == 'SEAFOOD_PIZZA_TYPE':
            return SeafoodPizza()
        return None


pizza = PizzaFactory().create_pizza("SEAFOOD_PIZZA")

pizza.put_toping()

앞선 코드에서 피자종류만, 해산물피자로 바꾸었다.

그런데 에러가 날 것이다.

왜냐하면, SEAFOOD피자에서는 put_toping이 아니라 add_toping이기 때문이다.

 

이는 즉, 만약 HAM_MUSHROOM_PIZZA를 먼저만들고, SEAFOOD 피자로 확장했다고 했을떄,

확장을 했을때 코드를 수정해야한느 일이 발생한 것이다.

즉, 확장에 열려있고, 수정에 닫혀있어야한다는 open/closed principle에 어긋난다.

 

그러면 어떻게 해줘야할까?

class Pizza(ABCMeta):
    def __init__(self):
        self.__price = None
	
    @abstractmethod
    def add_toping(self):
    	pass


class HamAndMushroomPizza(Pizza):
    def __init__(self):
        self.__price = 8.50

    def add_toping(self):
	self.topping = "HAM"


class DeluxePizza(Pizza):
    def __init__(self):
        self.__price = 10.50

    def add_toping(self):
	self.topping = "MEAT"
        
        
class SeafoodPizza(Pizza):
    def __init__(self):
        self.__price = 11.50
        
       
    def add_toping(self):
	self.topping = "SEAFOOD"        
        
        
    def add_cheese_crust(self):
    	self.cheese_crust = True

 이런식으로 추상화된 클라스를 만들어줘서 통일감있게 강제해줘야한다.

이렇게 추상화된 클라스를 상속받기만 하면, 기존코드 수정 없이, 새로운 피자를 만들어낼 수 있다.(확장)

 

이는 또한 생성이라는 역할을 factory가 다 맡고 있다는 점에서 단일책임 원칙을 지키고 있다고 볼 수 있다.

반응형
반응형

1. 발단

어떻게 하면 객체지향 프로그래밍 지식을 한 시간안에 잘 전달할 수 있을까? 이러한 고민에서 이 시리즈가 시작되었다.

필자는 매주 일요일 cs지식공유스터디를 하는데, 각자 공부한 것을 30~1시간정도 나누는 시간이다.

그래서 필자가 최근 열심히 공부한 객체지향을 나누고 싶은데, 이게 객체지향 특성상 말로 떠든다고 절대 와닿지 않는다.

특히 solid원칙은 직접해보고 생각해보고, 리팩토링을 해봐야 느낄수 있는 영역이라고 생각된다.

 

2. 전개

그러던중 필자는 디자인패턴을 공부하고 있었는데 너무 노잼이었다. 이 역시 객체지향을 처음 공부할떄랑 비슷한 느낌이 드는건데, 그거 좋은거 알겠는데, 머 어쩌라고? 이런느낌이 드는건 어쩔 수 없다.

이때 머릿속을 스쳐지나간 생각이 아. 디자인패턴을 역으로 solid 원칙 및  4기둥에 비추어 분석하고, 이를 같이 나눠보면 나도 공부되고 스터디원도 공부되지 않을까? 생각이 들었다.

 

 

반응형

'computer 지식 > 디자인패턴으로 알아보는 객체지향' 카테고리의 다른 글

디자인 패턴 용어들  (0) 2022.01.08
#1 팩토리패턴  (0) 2021.11.28
반응형

 비전공자로서 자료구조를 공부하다가 궁금했던 것이 있다. 내가 파이썬부터 배우기 시작해서 그런지는 몰라도.

스택/큐 다되는 deque가 있는데, 왜 굳이 스택/큐를 나누어서 쓰는 것일까? 그냥 그 모든 기능을 다 되게하면 안되는 걸까?

 

이 질문에 대한 답을 오늘 드디어 깨달아서, 이렇게 글을 쓴다.

 

일단 자료구조의 정의부터 알아보자.

In computer science, a data structure is a particular way of storing and organizing data in a computer so that it can be used efficiently

즉, 효율적으로 사용되기 위해, 데이터를 저장하고 표현하기 위한 특정한 방식이 자료구조라고 할 수 있다.

그러니까 스택이나 큐가 먼저 있었고, 그에 따른 기능들이 나온 것이 아니라.

FIFO, LIFO등의 데이터를 저장하고 표현하기  위한 방식이 있었고, 이에 대한 이름을 스택, 큐라고 붙인 것이다.

 

 

여기서부터는 내 상상이자, 뇌피셜이 살짝 섞여있다. (실제로는 아닐 수 있음 주의)

 

컴퓨터과학자들이 먼저 자료구조를 만들고, 프로그래머들이 이를 사용했을까?

아니면 프로그래머가 먼저 코드를 짜다보니 특정한 데이터의 저장/표현방식이 반복되었고, 이를 컴퓨터과학자들이 스택/큐라고 이름을 붙였을까?

 

나는 후자라고 생각한다. 사실 프로그래밍 세계의 발전이 그러한 것 같다. 계속 해결해야한느 문제점들이 발생하고, 이를 해결하려고 노력하고, 그 해결점들이 컴퓨터과학으로 학문화되는 것 같다. (그래서 나는 운영체제 과목을 물리적 한계에서 최적화된 컴퓨터를 개발하기 위한 컴퓨터과학자들의 분투들이 담겨있다고 느꼈다.)

 

 

그리고 C언어로 된 책을 보면 ADT를 설정하고 이를 자료구조로 구현한다.

이는 ADT는 설계도 같은 것으로, FIFO를 구현하는데 LIFO까지 가능하게 하면 이는 사족이 달려있는 것과 같다.

또한 다른 프로그래머들이 어떠한 맥락을 파악하는데 어려움을 겪을 것이다.

예를 들어, a라는 프로그래머가 FIFO기능이 필요한데 그냥 deque로 짜놓았다면, b란느 프로그래머는 deque가 fifo기능을 위해 들어갔다는 사실을 전후 코드를 살펴야하는 노력이 필요하다. 이러한 비효율을 줄이기 위해서라도, queue/ stack은 나누어서 쓰여져야 한다.

 

여튼 내가 가졌던 의문은 전제가 잘못되었다.

일단 나누어서 개발한게 아니라, 개발된것에 이름을 붙인것 뿐이다.

그리고 나뉘어져있어야 타 개발자와의 협업, 소통 등에서 유리하다.

 

반응형
반응형
n= int(input())

for i in range(n): 
    a = int(input())
    aa = list(map(int,input().split()))
    print(min(aa),max(aa))
반응형
반응형
aa = []
for i in range(28):
    aa.append(int(input()))
    
dd = list(set([j for j in range(1,31)]) -set(aa))

print(min(dd))
print(max(dd))
반응형

+ Recent posts