CS/Design Pattern

Facade Pattern

dawonny 2022. 3. 31. 21:21
728x90
반응형
Facade Pattern

프로그램이라는 것은 점점 커지는 경향이 있음

많은 클래스가 만들어져 서로 관계를 맺으면서 복잡하게 됨

상호 관련된 많은 클래스를 적절하게 제어해야 함

그 처리를 실행하기 위한 창구 역할을 하는 별도의 인터페이스를 두는 것

 


Facade 는 건물의 앞면을 의미한다

-> Facade Pattern 이란 건물의 앞면처럼 그 뒤쪽의 복잡함은 내부에 숨기고 간단한 인터페이스만 제공


Client는 여러 라이브러리와 클래스를 필요로 하는 상태

이런 경우 여러 클래스나 라이브러리를 조합해서 더 간단한 인터페이스를 제공해주는 클래스를 생각해볼 수 있음.

->

Client는 복잡한 클래스와 라이브러리 상대할 필요없이 간단한 인터페이스만 제공하는 Facade Pattern 사용해서 더 쉽게 개발


우주로켓을 만들기 위해 stage1 stage2 capsule이 있음

우주선 목적지까지 보낼 때 복잡한 과정 필요

stage1 : 점화, 이륙, 분리

stage2 : 점화, 분리

capsule : 점화, 착률의 과정 필요

->

이러한 과정 매번 Client가 다루기 번거롭기 때문에 하나로 묶은 Facade Pattern 만들면 개발하기 쉬움.




 

Facade Pattern for Deep Learning Framework

딥러닝에 적용시켜본 Facade Pattern을 알아보자.

데이터셋의 이름 : Fashion MNIST

- 70000개의 28x28픽셀의 이미지들과 10개의 클래스 정답으로 구성된 데이터 셋

- 훈련데이터 60000개, 테스트데이터 10000개

이미지를 input으로 하면 딥러닝을 거쳐 

ouput으로 라벨(정답)이 나올것이다. 실행화면은 다음과 같다.


Facade Pattern in Application : 절차지향적 코드
# #========================절차지향적 프로그램

import tensorflow as tf
import matplotlib.pyplot as plt

fashion_mnist = tf.keras.datasets.fashion_mnist
(train_X, train_Y), (test_X, test_Y) = fashion_mnist.load_data()

print(len(train_X), len(test_X))


plt.imshow(train_X[0], cmap='gray')
plt.colorbar()
plt.show()

print(train_Y[0])

train_X = train_X / 255.0
test_X = test_X /255.0

train_X = train_X.reshape(-1, 28, 28, 1)
test_X = test_X.reshape(-1, 28, 28, 1)


print(train_X.shape, test_X.shape)

model = tf.keras.Sequential([
      tf.keras.layers.Conv2D(input_shape=(28,28,1), kernel_size=(3, 3), filters = 16),
      tf.keras.layers.Conv2D(kernel_size=(3, 3), filters=32),
      tf.keras.layers.Conv2D(kernel_size=(3, 3), filters=64),                               
      tf.keras.layers.Flatten(),
      tf.keras.layers.Dense(units=128, activation='relu'),
      tf.keras.layers.Dense(units=10, activation='softmax')                        
])

model.compile(optimizer=tf.keras.optimizers.Adam(),
              loss='sparse_categorical_crossentropy',
              metrics=['accuracy']
              )

model.summary()

history = model.fit(train_X, train_Y, epochs=25, validation_split=0.25)

Facade Pattern in  Application : 객체지향적 코드
#========================객체지향적 Facade 응용


import tensorflow as tf
import matplotlib.pyplot as plt
import numpy as np

class DataProcess:

  def __init__(self):
    self.train_X = 0
    self.train_Y = 0
    self.test_X = 0
    self.test_Y = 0

    self.N = 0
    self.dimX = 0
    self.dimY = 0

  def setImageDim(self):
    self.N = len(self.train_X)

    imageCase = self.train_X[0]
    self.dimY = imageCase.shape[0]
    self.dimX = imageCase.shape[1]

  def readDataset(self):
    fashion_mnist = tf.keras.datasets.fashion_mnist
    (self.train_X, self.train_Y), (self.test_X, self.test_Y) = fashion_mnist.load_data()
    self.setImageDim()

  def normalize(self):
    # 0~1 normalize
    self.train_X = self.train_X / 255.0
    self.test_X = self.test_X /255.0

  def trainReady(self):
    #reshape the image dimension to (#, 28, 28, 1)
    self.train_X = self.train_X.reshape(-1, self.dimY, self.dimX, 1)
    self.test_X = self.test_X.reshape(-1, self.dimY, self.dimX, 1)

  def showStatus(self):
    print("DP: 총", self.N, "장의 이미지가 로드되었습니다.")
    print("DP: 각 이미지 크기는 ", self.dimY, "X", self.dimX, "입니다.")
    

  
class DeepLearning:
  
  def __init__(self):
    self.model = tf.keras.Sequential()
    self.optimizer = tf.keras.optimizers.Adam()
    self.data_X = 0
    self.data_Y = 0

    self.epoch = 0
    self.validation_split = 0
    
  def setEpoch(self, epoch):
    self.epoch = epoch
    return self
  
  def setValidSplitRatio(self, split_ratio):
    self.validation_split = split_ratio
    return self

  def setInputData(self, X, Y):
    self.data_X = X
    self.data_Y = Y
    return self

  def setLayers(self):
    self.model.add(tf.keras.layers.Conv2D(input_shape=(28,28,1), kernel_size=(3, 3), filters = 16))
    self.model.add(tf.keras.layers.Conv2D(kernel_size=(3, 3), filters=32))
    self.model.add(tf.keras.layers.Conv2D(kernel_size=(3, 3), filters=64))
    self.model.add(tf.keras.layers.Flatten())
    self.model.add(tf.keras.layers.Dense(units=128, activation='relu'))
    self.model.add(tf.keras.layers.Dense(units=10, activation='softmax'))

  def compileDL(self):
    self.model.compile(optimizer=self.optimizer,
              loss='sparse_categorical_crossentropy',
              metrics=['accuracy']
              )
    
  def showModelSummary(self):
    self.model.summary()

  def goTrain(self):
    print("DL: 학습을 시작합니다.")
    history = self.model.fit(self.data_X, self.data_Y, epochs=self.epoch, validation_split=self.validation_split)


class Visualize:
  def __init__(self):
    pass

  def showImage(self, image):
    print("VS: 이미지를 출력합니다.")
    plt.imshow(image, cmap='gray')
    plt.colorbar()
    plt.show()


#FACADE
class Learning:

  def __init__(self):
    self.DP = DataProcess()
    self.VS = Visualize()
    self.DL = DeepLearning()
  
  def learn(self):
    self.DP.readDataset()
    self.VS.showImage(self.DP.train_X[0])
    self.DP.normalize()
    self.DP.trainReady()
    self.DP.showStatus()
    self.DL.setInputData(self.DP.train_X, self.DP.train_Y).setEpoch(25).setValidSplitRatio(0.2)
    self.DL.setLayers()
    self.DL.compileDL()
    self.DL.goTrain()



#======================main
learn = Learning()
learn.learn()

Facade 의 역할은 무엇인가?

Facade는 복잡한 것을 단순하게 보여줌

핵심은 인터페이스를 적게하는 일

- 클래스나 메소드가 많이 보이면, 프로그래머는 무엇을 사용하면 좋을지 망설이게 되고, 호출하는 순서에도 주의 해야만 한다. -> 주의해야한다는 것은 틀리기 쉽다는 것


재귀적 Facade 패턴의 적용

가령 Facade 역할을 하는 클래스의 집합이 여러개가 있다고 가정.

이때 클래스의 집합을 정리해서 새로운 Facade 역할을 도입할 수 있다.

즉, Facade 패턴을 재귀적으로 적용하는 것이다

상당히 큰 시스템이 다수의 클래스, 다수의 패키지를 포함하고 있을 때. 요소들에 Facade 패턴을 적용하면 시스템은 보다 편리하게 된다.

728x90
반응형