참고  : https://blog.naver.com/centrople/80119012228

Ant로 빌드하는 과정에서 많은 프로퍼티를 사용하는 경우 별도의 프로퍼티 파일을 작성한 후 file이나 resource 속성을 사용하여 프로퍼티를 초기화하면 편리하다.

 Ant에서 기본적으로 제공하는 프로퍼티
모든 자바의 시스템 프로퍼티를 Ant의 프로퍼티로 사용할 수 있다.
Basedir – 프로젝트의 기본 디렉토리의 절대 경로. <project> 태그의 basedir 속성에 명시된 값
Ant.file – 빌드 파일의 절대 경로
Ant.version -  Ant 버전
Ant.project.name – 현재 실행중인 프로젝트의 이름 . proejct name 속성으로 지정
Ant.java.version – Ant가 발견한 자바 버전. 현재 “1.1”, “1.2”,”1.3”,”1.4”를 값으로 가질수 있다.

 

셈플

<project name="STRUTS_PROJECT" default="deploy" basedir=".">
  <description>
        simple example build file
    </description>
 
  <target name="init" description="prepare enviroment">
           <property name="catalina.dir" value="C:/Program Files/Apache Group/Tomcat 4.1" />
           <property name="catalina.common.lib.dir" value="${catalina.dir}/common/lib" />
           <property name="webapp.dir" value="webapp" />
           <property name="webapp.WEB-INF.dir" value="${webapp.dir}/WEB-INF" />
           <property name="webapp.WEB-INF.lib.dir" value="${webapp.WEB-INF.dir}/lib" />
           <property name="webapp.WEB-INF.classes.dir" value="${webapp.WEB-INF.dir}/classes" />
           <property name="source.dir" value="${basedir}/src" />
           <property name="build.dir" value="${basedir}/build" />
           <property name="build.classes.dir" value="${build.dir}/classes" />
           <property name="build.jar.dir" value="${build.dir}/jar" />
           <property name="dist.dir" value="dist" />
           <property name="jarfile.name" value="struts_project.jar" />
           <!--set classpath for compile-->
           <path id="compile.classpath">
                    <path>
                            <fileset dir="${catalina.common.lib.dir}">
                                     <include name="*.jar"/>
                            </fileset>
                    </path>
                    <pathelement location="${webapp.WEB-INF.lib.dir}/struts.jar" />
           </path>
  </target>
  <!--delete previous folders-->
  <target name="delete" depends="init" description="delete directory">
           <delete dir="${build.dir}" />
           <delete dir="${dist.dir}" />
  </target>
  <!--create new folders-->
  <target name="create" depends="init" description="create directory">
           <mkdir dir="${build.classes.dir}" />
           <mkdir dir="${build.jar.dir}" />
           <mkdir dir="${dist.dir}" />
  </target>
  <!--compile sources-->
  <target name="compile" depends="delete, create" description="compile java sources">
           <javac srcdir="${source.dir}" destdir="${build.classes.dir}" failonerror="no">
                    <classpath refid="compile.classpath" />
           </javac>
  </target>
  <!--packaging-->
  <target name="package" depends="compile" description="package class files">
           <jar jarfile="${build.jar.dir}/${jarfile.name}" basedir="${build.classes.dir}"/>
  </target>
  <!--copy the jar file-->
  <target name="deploy" depends="package" description="deploy jar files">
           <copy todir="${dist.dir}">
                    <fileset dir="${build.jar.dir}">
                            <include name="**/*.jar"/>
                    </fileset>
           </copy>
  </target>
</project>

 

1. 기본구조

<?xml version=”1.0” encoding=”euc-kr”?>
 
<project name=”projectName” default=”targetNameN” basedir=”.”>
 
        <target name=”init”>………..</target>
 
        <target name=”compile” depends=”init”>………</target>
 
        <target name=”copyJSP” depends=”compile”>………</target>
        <target name=”copyJar” depends=”copyJSP”>………</target>
 
        <target name=”makeWar” depends=”copyJar”>………</target>
 
        <target name=”clean” depends=”makeWAR”>………</target>
 
<project>

 

1.1 Ant의 규칙

  

1.1 Project 요소 설정

속성 설명 필수
name    
default    
basedir    

 

1.2 Property 요소 속성

속성 설명 필수
name    
value 프로퍼티의 값을 지정 Name 속성을 사용했을 경우
둘 중의 하나를 반드시 사용
location 지정한 경로명의 절대 경로명을 값으로 지정
resource 프로퍼티 파일을 읽어 올 때 사용할 자원명을 지정 Name 속성을 사용하지 않은 경우
셋중의 하나를 반드시 사용해야 한다.
file 지정할 파일로부터 프로퍼티 목록을 읽어 온다
environment 환경 변수를 읽어 올 때 사용할 접두어를 지정
classpath 자원으로부터 프로퍼티 파일을 읽어 올 때 사용할 클래스패스  
classpathref 클래스패스로 사용할 경로를 <path>요소로부터 가져온다  
prefix Resource file속성을 사용하여 읽어 온 프로퍼티를 참조 할 때 사용할 접두어를 지정, 접두어 맨 뒤에 “.”가 포함되어 있지 않을 경우, 자동으로 “.”이 접두어 뒤에 붙는다.  

프로퍼티의 값을 사용할 때에는 ${프로퍼티이름} 형식을 사용

 

1.3 Target 요소 설정

속성 설명 필수
name    
depends 의존하고 있는 목록  목록인경우 콤마구분  
if 지정한 프로퍼티가 설정되어 있는 경우 타겟을 수행  
unless 지정한 프로퍼티가 설정되어 있지 않은 경우 타겟을 수행  
description    

 

  

경로 규칙

- 경로 규칙은 파일이나 디렉토리 또는 경로 집합을 사용하는 태스크나 <fileset>이나 <patternset>등에 적용된다.
- ‘*’ ----- 0개 또는 그 이상의 글자가 매칭된다.
- ‘?’ ----- 한 글자와 매칭된다.
- 디렉토리 지정에서’*’를 사용할 경우 디렉토리 트리에서 단 하나의 계층만을 가리키게 되는 반면에 ‘**’는 다계층을 나타낸다.
- ‘**’로 패턴이 끝나게 되면 디렉토리뿐만 아니라 모든 파일을 나타낸다.
Ant에서 excludes속성에 명시하지 않아도 자동으로 처리 대상에 제외되는 파일/디렉토리
**/*~, **/#*#, **/.#*, **/%*%,**/._*
**/CVS,**/CVS/**,**/.cvsignore
**/SCCS,**/SCCS/**
**/vssver.scc
**/.svn, **/.svn/**
**/.DS_Store

 

1.3.1 fileset/dirset 태그 속성  : 파일/디렉토리 집합을 사용하는 태스크에서 사용

속성 설명 필수
dir 파일 집합을 표시할 때의 루트 디렉토리 dir이나file중 한 개를 반드시 명시
file 한 개의 파일을 명시할 때 사용          (fileset만 해당)
casesensitive True일 경우 대소문자를 구분해서 처리, 기본값 true  
followsymlinks 심볼릭 링크를 따라갈지의 여부를 나타낸다 기본값 true  
includes(file) 처리대상에 포함시킬 디렉토리/파일, 속성대신 테그 가능  
excludes(file) 처리대상에 제외시킬 디렉토리/파일, 속성대신 테그 가능  
defaultexcludes 기본적으로 제외되는 파일을 제외시키고 싶지 않으면 defaultexcludes=’no’  

 

   예시

<copy todir=”backup”>
   <fileset dir=”${basedir}”  includes=”src/**,lib/*.jar,jsp,src/**”
           exclude=”**/*.bak”  defaultexcludes=”no” />
</copy>

 

1.3.2 patternset : 파일/디랙토리 집합의 공통부분 지정시(재사용)

- patternset 내에 fileset/dirset 태그 사용

- Includes, includesfile, excludes, excludefile 속성 지원

- Id 속성을 사용하여 패턴 집합의 이름을 지정

- 패턴 집합을 사용할 때에는 refid속성을 사용한다.

예시1) 기본

<patternset id=”commonJar”>
<include name=”servlet.jar”/>
<include name=”mail.jar”/>
<include name=”activation.jar”/>
<patternset>

 

예시2) refid

<pattern refid=”commonJar”/>

 

1.3.3 path : 경로목록을 공통적으로

- <path>에서 경로를 지정할 때에는 <pathelement>태그를 사용

- location 속성은 하나의 디렉토리 또는 파일을 나타낼 때 사용

- 여러 경로를 함께 표시 할 때 각각의 경로는 ‘;’ ‘:’을 사용하여 구분

<path id=”project.class.path”>
     <pathelement location=”classes”/>
     <pathelement path=”lib/servlet.jar;lib/commons-fileupload-1.0.jar”/>
</path>

 

1.3.3 classpath

<classpath>와 같이 경로를 사용하는 태그에서는 refid속성을 사용하여 <path>요소를 경로값으로 사용할 수 있다.

<classpath refid=”project.class.path”/>

 

2 기타 속성 

목록

설명
copy 하위 태그로 fileset, / direst 가능, 속성: todir
mkdir  
javac  
delete  
jar  

 

2.1. javac: 자바 소스 코드 컴파일

속성 설명 필수
srcdir 소스가 위치한 디렉토리를 지정 <src>요소가 사용되지 않은 경우 필수
destdir 생성된 클래스가 위치할 디렉토리를 지정  
includes 컴파일할 파일의 패턴 목록, 기본값 *.java  
classpath 컴파일할 때 사용할 클래스패스.
,<classpath>태그를 사용하여 지정가능
 
classpathref <path>로 지정한 경로를 클래스패스로 참조  
debug 디버그 정보 포함,  기본값 false  
optimize 최적화 사용,       기본값 false  
verbose 긴 결과 제공  
failonerror 오류가 발생하면 빌드 중지, 기본값 true  
encoding 소스 파일의 인코딩을 지정
javac –encoding 옵션과 동일
 
nowarn on을 값으로 가질 경우 컴파일할 때 –nowarn 옵션을 사용. 기본값은 off  
deprecation on을 값으로 가질 경우 –deprecation 옵션을 컴파일할 때에 사용, 기본값은 off  

 

예시

<javac srcdir=”소스 코드가 위치한 디렉토리
       destdir=”컴파일한 클래스가 위치한 디렉토리
       classpath=”클래스패스”>
…….
</javac>

 

2.2. jar: JAR 파일로 압축

- destfile 속성은 생성할 JAR 파일을 지정

- basedir 속성은 jar파일로 압축할 기본 디렉토리 지정

- includes, includesfile, excludes, excludesfile, defualtexcludes 속성 사용

예시

<jar destfile=”${dist}/lib/app.jar”  basedir=”${build}/classes” />

 

2.3. zip : ZIP 파일로 압축

- includes, includesfile, excludes, excludesfile, 속성 사용

- <zipfileset>은 압축되는 파일의 경로명을 변경 가능

속성 설명 필수
prefix ZIP 파일에 압축될 때 변경되어 들어갈 경로명  
fullpath 특정 파일의 변경될 경로를 지정  
filemode 유닉스 기반의 시스템에서 사용되며, 압축되는 파일의 모드를 지정. 기본값은 644  
dirmode 유닉스 기반의 시스템에서 압축되는 디렉토리의 모드를 지정. 기본값은 755  

 

2.4. war : 웹 어플리케이션 압축

- basdir 속성을 사용하여 해당 디렉토리를 WAR파일로 묶는다.

- lib 태그 지정한 파일들을 WEB-INF/lib 디렉토리에 위치하게 해준다.

- classes 태그는 지정한 디렉토리에 위치한 classes 파일들을 WEB-INF/classes디렉토리에 위치하게 해준다.

- webxml 속성은 지정한 파일을 WEB-INF/web.xml 파일로 복사한다

- includes, includesfile, excludes, excludesfile, defualtexcludes 속성 사용

- 파일을 묶을 때 파일의 경로를 변겨해주는 zipfileset 태그 사용 가능

예시

<war destfile=”main.war” webxml=”src/metadata/web.xml”>
   <fileset dir=”src/mainapp/html” />
   <fileset dir=”src/mainapp/j” />
   <lib dir=”lib”>
      <exclude name=”logging2.jar”/>
   </lib>
   <classes dir=”build/main/classes”/>
   <zipfileset dir=”src/imagefile/images” prefix=”images”/>
</war>

 

2.5. tar : TAR 파일의 생성

- basedir속성이나 <fileset> 태그 등을 사용하여 묶을 파일의 목록을 지정

- compression 속성을 사용하여 우너하는 방식으로 압축가능, “gzip”, “bzip2”,”none”값 지정

- tarfileset 태그는 파일을 묶을 때 파일의 경로를 변경해 주며, 파일에 대한 사용자 및 그룹을 지정할 수도 있다.

예시

<tar destfile=”${dist}/example.tar.gz” basedir=”${build}” compression=”gzip”/>

 

속성 설명 필수
mode 3자리 8진수값  
useranme 파일에 대한 사용자 이름을 지정, UID와는 다름  
group 파일에 대한 그룹 이르을 지정, GID와는 다름  
prefix ZIP 파일에 압축될 때 변경되어 들어갈 경로명  
fullpath 특정 파일의 변경될 경로를 지정  
preserveLeadingSlashes 맨 앞의 ‘/’를 유지할지의 여부를 지정, 기본값은 false  

 

2.6. javadoc : API 문서의 생성

- 소스 코드로부터 Javadoc API문서를 생성

- 옵션이 너무 많아서 생략^^;

 

2.7. copy : 파일 복사

- 지정한 디렉토리로 파일을 복사

- 개개의 파일을 복사할 수도 있고 디렉토리 단위로 복사할 수도 있다.

예시

<copy todir=”${build}/src”>
   <fileset dir=”${workspace}/src”/>
</copy>

 

속성 설명 필수
file 복사할 파일을 지정 <fileset>으로 복사할 파일 목록을 지정하지 않은 경우 필수
tofile 복사될 파일을 지정  
todir 원본을 복사할 디렉토리 지정
overwrite true인경우 기존에 존재하는 파일을 덮어 쓴다. 기본값 false  
preservelastmodified True인 경우 원본의 최종 수정 날짜를 유지.   기본값은 false  
includeEmptyDirs <fileset>으로 지정한 디렉토리 중 텅빈 디렉토리도 복사할지의 여부를 지정, 기본값은 true  
failonerror 파일이 없을 경우 빌드 중단, 기본값 true  
verbose 복사한 파일 목록, 기본값 false  

 

2.8. mkdir : 디렉토리의 생성

예시

<mkdir dir=”${build}/webapp/WEB-INF/classes” />

 

2.9. delete : 파일의 삭제

- file 속성 -  특정 파일을 삭제하기 위해 지정

- dir 속성 -  지정 디렉토리 및 그 하위 디렉토리까지 모두 삭제

- includes, includesfile, excludes, excludesfile, defualtexcludes 속성 사용

- <fileset> 태그를 사용하여 삭제할 파일의 집합 표시 가능 (단 파일만 삭제될 뿐 디렉토리는 삭제되지 않는다)

- includeEmptyDirs 속성 - true로 지정하면 텅빈 디렉토리까지 삭제

- failonerror 속성 – 오류시 빌드 중단, 기본값 true

- verbose속성 – 삭제할 파일 목록, 기본값 false

 

2.10. ant : 또 다른 빌드 파일의 실행

- 하나의 프로젝트가 여러 개의 서브 프로젝트로 구성되어 있는 경우 한번에 서브 프로젝트를 포함한 모든 프로젝트를 빌드함

속성 설명 필수
antfile 사용할 빌드 파일을 지정, 명시하지 않을 경우 build.xml파일 사용, dir 속성에 주어진 디렉토리에 대해 상대 경로로 명시해야 함  
dir 새로운 Ant 프로젝트의 basedir을 지정, 사용될 빌드 파일에서 basedir 속성을 지정하고 있다면 무시됨  
target 수행할 타겟을 지정  
output 새로운 Ant 프로젝트의 수행 결과를 저장할 파일을 지정  
inheritAll 기본값 true이며 새로운 Ant 프로젝트는 현재Ant 프로젝트의 모든 프로퍼티를 전달받는다.  
inheritRefs 기본값 true이며 새로운 Ant 프로젝트는 현재 Ant 프로젝트의 모든 참조를 전달받는다.  

 

2.11. java : 자바 실행

속성 설명 필수
classname 실행할 클래스 이름 둘 중 하나 필수
jar 실행할 jar 파일의 위치
classpath 사용할 클래스 패스를 지정  
classpathref 미리 지정한 <path>요소를 참조  
fork true인경우 새로운 가상 머신에서 클래스를 수행, 기본값은 false  
maxmemory 포크된 가상 머신에 할당할 메모리의 최대 크기를 지정 (fork false인 경우 무시)  
dir 가상 머신을 호출할 디렉토리(fork false인 경우 무시)  
output 결과 파일  
append 기본 파일에 연결하거나 겹쳐씀  

 

  예시

<java classname=”Add” classpath=”${basedir}/bin”>
   <arg value=”100”/>
   <arg value=”200”/>
</java>

 

2.12. native2ascii : 유니코드로의 변환..

- ResourceBundle 클래스나 Properties 클래스를 사용하여 프로퍼티 파일로부터 정보를 읽어올 때 파일에 있는 문자를 유니코드로 변환해준다.

- Src 속성은 변환할 파일들의 위치한 기준 디렉토리를 지정

- Dest 속성은 변환한 결과를 저장할 디렉토리

- includes, includesfile, excludes, excludesfile, defualtexcludes 속성 사용

- <include>,<exclude>태그를 사용하여 원하는 파일만 변환처리 가능

- encoding속성은 변환할 파일의 인코딩 지정(명시하지 않을 경우 JVM 기본 인코딩 사용)

- reverse 옵션은 이스케이프된 유니코드를 지정한 인코딩을 사용하는 문자열로 변환

 

2.13. buildnumber : 빌드 번호

- 파일에서 빌드 번호를 읽고 build.number를 설정한 다음 build.number+1의 값을 파일에 기록

예시

<buildnumber file=”buildnum.txt”/>

 

2.14. echo

- System.out(기본값), 파일, 로그, 수신기에 메시지를 기록

속성 설명 필수
message 기록할 텍스트 텍스트를 요소 컨텐츠로 사용하지 않을 경우 필수
file 결과 파일 선택
append 파일을 겹쳐 쓰지 않고 연결, 기본값 false  

  예시

<echo message=”Hello”/>
<echo> This is a message from Ant </echo>

 

2.15 tstamp

- DSTAMP, TSTAMP, TODAY 프로퍼티를 설정

- DSTAMP : yyyyMMdd

- TSTAMP : hhmm

- TODAY : MMM dd yyy

cf. <format> Java SimpleDateFormat 클래스에서 정의한 패턴을 사용해 현식을 변경하는데 쓰인다.

ㅁ IntelliJ 포터블 버전 설치

다운로드 : https://portapps.io/app/intellij-idea-community-portable/

 

Portapps

Portapps is a collection of portable applications for Windows

portapps.io

 exe로 압축풀어놓을때를 선택

 

ㅁ 파일을 가져와서 직접 설치하는 방법이 있다기에 도전해보았다.

 

1. Plugin 파일 다운받기

https://plugins.jetbrains.com/plugin 요 사이트에 들어가면 플러그인들을 검색할 수 있다.

 

JetBrains Marketplace

Welcome to the JetBrains Marketplace

plugins.jetbrains.com

 

원하는 플러그인에 들어가서 Versions 탭에 들어가면 zip 파일을 다운받을 수 있다.

 

 

유의할 점은 자신의 IntelliJ에 맞는 버전을 찾아야한다.

최신이 좋겠지~하면서 최신 버전을 설치하면 버전이 맞지 않는다는 오류가 발생한다.

 

 

2. Install Plugin from Disk

  • Settings - Plugins - 톱니바퀴 - Install Plugin from Disk ... - 파일 선택

 

3. IDE 재시작

 

아쉽게도 내가 사용하려던 플러그인은 커뮤니티 버전에서는 지원 불가능하다고 한다.

그래서 Marketplace에서 검색도 안되던 것 같은데...

IntelliJ의 새로운 기능을 알게된 것으로 만족하겠다 ^-T

ㅁ 영문/한글버전 프로젝트 생성 메뉴 차이

 

 
 

 

영문 한글 비고
Plug-in Project 플러그인 프로젝트 플러그인 개발
Feature Project 기능 프로젝트  
Product Configuration 제품구성  
Target Definition 대상정의  

   

 

ㅁ 컨트리뷰션이란

   오픈소스 프로젝트에 참여하고 기여하는 모든 활동 

ㅁ 핼퍼클래스

       helper class는 특정 클래스의 작업을 도와주는 역할을 하는 클래스로 유용한 기능들을 제공하며, 다른 helper class와는 의존하지 않음 

 

ㅁ 확장 과 확장점

'RCP정리(DevOne프로젝트)' 카테고리의 다른 글

이클립스 팁  (0) 2023.06.04
1. DevOne 특징  (0) 2022.01.31

F11 마지막 디버깅 단축키 
글자 크기  : ctrl + + 크게 ctrl + - 작게 
에러위치 이동 : ctrl + . 

 

C+S+T : 자바타입
C + S + R : 리소스 추가등
C + T : 선택된 리소스 계층도
C + S + G : 참조요소 검색 = C+S+U
C + 3 : 커맨드와 뷰 

A+S+F1 : 플러그인 스파이 (기여된 플러그인과 구현 클래스 정보) -> locationURI

'RCP정리(DevOne프로젝트)' 카테고리의 다른 글

RCP 정리부터다시  (0) 2023.06.04
1. DevOne 특징  (0) 2022.01.31

이클립스 설치시 두가지 더 추가 했는데 하나는 롬복(Getter/Setter 자동생성)

STS : 스프링프레임워크 추가 하여 개발구조화 해보자

1. 이클립스 버전 : 2023-03-R

 

1. 롬복 다운로드

    이클립스 코딩시 : Getter, Setter 메소드를 컴파일시 자동 생성해줌

    다운로드 경로 : https://projectlombok.org/download

 

Download

 

projectlombok.org

 

2. STS(Spring Tools Suite)

   이클립스 마켓플레이스에서  설치함.

울트라에디터에서 한글 사용시 자음 모음이 이상하게 되는경우

윈도우 설정에 IME 설정시 해결됨

 

1. 설정화면

2. 시간 및 언어  선택 0 > 언어 및 지역선택

3. 한국어 옵션에 언어 옵션 선택

4. Microsoft 입력기 -> 키보드 옵션 선택

4. IME 설정 켬으로 변경

'IT > 윈도우 일반' 카테고리의 다른 글

도스 커멘드 정리  (0) 2022.06.18
윈도우 숨겨진 창 보이기  (0) 2022.06.18
명령줄로 연결프로그램 변경  (0) 2022.05.25

관리자권한으로  cmd 실행후  명령어 수행

 

ie4uinit.exe -show

 

캐쉬파일 경로

C:\Users\사용자이름\AppData\Local 에 iconCash.db 파일이 있음 삭제후 재부팅 하면 됨.

 

 

'IT > Tip' 카테고리의 다른 글

[이클립스 ] 툴팁  (0) 2021.07.04

현재 거의 모든 윈도우는 64bit로 MS-Office 설치시 32bit가 깔려 Excel ODBC Driver가 설치 안된경우가 있습니다.

그경우 아래 사이트에서  추가로  Microsoft Access Database Engine 2016를 설치후 사용가능

   ▶ MS Office 설치후 64 bit ODBC 확인방법

        1) 64bit odbc 실행

64bit odbc 열기

    2) 설치 드라이버 확인

64bit 엑셀 ODBC 설치 확인

       ※ 없으면 하단 프로그램 설치후 확인하면 추가 생김

 

   ▶ 64bit MS OFFICE ODBC 설치경로 : https://www.microsoft.com/ko-KR/download/details.aspx?id=54920 

 

Download Microsoft Access Database Engine 2016 재배포 가능 패키지 from Official Microsoft Download Center

중요! 아래에서 언어를 선택하면 전체 페이지 내용이 해당 언어로 신속하게 변경됩니다. 그리스어네덜란드어노르웨이어(복말)덴마크어독일어라트비아어러시아어루마니아어리투아니아어불가

www.microsoft.com

 

 

자바스크립트의 정의는 ‘웹페이지에 생동감을 불어넣기 위해’ 만들어진 프로그래밍 언어

 

먼저 HTML 란? 

     HTML 은 Hyper Text Markup Language 약어로 HyperText(웹 페이지에서 다른 페이지로 이동할 수 있도록 하는 것) 기능을 가진 문서를 만드는 언어입니다.(특히 정적 변화가 없다)

     93~94년도 초기 문서를 만들고 단순 링크로 여러 정보들을 연결하여 처리할수 있도록 만들어진 언어이고 .htm, .html 확장자 포맷을 가지고 있습니다.

 

그럼 JavaScript는 왜 생겨났을까요?

정적인 페이지를 동적으로 변화할수 있도록 만들어진 프로그램 언어입니다. 

 

참고로 Script란 뒷말은 별도 컴파일이 없이 web브라우저에서 실행시 알아서 번역하도록 설계되어 단순 텍스트로만 만들어도 되도록 만들어졌습니다.(컴파일러가 필요없음)

 

Javascript의 기본

<script>  --> JavaScript의 시작

  .. JavaScript 프로그램 코딩

</script>  --> JavaScript의 종료

test.html파일을 만들어 아래같이 넣고 실행해보자

 

ㅁ test.html 파일 내용

<script>
	alert("test");
</script>

==> 결과 

test.html의 결과

ㅁ JavaScript 시작전 기초준비작업

    - 한줄주석 : 중간중간 개발자가 관리적인 내용으로 등록

      // 한줄주석

       /*

          여러줄 주석

       */

    - JavaScript의 시작종료

      <script>   코딩</scirpt>

    - 명령어

        alert(" 내용");    -> 팝업

 

ㅁ 변수정의

   변수(variable)는 데이터를 저장할 때 쓰이는 ‘이름이 붙은 저장소’ 입니다. 온라인 쇼핑몰 애플리케이션을 구축하는 경우 상품이나 방문객 등의 정보를 저장할 때 변수

   

   부연설명 : ‘상자’ 안에 데이터를 저장하는데, 이 상자에는 특별한 이름표가 붙어 있다고 상상해 봅시다. 이렇게 하면 '변수’를 좀 더 쉽게 이해할 수 있습니다.

예를 들어, 변수 message는 message라는 이름표가 붙어있는 상자에 "Hello!"라는 값을 저장한 것이라고 생각할 수 있습니다.

상자 속엔 어떤 값이든지 넣을 수 있습니다.

원하는 만큼 값을 변경할 수도 있습니다.

값이 변경되면, 이전 데이터는 변수에서 제거됩니다.

※ 명령규칙 : 예약어 불가(var, let , return 숫자시작... 등등)

                     중간에 하이픈 불가

                     ex) myName   (true)   <->   my-Name(false)

  변수의 선언예시

let userName;   //시작은 소문자 , 구분에 대문자
let test123;    //뒤에 숫자 가능 
let userName = "10";   //초기값까지 설정

  변수명은 사람이 알아볼수 있는 언어로 사용하자!!

 

ㅁ 상수    

    한번정하면 변하지 않는 수 

const pi = 3.14;   //불변 변하지 않는값을 지정시 변수처럼 바꿀수도 없음

 ㅁ 자료형

자바스크립트의 변수는 자료형에 관계없이 모든 데이터일 수 있습니다. 따라서 변수는 어떤 순간에 문자열일 수 있고 다른 순간엔 숫자가 될 수도 있습니다.

// no error
let message = "hello";
message = 123456;

요약

자바스크립트에는 여덟 가지 기본 자료형이 있습니다.

  • 숫자형 – 정수, 부동 소수점 숫자 등의 숫자를 나타낼 때 사용합니다. 정수의 한계는 ±253 입니다.
  • bigint – 길이 제약 없이 정수를 나타낼 수 있습니다.
  • 문자형 – 빈 문자열이나 글자들로 이뤄진 문자열을 나타낼 때 사용합니다. 단일 문자를 나타내는 별도의 자료형은 없습니다.
  • 불린형  true, false를 나타낼 때 사용합니다.
  • null  null 값만을 위한 독립 자료형입니다. null은 알 수 없는 값을 나타냅니다.
  • undefined  undefined 값만을 위한 독립 자료형입니다. undefined는 할당되지 않은 값을 나타냅니다.
  • 객체형 – 복잡한 데이터 구조를 표현할 때 사용합니다.
  • 심볼형 – 객체의 고유 식별자를 만들 때 사용합니다.

typeof 연산자는 피연산자의 자료형을 알려줍니다.  --> 나중에 

  • typeof x 또는 typeof(x) 형태로 사용합니다.
  • 피연산자의 자료형을 문자열 형태로 반환합니다.
  • null의 typeof 연산은 "object"인데, 이는 언어상 오류입니다. null은 객체가 아닙니다.

이어지는 챕터에선 원시 자료형에 대해 학습해 볼 예정입니다. 원시형에 어느 정도 익숙해지면 객체형에 대해 알아보도록 하겠습니다.

 여기 1~18번이 프로그램 기본으로 꼭 해야될듯

https://ko.javascript.info/strict-mode?map

Eclipse RCP 배포후 java소스내 한글이 깨지는 경우

 

이클립스 RCP 배포 시 소스코드를 재 빌드하는데 프로젝트 설정을 이용하여 빌드 하지 않고 자체적으로
시스템 디폴트 인코딩으로 소스파일을 컴파일 한다.

따라서 보통 윈도우의 경우 MS949로 되어 utf-8로 되어 있는 소스가 아래와 같이 모두 애러가 발생한다.

 

해결방법 : 이클립스 개발툴에 eclipse.ini에 vm 추가 

-vmargs
-Dfile.encoding=UTF-8

 

org.eclipse.equinox.p2.ui

'IT > RCP' 카테고리의 다른 글

[JFace] 뷰어와 뷰어 프레임 워크  (0) 2020.12.26
[RCP] RCP 기본생성 방법  (0) 2020.12.20
[RCP] 개발 환경설정  (0) 2020.12.20
[RCP] 사전 준비 및 주요 용어  (0) 2020.12.20
[SWT] 윈도우 레지스트리  (0) 2020.12.19

Java8에서는 java경로 /jre/bin/에 JdbcOdbc.dll 파일을 가지고 있지 않아서

java7에서 java8의 경로에 복사해야 사용가능함 

 

 

연결 셈플 소스 

import java.sql.*;
 
public class JDBCAccess {
 
    public static void main(String[] args) {
        JDBCAccess jdbcAccess = new JDBCAccess();
        jdbcAccess.run();
    }
 
    public void run() {
        try {
            Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
            java.util.Properties props = new java.util.Properties();
    		props.put("charSet", "euc-kr");
            // javasubname ist der bei der Datenquelle festgelgte subname
            Connection connection = DriverManager.getConnection("jdbc:odbc:Driver={Microsoft Excel Driver (*.xls, *.xlsx, *.xlsm, *.xlsb)};DBQ=D:/test.xls",props);
            Statement statement = connection.createStatement();
            ResultSet result = statement.executeQuery
            ("SELECT * FROM [test$]");
            //System.out.println("ID, Name: ");
            while (result.next()) {
            	System.out.println(result.getString(1));
            }
            result.close();
            statement.close();
            connection.close();
        }
        catch(java.lang.ClassNotFoundException e) {
            System.out.println("JDBC-ODBC-Driver not found");
        }
        catch(java.sql.SQLException e) {
            System.out.println("Error on database"
                    + e.getMessage());
        }
    }
}

이클립스 신버전에는 파이쎤 9.3.0 최신은 설치되지만

구번에전에 설치가 안되는듯 

 

파이쎤에 설치버전별 뭔가 제약이 있음

https://www.pydev.org/manual_101_install.html

 

Install

Corrupted install Eclipse sometimes is not able to correctly get the plugin, from the update site but will do no checking on whether it is really correct (no md5 checking), and when this happens, you'll usually get a ClassNotFoundException (similar to the

www.pydev.org

이전 Eclipse/Java/Python을 사용해야 합니다.

Eclipse/Java/Python의 이전 버전을 사용해야 하는 경우 요구 사항에 따라 사용할 최신 PyDev 버전이 아래에 있습니다.

  • 이클립스 4.18, 자바 8: PyDev 8.2.0
  • 이클립스 4.5, 자바 8: PyDev 5.2.0
  • 이클립스 3.8, 자바 7: PyDev 4.5.5
  • 이클립스 3.x, 자바 6: PyDev 2.8.2
  • Python 2.5 이상: PyDev 5.5.0

참고: 이전 버전과의 호환성을 중단한 Java 16은 PyDev 9.0.0에서만 지원됩니다. 참고: Eclipse 4.19에는 PyDev가 제대로 작동하지 않는 중요한 문제가 있습니다.

 

파이쎤 버전별 update sizte 

https://www.pydev.org/update_sites/

 

https://www.pydev.org/update_sites/

 

www.pydev.org

 

파이쎤 sourceforget site

https://sourceforge.net/projects/pydev/files/pydev/

'IT > Python' 카테고리의 다른 글

python 이클립스 설치  (0) 2022.07.31
Python 포트블 환경설정(embeddable)  (0) 2022.07.31

실행될 기능을 캡슐화함으로써 주어진 여러 기능을 실행할 수 있는 재사용성이 높은 클래스를 설계하는 패턴

  • 즉, 이벤트가 발생했을 때 실행될 기능이 다양하면서도 변경이 필요한 경우에 이벤트를 발생시키는 클래스를 변경하지 않고 재사용하고자 할 때 유용하다.
  • ‘행위(Behavioral) 패턴’의 하나 (아래 참고)

실행될 기능을 캡슐화함으로써 기능의 실행을 요구하는 호출자(Invoker) 클래스와 실제 기능을 실행하는 수신자(Receiver) 클래스 사이의 의존성을 제거한다.

따라서 실행될 기능의 변경에도 호출자 클래스를 수정 없이 그대로 사용 할 수 있도록 해준다.

 

역할이 수행하는 작업
- Command
  실행될 기능에 대한 인터페이스
  실행될 기능을 execute 메서드로 선언함
- ConcreteCommand
  실제로 실행되는 기능을 구현
  즉, Command라는 인터페이스를 구현함
- Invoker
  기능의 실행을 요청하는 호출자 클래스
- Receiver
  ConcreteCommand에서 execute 메서드를 구현할 때 필요한 클래스
  즉, ConcreteCommand의 기능을 실행하기 위해 사용하는 수신자 클래스

 

예시
   만능 버튼 만들기


버튼이 눌리면 램프의 불이 켜지는 프로그램
Lamp 생성에 Button 클래스에 넘기고  press하면 램프 켜짐

package com.patterns.CommandPattern;

public class Lamp {
	public void turnOn() {
		System.out.println("Lamp On");
	}
	
	public static void main(String[] args) {
		Lamp lamp = new Lamp();
		Button1 lampButton = new Button1(lamp);
		lampButton.pressed();
	}
}

class Button1 {
	private Lamp theLamp;

	public Button1(Lamp theLamp) {
		this.theLamp = theLamp;
	}

	public void pressed() {
		theLamp.turnOn();
	}
}
  • Button 클래스의 생성자를 이용해 불을 켤 Lamp 객체를 전달한다.
  • Buttom 클래스의 pressed()가 호출되면 생성자를 통해 전달받은 Lamp 객체의 turnOn()를 호출해 불을 켠다.


문제점
1. 버튼을 눌렀을 때 다른 기능을 실행하는 경우
   버튼을 눌렀을 때 알람이 시작되게 하려면?

package com.patterns.CommandPattern;

public class Alarm {
	public void start() {
		System.out.println("Alarming");
	}

	public static void main(String[] args) {
		 Alarm alarm = new Alarm();
		 Button2 alarmButton = new Button2(alarm);
		 alarmButton.pressed();
		  }
		
}

class Button2 {
	private Alarm theAlarm;

	public Button2(Alarm theAlarm) {
		this.theAlarm = theAlarm;
	}

	public void pressed() {
		theAlarm.start();
	}
}
  • 새로운 기능으로 변경하려고 기존 코드(Button 클래스)의 내용을 수정해야 하므로 OCP에 위배된다.
  • Button 클래스의 pressed() 전체를 변경해야 한다.


2. 버튼을 누르는 동작에 따라 다른 기능을 실행하는 경우
    버튼을 처음 눌렀을 때는 램프를 켜고, 두 번째 눌렀을 때는 알람을 동작하게 하려면?

package com.patterns.CommandPattern;

enum Mode {
	LAMP, ALARM
};

public class Button3 {
	private Lamp theLamp;
	private Alarm theAlarm;
	private Mode theMode;

	// 생성자에서 버튼을 눌렀을 때 필요한 기능을 인지로 받는다.
	public Button3(Lamp theLamp, Alarm theAlarm) {
	   this.theLamp = theLamp;
	   this.theAlarm = theAlarm;
	  }

	// 램프 모드 또는 알람 모드를 설정
	public void setMode(Mode mode) {
		this.theMode = mode;
	}

	// 설정된 모드에 따라 램프를 켜거나 알람을 울림
	public void pressed() {
		switch (theMode) {
		case LAMP:
			theLamp.turnOn();
			break;
		case ALARM:
			theAlarm.start();
			break;
		}
	}
}
  • 필요한 기능을 새로 추가할 때마다 Button 클래스의 코드를 수정해야 하므로 재사용하기 어렵다.

 

해결책

  • 문제를 해결하기 위해서는 구체적인 기능을 직접 구현하는 대신 실행될 기능을 캡슐화해야 한다.

    즉, Button 클래스의 pressed 메서드에서 구체적인 기능(램프 켜기, 알람 동작 등)을 직접 구현하는 대신 버튼을 눌렀을 때 실행될 기능을 Button 클래스 외부에서 제공받아 캡슐화해 pressed 메서드에서 호출한다.
  • 이를 통해 Button 클래스 코드를 수정하지 않고 그대로 사용할 수 있다.

Button 클래스는 미리 약속된 Command 인터페이스의 execute 메서드를 호출한다.
램프를 켜는 경우에는 theLamp.turnOn 메서드를 호출하고 알람이 동작하는 경우에는 theAlarm.start 메서드를 호출하도록 pressed 메서드를 수정한다.
LampOnCommand 클래스에서는 Command 인터페이스의 execute 메서드를 구현해 Lamp 클래스의 turnOn 메서드(램프 켜는 기능)를 호출한다.
마찬가지로 AlarmStartCommand 클래스는 Command 인터페이스의 execute 메서드를 구현해 Alarm 클래스의 start 메서드(알람이 울리는 기능)를 호출한다.

 

Command.java : 인터페이스 

package com.patterns.CommandPattern;

public interface Command {
	public abstract void execute(); 
}

Button.java : 생성시 setCommand, 별도 setCommand, press

package com.patterns.CommandPattern;

public class Button {
	private Command theCommand;

	// 생성자에서 버튼을 눌렀을 때 필요한 기능을 인지로 받는다.
	public Button(Command theCommand) {
		setCommand(theCommand);
	}

	public void setCommand(Command newCommand) {
		this.theCommand = newCommand;
	}

	// 버튼이 눌리면 주어진 Command의 execute 메서드를 호출한다.
	public void pressed() {
		theCommand.execute();
	}
}

각각 Command를 상속받아 ConcreateCommand를 구성

package com.patterns.CommandPattern;

/* 램프를 켜는 LampOnCommand 클래스 */
public class LampOnCommand implements Command {
	private Lamp theLamp;

	public LampOnCommand(Lamp theLamp) {
		this.theLamp = theLamp;
	}

// Command 인터페이스의 execute 메서드
	public void execute() {
		theLamp.turnOn();
	}
}
package com.patterns.CommandPattern;

/* 알람을 울리는 AlarmStartCommand 클래스 */
public class AlarmStartCommand implements Command {
	private Alarm theAlarm;

	public AlarmStartCommand(Alarm theAlarm) {
		this.theAlarm = theAlarm;
	}

// Command 인터페이스의 execute 메서드
	public void execute() {
		theAlarm.start();
	}
}

수신자 구체적인 기능을 구현 : Lamp.java, Alarm.java

package com.patterns.CommandPattern;

public class Lamp {

	public void turnOn() {
		System.out.println("Lamp On");
	}
}
package com.patterns.CommandPattern;

public class Alarm {
	public void start() {
		System.out.println("Alarming");
	}
}

테스트

package com.patterns.CommandPattern;

public class Client {

	public static void main(String[] args) {
		Lamp lamp = new Lamp();
		Command lampOnCommand = new LampOnCommand(lamp);
		Alarm alarm = new Alarm();
		Command alarmStartCommand = new AlarmStartCommand(alarm);

		Button button1 = new Button(lampOnCommand); // 램프 켜는 Command 설정
		button1.pressed(); // 램프 켜는 기능 수행

		Button button2 = new Button(alarmStartCommand); // 알람 울리는 Command 설정
		button2.pressed(); // 알람 울리는 기능 수행
		button2.setCommand(lampOnCommand); // 다시 램프 켜는 Command로 설정
		button2.pressed(); // 램프 켜는 기능 수행
	}
}


Command 인터페이스를 구현하는 LampOnCommand와 AlarmStartCommand 객체를 Button 객체에 설정한다.
Button 클래스의 pressed 메서드에서 Command 인터페이스의 execute 메서드를 호출한다.
즉, 버튼을 눌렀을 때 필요한 임의의 기능은 Command 인터페이스를 구현한 클래스의 객체를 Button 객체에 설정해서 실행할 수 있다.
이렇게 Command 패턴을 이용하면 Button 클래스의 코드를 변경하지 않으면서 다양한 동작을 구현할 수 있게 된다.

 

확장설계

참고 원문 : https://gmlwjd9405.github.io/2018/07/07/command-pattern.html

문법적 규칙을 클래스화 하여, 일련의 규칙을 통해 언어/문법을 해석하는 패턴이다.

 사용되는 곳

​ SQL 문은 SELECT (어쩌구) FROM (저쩌구) WHERE (이러쿵저러쿵) 과 같이

​ 특정 문법을 지키면 MYSQL에서 알아서 쿼리결과를 짠 하고 내줍니다.

​ 덕분에 개발자들은 손쉽게 DB에서 결과를 얻게 됩니다.

​ 이렇듯 간단한 문법적 규칙(대체로 문자열을 해석하는)을 클래스화해서 사용자가 원하는 답을 얻게 해주는 패턴이 Interpreter 패턴입니다.

​ 주로 SQL 해석, shell 명령어 해석기 등에 사용하는 패턴입니다.

 구현을 어떻게 할까 (구현 예시)

​ Interpreter 패턴으로 후위 표기법 을 구현해보겠습니다.

​ 후위 표기법에서는 1+2 를 1 2 + 로 표현합니다.

​ (3 + 5) (4 + 2) => 3 5 + 4 2 +

​ 우리가 "a b +" 를 요청해도, "w x z - +" 를 요청해도

​ 문법 해석기가 알아서 해석해서 결과를 줄 수 있어야 합니다.

 

코드로 살펴볼까요!

  1. 연산자들
  • 연산자 interface
package com.patterns.InterpreterPattern;

import java.util.Map;

public interface Expression {
	public int interpret(Map<String, Expression> variables);
}
  • Plus 연산자 구현
package com.patterns.InterpreterPattern;

import java.util.Map;

public class Plus implements Expression {

	//+의 왼쪽에 올 표현(숫자일 수도 있고 이미 연산된 결과일 수 있음)
    Expression leftOperand;
     //+의 오른쪽에 올 표현
    Expression rightOperand;

    public Plus(Expression leftOperand, Expression rightOperand) {
        this.leftOperand = leftOperand;
        this.rightOperand = rightOperand;
    }

    @Override
    public int interpret(Map variables) {
        //왼쪽과 오른쪽의 결과를 더해서 반환
        return leftOperand.interpret(variables)+rightOperand.interpret(variables);
    }

}
  • Minus 연산자 구현
package com.patterns.InterpreterPattern;

import java.util.Map;

public class Minus implements Expression{
	//-의 왼쪽에 올 표현(숫자일 수도 있고 이미 연산된 결과일 수 있음)
    Expression leftOperand;
    //-의 왼쪽에 올 표현(숫자일 수도 있고 이미 연산된 결과일 수 있음)
    Expression rightOperand;

    public Minus(Expression leftOperand, Expression rightOperand) {
        this.leftOperand = leftOperand;
        this.rightOperand = rightOperand;
    }

    @Override
    public int interpret(Map variables) {
         //왼쪽에서 오른쪽의 결과를 빼서 반환
        return leftOperand.interpret(variables)-rightOperand.interpret(variables);
    }
}
  • Variable(알파벳에 해당) 연산자 구현
package com.patterns.InterpreterPattern;

import java.util.Map;

public class Variable implements Expression {

	private String alphabet;

    public Variable(String alphabet) {
        this.alphabet = alphabet;
    }

    @Override
    public int interpret(Map<String, Expression> variables) {
        // 사용자가 입력한 Map에 alphabet이 있으면 그 알파벳에 해당하는 숫자 반환
        // 없으면 0 반환 
        if(variables.get(alphabet) == null)
            return 0;
        return variables.get(alphabet).interpret(variables);
    }

}
  • Number(사용자가 입력한 숫자) 연산자 구현
public class Number implements Expression{
    private int num;

    public Number(int num) {
        this.num = num;
    }

    @Override
    public int interpret(Map variables) {
        return num; //숫자를 반환
    }
}
  1. 문법에 따라 연산 제조
  • Evaluator(해석기) 구현
  • 후위 연산법은 스택을 통해 구현합니다.(참고 : 후위 표기법)
package com.patterns.InterpreterPattern;

import java.util.Map;
import java.util.Stack;

public class Evaluator implements Expression{
    private Expression syntax; //만들 최종 해석
    
    public Evaluator(String expression){
        //expression을 입력받음
        Stack<Expression> stack = new Stack<Expression>();

        for(String strToken : expression.split(" ")){
            if(strToken.equals("+")){
                Expression expressionPlus = new Plus(stack.pop(),stack.pop());
                stack.push(expressionPlus);
            }else if(strToken.equals("-")){
                Expression expressionMinus = new Minus(stack.pop(),stack.pop());
                stack.push(expressionMinus);
            }else {
                stack.push(new Variable(strToken));
            }
        }
        //해석 결과로 나온 계산기 
        syntax = stack.pop();
    }

    //사용자가 입력한 숫자로 계산기에 계산돌리기
    @Override
    public int interpret(Map<String, Expression> variables) {
        return syntax.interpret(variables);
    }
}

 

테스트

package com.patterns.InterpreterPattern;

import java.util.HashMap;
import java.util.Map;

public class InterpreteTest {
	public static void main(String[] args) {
		//해석을 원하는 문장
        String expression ="w x z - +";
        
        //문장에 따른 해석기를 제작
        Evaluator sentence = new Evaluator(expression);

        //사용자가 w = 5, x = 10, z =42 를 입력
        Map<String, Expression> variables = new HashMap<String, Expression> ();
        variables.put("w",new Number(5));
        variables.put("x",new Number(10));
        variables.put("z",new Number(42));

        //해석기에 입력을 넣고 결과 얻기
        int result = sentence.interpret(variables);
        System.out.println(result);
    }
}

결과

"w x z - +"

(z-x) + w == (42-10) + 5

37

 

 참고한 링크들

https://velog.io/@hoit_98/%EB%94%94%EC%9E%90%EC%9D%B8-%ED%8C%A8%ED%84%B4-Interpreter-%ED%8C%A8%ED%84%B4

 

[디자인 패턴] Interpreter 패턴

​ 문법적 규칙을 클래스화 하여, 일련의 규칙을 통해 언어/문법을 해석하는 패턴이다.​ SQL 문은 SELECT (어쩌구) FROM (저쩌구) WHERE (이러쿵저러쿵) 과 같이​ 특정 문법을 지키면 MYSQL에서 알아서

velog.io

  1. 기본적인 Interpreter 패턴이해
  2. https://beomseok95.tistory.com/288
  3. 구체적인 Interpreter 패턴 구현(후위 표기법 구현)
  4. https://hamait.tistory.com/199
 

[Design Pattern] Interpreter Pattern

[Design Pattern] Interpreter Pattern Interpreter Pattern에 대하여 알아보고 , 자바 코틀린 예제를 봐보도록 하겠습니다. Interpreter Pattern이란???? 문법 규칙을 클래스화 한 구조로써, 일련의 규칙으로 정..

beomseok95.tistory.com

 

Interpreter 패턴

GOF 의 디자인패턴중 하나인 인터프리터 패턴에 대해서 살펴보도록 하자. 인터프리터 패턴은 모든 종류의 GoF 패턴들 중에 가장 어렵다. 물론 인터프리터 자체를 만드는게 어렵 기때문에 덩달아

hamait.tistory.com

 

Visitor는 사전적인 의미로 어떤 장소에 찾아오는 사람이라는 의미를 갖고 있다. 방문자 패턴에서는 데이터 구조와 처리를 분리한다. 데이터 구조 안을 돌아다니는 주체인 방문자를 나타내는 클래스를 준비해서 처리를 맡긴다. 새로운 처리를 추가하고 싶을 땐 새로운 방문자를 만들고 데이터 구조는 방문자를 받아들이면 된다.

방문자 패턴은 개방-폐쇠 원칙을 적용하는 방법 중 한 가지이다.
[확장에 대해 열려있다.]
클래스를 설계할 때, 특별한 이유가 없는 한 확장을 금지해서는 안된다.

[수정에 대해 닫혀있다.]
확장을 할 때 마다 기존의 클래스를 수정하면 안된다.

[Visitor]
데이터 구조 내 각각의 구체적인 요소에 visit메소드를 선언한다.

[ConcreteVisitor]
Visitor 인터페이스를 구현하고, ConcreteAccepter 역할을 처리한다.

[Acceptor]
Acceptor는 Visitor역할이 방문할 곳을 나타낸은 역할을 하고 있다. 방문자를 받아들이는 accept메소드를 선언한다.

[ConcreteAcceptor]
Acceptor 인터페이스를 구현하는 역할을 한다.

[ObjectStructure]
Acceptor역할의 집할을 취급하는 역할을 한다.

연습

위 개념을 토대로 방문자 패턴을 적용하여 마트에서 물건을 사는 사람을 예로 들어보자!

 

Element.java  : Element는 인터페이스로, 방문자를 받아들이기 위한 accept메소드를 가지고 있다.

package com.patterns.VistorPattern;

public interface Element {
	public void accept(Visitor visitor);
}

 

Cart.java :담을 물품을 추가한다. 카트에 추가된 물품의 개수 만큼 반복문을 돌며 해당 요소의 accept메소드를 실행한다.

 

package com.patterns.VistorPattern;

import java.util.ArrayList;

public class Cart implements Element {

	ArrayList<Element> cart = new ArrayList<>();

	public Cart() {
		cart.add(new Snack());
		cart.add(new Milk());
	}

	@Override
	public void accept(Visitor visitor) {
		System.out.println("카트가 준비되었습니다.");
		visitor.visit(this);

		for (Element element : cart) {
			element.accept(visitor);
		}
	}

}

Snack.java

package com.patterns.VistorPattern;

public class Snack implements Element {

	@Override
	public void accept(Visitor visitor) {
		System.out.println("과자가 준비되었습니다.");
        visitor.visit(this);
	}

}

Milk.java

package com.patterns.VistorPattern;

public class Milk implements Element {

	@Override
	public void accept(Visitor visitor) {
		System.out.println("우유가 준비되었습니다.");
        visitor.visit(this);
	}

}

 

Visitor.java : 인터페이스 정의

package com.patterns.VistorPattern;

public interface  Visitor {
    public void visit(Cart cart);
    public void visit(Snack snack);
    public void visit(Milk milk);
}

Shopper.java : Visitor 의 구현체

package com.patterns.VistorPattern;

public class Shopper implements Visitor {

	@Override
    public void visit(Cart cart) {
    	System.out.println("카트를 사용합니다.");
    }
    
    @Override
    public void visit(Snack snack) {
    	System.out.println("과자를 카트에 넣습니다.");
    }
    
    @Override
    public void visit(Milk milk) {
    	System.out.println("우유를 카트에 넣습니다.");
    }

}

테스트 

package com.patterns.VistorPattern;

public class Client {
	
	public static void main(String args[]) {
        Shopper shopper = new Shopper();
        Cart cart = new Cart();
        cart.accept(shopper);
    }
}

 

정리

- 정리하자면 방문자 패턴은, 기존 클래스 필드 정보를 유지하면서 새로운 연산을 추가하는 방식이다!

참고

비지터 패턴 - 위키 백과
방문자 패턴(Visitor Pattern)

 

참고 원문 : https://velog.io/@newtownboy/%EB%94%94%EC%9E%90%EC%9D%B8%ED%8C%A8%ED%84%B4-%EB%B0%A9%EB%AC%B8%EC%9E%90%ED%8C%A8%ED%84%B4Visitor-Pattern

 

[디자인패턴] 방문자패턴(Visitor Pattern)

Visitor는 사전적인 의미로 어떤 장소에 찾아오는 사람이라는 의미를 갖고 있다. 방문자 패턴에서는 데이터 구조와 처리를 분리한다. 데이터 구조 안을 돌아다니는 주체인 방문자를 나타내는 클

velog.io

 

메멘토 패턴은 객체의 상태 정보를 저장하고 사용자의 필요에 의하여 원하는 시점의 데이터를 복원 할 수 있는 패턴을 의미합니다.

 

메멘토 패턴 예제 구조

 

 실제로 메멘토 패턴을 사용하여 객체 정보를 저장하고 복원하는 예제를 살펴 보겠습니다. 예제는 간단히 String형 데이터 하나와 Int형 데이터 하나에 대한 정보로 가지는 Information 객체를 구현하였습니다.

 

 User : 메멘토 패턴이 적용 된 Information 객체를 실제로 사용하는 사용자입니다.

 Information : 상태를 저장하고 복원 할 데이터를 가지고 있는 클래스입니다.

 Memento : 특정 시점의 Information의 상태정보를 저장하는 클래스입니다.

 CareTaker : 상태 정보가 저장되어 있는 Memento들을 관리하는 클래스입니다. 내부에 Stack 자료형 변수를 가짐으로써 Memento 객체를 저장하고 복원을 합니다.

 

 

■ 구현

Information.java

package com.patterns.MementoPattern;

public class Information {
	private String Data1; 	// Information이 가지고 있는 데이터1
	private int Data2; 		// Information이 가지고 있는 데이터2

	public Information(String Data1, int Data2) // 생성자입니다.
	{
		this.Data1 = Data1;
		this.Data2 = Data2;
	}

	public Memento CreateMemento() // Memento를 생성합니다 (상태저장)
	{
		return new Memento(this.Data1, this.Data2);
	}

	public void RestorMemento(Memento memento) // Memento를 복원합니다 (상태복원)
	{
		this.Data1 = memento.getData1();
		this.Data2 = memento.getData2();
	}

	public void set_Data1(String Data1) // 데이터1의 값을 지정
	{
		this.Data1 = Data1;
	}

	public void set_Data2(int Data2) // 데이터2의 값을 지정
	{
		this.Data2 = Data2;
	}

	public String get_Data1() // 데이터 1의 값 반환
	{
		return this.Data1;
	}

	public int get_Data2() // 데이터 2의 값 반환
	{
		return this.Data2;
	}
}
 

▶실제 데이터 값을 가지고 있는 Information 클래스입니다. Information 클래스는 String형 데이터 Data1과 int형 데이터 Data2를 속성으로 가지고 각각 setter/getter 메서드가 구현되어 있습니다. 현재 Information 상태를 저장하기 위한 CreateMemento 메서드 ( 내부적으로 Data1과 Data2의 데이터 값을 가지는 Memento 객체를 생성)와 상태복원을 위한 RestorMemento가 구현되어 있습니다. RestoreMemento는 이전에 생성된 Memento 객체의 정보를 가져와 Information 상태 정보로 setting을 하게 됩니다.

Memento.java

package com.patterns.MementoPattern;

public class Memento {
    
    //Information의 상태정보를 가지고 있음
    private String Data1;
    private int Data2;
    
    public Memento(String Data1,int Data2)
    {
        this.Data1 = Data1;
        this.Data2 = Data2;
    }
    public String getData1()
    {
        return this.Data1;
    }
    public int getData2()
    {
        return this.Data2;
    }
}
 

▶Memento는 Information의 특정 시점에 대한 내부 상태 정보를 가지고 있습니다.

CareTaker.java

package com.patterns.MementoPattern;

import java.util.Stack;

public class CareTaker {

	Stack<Memento> mementos = new Stack<>(); // Memento 관리를 위한 Stack

	public void push(Memento memento) // 특정 시점에 생성된 Memento를 Push
	{
		mementos.push(memento);
	}

	public Memento pop() // 복원을 위한 Memento 객체 반환
	{
		return mementos.pop();
	}
}
 
 

CareTaker는 Inforamtion의 상태 정보를 저장하고 있는 Memento들을 관리하기 위한 클래스입니다. 내부적으로 Memento를 저장하기 위한 Stack 자료 구조가 존재하며 push와 pop을 통해 Memento객체를 저장하고 복원을 하게 됩니다.

User.java

package com.patterns.MementoPattern;

public class User {

	Information info;
	CareTaker caretaker;

	public void exe() {
		info = new Information("Data1", 10); // Information 객체 생성
		caretaker = new CareTaker(); // CareTaker 객체 생성
		// 현재 Information의 상태 정보를 가지는 Memento를 생성하여 CareTaker에 추가합니다.
		caretaker.push(info.CreateMemento());

		// Information 정보를 수정합니다.
		info.set_Data1("Data2");
		info.set_Data2(20);
		// 현재 Information의 상태정보를 출력합니다.
		System.out.println("현재 Data1 : " + info.get_Data1());
		System.out.println("현재 Data2 : " + info.get_Data2());
		// 가장 최근에 생성 된 Memento를 가지고와서 상태 정보를 복원합니다.
		info.RestorMemento(caretaker.pop());
		// 상태 정보를 복원 한 후에 Information의 상태 정보를 출력합니다.
		System.out.println("복구된 Data1 : " + info.get_Data1());
		System.out.println("복구된 Data2 : " + info.get_Data2());
	}
	
	public static void main(String[] args) {
		User user = new User();
		user.exe();
	}
}
 
 

▶ 실제로 Information의 정보를 다루는 User입니다. 10번 라인에서 특정 시점의 Information의 상태 정보를 저장하고 19번 라인에서 상태 정보를 복원하는 모습입니다.

 

 

참고 원본 : https://lktprogrammer.tistory.com/65

 

14 메멘토 패턴 (Memento Pattern)

메멘토 패턴 (Memento Pattern) 메멘토 패턴은 객체의 상태 정보를 저장하고 사용자의 필요에 의하여 원하는 시점의 데이터를 복원 할 수 있는 패턴을 의미합니다. ■메멘토 패턴 예제 구조 ▶ 실제

lktprogrammer.tistory.com

 

정의

  • 명령 객체와 일련의 처리 객체를 포함하는 디자인 패턴이다. 각각의 처리 객체는 명령 객체를 처리할 수 있는 연산의 집합이고, 체인 안의 처리 객체가 핸들할 수 없는 명령은 다음 처리 객체로 넘겨진다.
  • 이 작동방식은 새로운 처리 객체부터 체인의 끝까지 다시 반복된다.

쉽게 설명하면

  • 어떤 요청이 그 요청을 담당하는 객체에 들어오면 각각의 요청에 대해서 특정한 객체가 담당하는 것이 일반적이지만 객체를 연결리스트와 같은 사슬 방식으로 연결한 후에 요청을 수행하지 못하는 객체라면 다음 객체에 넘기며 책임을 넘기는 형태의 패턴을 말한다.

목적

  • 이 패턴은 결합을 느슨하게 하기 위해 고안되었으며 가장 좋은 프로그래밍 사례로 꼽힌다. 요청을 보내는 객체와 이를 처리하는 객체간의 결합도를 느슨하게 하기 위한 방법이며 여러 객체에 처리 기회를 준다.
  • 책임연쇄 패턴 장점
  1. 결합도를 낮추며, 요청의 발신자와 수신자를 분리시킬 수 있다.
  2. 클라이언트는 처리객체의 집합 내부의 구조를 알 필요가 없다.
  3. 집합 내의 처리 순서를 변경하거나 처리객체를 추가 또는 삭제할 수 있어 유연성이 향상된다.
  4. 새로운 요청에 대한 처리객체 생성이 매우 편리하다.
  • 책임연쇄 패턴 단점
  1. 충분한 디버깅을 거치지 않았을 경우 집합 내부에서 사이클이 발생할 수 있다.
  2. 디버깅 및 테스트가 쉽지 않다.
  • 책임연쇄 패턴 구조

  1. Handler
    요청을 수신하고 처리객체들의 집합에 전달하는 인터페이스이다.
    집합의 첫 번째 핸들러에 대한 정보만 가지고 있으며 그 이후의 핸들러에 대해서는 알 수 없다.
  2. Concrete Handler
    요청을 처리하는 실제 처리객체입니다.
  3. Client
    요청을 전달하는 클라이언트입니다.
  • 예제 코드

       가장 대표적인 연쇄 책임 패턴의 예는 Java 에서의 try catch 문의 있다.

    try {
        ...     
    } catch (IllegalArgumentException e) {
        someCode();
    } catch (SecurityException e) {
        someCode();
    } catch (IllegalAccessException e) {
        someCode();
    } catch (NoSuchFieldException e) {
        someCode();
    } finally {
        ...
    }
  • 동전을 거슬러주는 프로그램을 만든다고 해보자.
  • 그리고 동전은 100원, 10원, 1원 으로만 거슬러줄수 있다고 가정해보자.
  • 이경우는 100원 -> 10원 -> 1원으로 넘겨주는 방식으로 연쇄책임패턴을 구현할수있다.

Currency.java : PJO 선언

package com.patterns.ChainofResponsibility;

public class Currency {
	private int amount;

	public Currency(int amt) {
		this.amount = amt;
	}

	public int getAmount() {
		return this.amount;
	}
}

 

DispenseChain.java : 인터페이스로 선언

package com.patterns.ChainofResponsibility;

public interface DispenseChain {
	void setNextChain(DispenseChain nextChain);  //다음체인 넘겨줌
    void dispense(Currency cur);	  //분배
}

Won100Dispenser.java 

package com.patterns.ChainofResponsibility;

public class Won100Dispenser implements DispenseChain {

	private DispenseChain chain;

	@Override
	public void setNextChain(DispenseChain nextChain) {
		this.chain = nextChain;
	}

	@Override
	public void dispense(Currency cur) {
		if (cur.getAmount() >= 100) {
			int num = cur.getAmount() / 100;
			int remainder = cur.getAmount() % 100;

			System.out.println("Dispensing " + num + " 100₩ note");

			if (remainder != 0)
				this.chain.dispense(new Currency(remainder));
		} else
			this.chain.dispense(cur);
	}

}

Won10Dispenser.java

package com.patterns.ChainofResponsibility;

public class Won10Dispenser implements DispenseChain {

	private DispenseChain chain;
	
	@Override
    public void setNextChain(DispenseChain nextChain) {
        this.chain=nextChain;
    }
    
    @Override
    public void dispense(Currency cur) {
        if(cur.getAmount()>=10){
            int num=cur.getAmount()/10;
            int remainder=cur.getAmount()%10;
            
            System.out.println("Dispensing " +num+" 10₩ note");
            
            if(remainder!=0) this.chain.dispense(new Currency(remainder));    
        }
        else this.chain.dispense(cur);
    }
}

Won1Dispenser.java

package com.patterns.ChainofResponsibility;

public class Won1Dispenser implements DispenseChain {

	private DispenseChain chain;

	@Override
	public void setNextChain(DispenseChain nextChain) {
		this.chain = nextChain;
	}

	@Override
	public void dispense(Currency cur) {
		int num = cur.getAmount() / 1;
		System.out.println("Dispensing " + num + " 1₩ note");
	}

}

분배체인 인터페이스(DispenseChain) 통해 Won100Dispenser - > Won10Dispenser -> Won1Dispenser로 넘김

 

테스트

package com.patterns.ChainofResponsibility;

public class ChainTest {
    
	private DispenseChain c1;
	
    public ChainTest(){
        this.c1=new Won100Dispenser();
        DispenseChain c2=new Won10Dispenser();
        DispenseChain c3=new Won1Dispenser();
        
        c1.setNextChain(c2);
        c2.setNextChain(c3);
    }
    
    public static void main(String[] args) {
    	
    	
    	ChainTest atmDispenser = new ChainTest();
        atmDispenser.c1.dispense(new Currency(378));
    }
}

 

참고원문 : https://k0102575.github.io/articles/2020-02/chain-of-responsibility-pattern

 

책임 연쇄 패턴(chain-of-responsibility pattern)

연쇄책임패턴 (Chain-of-responsibility pattern)

k0102575.github.io

 

상태 패턴(State Pattern)

state 패턴은 객체가 특정 상태에 따라 행위를 달리하는 상황에서 자신이 직접 상태를 체크하여 상태에 따라 행위를 호출하지 않고 상태를 객체화하여 상태가 행동을 할 수 있도록 위임하는 패턴이다.

 

즉, 객체의 특정 상태를 클래스로 선언하고,클래스에서는 해당 스테이트 패턴은 객체가 특정 상태에 따라 행위를 달리하는 상황에서,자신이 직접 상태를 체크하여 상태에 따라 행위를 호출하지 않고,상태를 객체화 하여 상태가 행동을 할 수 있도록 위임하는 패턴을 말합니다.

 

즉, 객체의 특정 상태를 클래스로 선언하고, 클래스에서는 해당 상태에서 할 수 있는 행위들을 메서드로 정의한다.
그리고 이러한 각 상태 클래스들을 인터페이스로 캡슐화 하여, 클라이언트에서 인터페이스를 호출하는 방식을 말한다.

상태에 기반한 behavior object를 만들 때 이용하고 State machine diagram을 쓸 때 만드는 패턴이다.

 

쓰는 시점은, 기존 State machine diagram을 개선하기 힘든 경우에 쓰이고

이때 상속 보다는 객체의 합성을 더 선호하라는 디자인 원칙이 이용된다.

상태 패턴 클래스 다이어그램

 

하나의 클래스에서 상태, 행동을 모두 정의하는 것이 아닌

인터페이스로 상태에 따른 행동을 정의해주고

다른 클래스에서는 상태를 객체화하여 상태가 행동 할 수 있도록 위임 해준다.

 

HandState 인터페이스

상태에 대한 행동을 정의해준다.

package com.patterns.StatePattern;

public interface HandState {
	public String getState();
}

Rock, Scissors, Paper 클래스

HandState를 직접 구현하는 클래스로 상태에 대한 행동을 구체화한다.

package com.patterns.StatePattern;

public class Rock implements HandState {
	@Override
	public String getState() {
		return "바위";
	}
}
package com.patterns.StatePattern;

public class Scissors implements HandState {
	@Override
	public String getState() {
		return "가위";
	}
}
package com.patterns.StatePattern;

public class Paper implements HandState {
	@Override
	public String getState() {
		return "보";
	}
}

 

Person 클래스

Person의 상태를 set, get해준다.

package com.patterns.StatePattern;

public class Person {
	private HandState handState;

	public Person() {
		handState = new Rock();
	}

	public void setState(HandState handState) {
		this.handState = handState;
	}

	public String getState() {
		return handState.getState();
	}
}

 

StateTest : 상태를 객체화 하여 행동을 위임하고 있는 것을 볼 수 있다.

package com.patterns.StatePattern;

public class StateTest {
	
	public static void main(String[] args) {
		Person person = new Person();
		System.out.println(person.getState());

		person.setState(new Scissors());
		System.out.println(person.getState());

		person.setState(new Paper());
		System.out.println(person.getState());
	}
}

 

바위
가위

 

정리

상태 패턴은 내부 상태 객체들이 캡슐화되어 외부에서 전혀 알 수 없게되고,

외부에서는 Context 객체의 각 Action들을 호출하기만 할 뿐이다.

이를 통해 Decoupling을 하여 코드의 수정 및 확장을 용이하게 한다.

 

참고원문: https://www.crocus.co.kr/1541?category=337544 

 

상태 패턴(State Pattern)

상태 패턴(State Pattern) 스테이트 패턴은 객체가 특정 상태에 따라 행위를 달리하는 상황에서 자신이 직접 상태를 체크하여 상태에 따라 행위를 호출하지 않고 상태를 객체화하여 상태가 행동을

www.crocus.co.kr

 

스트래티지 패턴(Strategy pattern)은 각각을 캡슐화하여 교환해서 사용할 수 있도록 만든다. 
스트래티지를 활용하면 알고리즘을 사용하는 클라이언트와는 독립적으로 알고리즘을 변경할 수 있다.
즉, 행위를 클래스로 캡슐화 하여 동적으로 행위를 바꾸어도 코드가 복잡해 지지 않도록 한다.
여기서의 패턴 이름과 같이 전략을 쉽게 바꾸도록 해주는 디자인 패턴이다.
ex) sorting 알고리즘 여러개가 있는데 이중 하나를 고르려고 할 때

이때, 스트래티지 패턴을 이용하면 condition statement가 현저히 줄어드는 장점이 있다.


디자인 원칙
코드에서 달라지는 부분을 찾아내고, 달라지지 않는 부분으로부터 분리시킨다. (달라지는 부분을 찾아서 나머지 코드에 영향을 주지 않도록 "캡술화")
상속보다는 구성을 활용한다.(상속 보다는 객체의 합성을 중요시 하자)
상속보다는 구성을 활용한다. 구현이 아닌 인터페이스에 맞춰서 프로그래밍 한다.
Strategy
  외부에서 동일한 방식으로 알고리즘을 호출 할 수 있도록 명시해둔 인터페이스
ConcreteStrategy
  스트래티지 인터페이스에서 명시해둔 코드를 실제로 구현한 클래스
Context
    스트래티지 패턴을 이용하는 역할을 수행하는 추상 클래스필요에 따라 동적으로 구체적인 전략을 바꿀 수 있도록 하기위해 setter 집약 관계 메서드를 제공한다.
집약 관계
- 참조값을 인자로 받아 필드를 세팅하는 경우- 전체 객체의 라이프타임과 부분 객체의 라이프 타임은 독립적이다.- 즉, 전체 객체가 메모리에서 사라진다 해도 부분 객체는 사라지지 않는다.

Stragety Pattern을 오리 게임을 만드는 것을 이용하여 한번 생각해보자.


Strategy, ConcreteStrategy를 통해 fly, quack에 대한 행동을 먼저 만들어보자

외부에서 명세 Strategy FlyBehavior를 통해 ContreateStartegy인 FlyWithWings, FlyNoWay 행동을 먼저 만들자

package com.patterns.StrategyPattern;

public interface FlyBehavior {
	public void fly();
}
package com.patterns.StrategyPattern;

public class FlyWithWings implements FlyBehavior {
	@Override
	public void fly() {
		System.out.println("날고 있습니다.");
	}
}
package com.patterns.StrategyPattern;

public class FlyNoWay implements FlyBehavior {

	@Override
	public void fly() {
		System.out.println("날지 못하고 있습니다.");
	}

}

마찬가지로 외부에서 명세 Strategy QuackBehavior를 통해 ContreateStartegy인 Quack, NoQuack 행동을 만들자

package com.patterns.StrategyPattern;

public interface  QuackBehavior {
	public void quack();
}
package com.patterns.StrategyPattern;

public class Quack implements QuackBehavior{

	@Override
	public void quack() {
		  System.out.println("꽥꽥");
	}

}
package com.patterns.StrategyPattern;

public class NoQuack  implements QuackBehavior {

	@Override
	public void quack() {
		System.out.println("소리를 못냅니다.");
	}

}
그리고 Duck 추상 클래스를 만들어준다.
package com.patterns.StrategyPattern;

public abstract class Duck {

	FlyBehavior 	flyBehavior;
	QuackBehavior 	quackBehavior;

	public void swim() {
		System.out.println("물에 떠있습니다.");
	}

	public abstract void display();

	public void setFlyBehavior(FlyBehavior flyBehavior) {
		this.flyBehavior = flyBehavior;
	}

	public void getFlyBehavior() {
		flyBehavior.fly();
	}

	public void setQuackBehavior(QuackBehavior quackBehavior) {
		this.quackBehavior = quackBehavior;
	}

	public void getQuackBehavior() {
		quackBehavior.quack();
	}
}​

실제 오리객체인 청둥오리객체 생성

package com.patterns.StrategyPattern;

public class MallardDuck extends Duck {

	public MallardDuck() {
		flyBehavior = new FlyWithWings();
		quackBehavior = new Quack();
	}

	@Override
	public void display() {
		System.out.println("청둥오리 입니다.");
	}

}

 

개발내용 테스트

package com.patterns.StrategyPattern;

public class DuckGame {
	public static void main(String[] args) {
		Duck mallard = new MallardDuck();
		mallard.getQuackBehavior();
		mallard.getFlyBehavior();
		System.out.println();
		mallard.setFlyBehavior(new FlyNoWay());
		mallard.getQuackBehavior();
		mallard.getFlyBehavior();
		System.out.println();
		mallard.setQuackBehavior(new NoQuack());
		mallard.getQuackBehavior();
		mallard.getFlyBehavior();
	}
}

 마지막으로 실제 오리 게임에서

오리 객체를 생성해주면 오리는 fly, quack에 대해 기본 상태를 가지게 되고
지금부터는 코드의 복잡함 없이 각 클래스에서 필요한 메서드만 호출하면 되고
FlyBehavior, QuackBehavior쪽에서는 그에 맞는 행동만 정의하고 구현해주면 된다.

참고 원문: https://www.crocus.co.kr/1526?category=337544 

 

모든 클래스간의 복잡한 로직(상호작용)을 캡슐화하여 하나의 클래스에 위임하여 처리하는 패턴이다.

즉, M:N의 관계에서 M:1의 관계로 복잡도를 떨어뜨려 유지 보수 및 재사용의 확장성에 유리한 패턴이다.

 

커뮤니케이션을 하고자 하는 객체가 있을 때 서로가 커뮤니케이션 하기 복잡한 경우 이를 해결해주고 서로 간 쉽게 해주며 커플링을 약화시켜주는 패턴이다.

 

객체들간 커뮤니케이션 정의가 잘 돼있으나 복잡할 때(종합이 필요할 때) 사용한다.

이와 비슷한 패턴은 파사드 패턴(Facade Pattern)과 옵저버 패턴(Observer Pattern)이 있다.

 

위의 그림에서 관제탑이 중재자가 되고 각 비행기가 서로 커뮤니케이션을 하기 위해서는

관제탑을 거쳐 M:N이 아닌 M:1의 관계로 커뮤니케이션을 진행하게 된다.

 

프로그램을 작성하다 보면 상호작용을 해야하는 경우 객체들 간의 결합도가 증가하고 유연성이 떨어지는 경우가 발생하게 된다.

이때 중재자 패턴에서는 서로 명령을 주고 받을 수 있는 형식이 있다고 했을 때 서로 명령을 주고 받는 부분을 중재하는 형식을 정의를 한다.

그리고, 원래 서로 명령을 주고 받았던 개체들은 중재자 개체를 알게 하고 중재자 개체는 이들 개체를 알게 한다.

 

이제 특정 개체가 명령을 내릴 필요가 있으면 중재자 개체에게 전달하기만 하면 되고, 

중재자는 해당 명령을 자신이 알고 있는 개체들 중에 적절한 개체에게 전달만 하면 된다.

 

이처럼 중재자 패턴을 사용하면 복잡한 상호작용을 하기 위한 복잡한 관계를 단순화시킬 수 있게 된다.

 

그리고 중재자가 notify한다는 의미로 옵저버 패턴과 매우 유사한데,

옵저버는 Subscriber이 받기만 하는데 Mediator은 서로 통신한다는 것에서 차이가 있다.

 

중재자 패턴 클래스 다이어그램

+Mediator은 Colleague(동료)가 Mediator에서 알려주는 것을 의미하고

ColleagueA도 마찬가지로 Mediator가 ColleagueA,B에게 알리는 것을 의미한다.

 

중재자 패턴 예제

ISource 인터페이스

package com.patterns.MediatorPattern;

public interface ISource {
	public void setMediator(Mediator mediator);
	public void eventOccured(String event);
}

 

TcpComm 클래스

  ISource를 구현하는 Concrete 부분.

  mediator을 설정하고 mediator에게 onEvent로 메시지를 전달한다.

package com.patterns.MediatorPattern;

public class TcpComm implements ISource {
	Mediator mediator;

	@Override
	public void setMediator(Mediator mediator) { // 중재자 설정
		this.mediator = mediator;
	}

	@Override
	public void eventOccured(String event) { // 이벤트의 전달
		mediator.onEvent("TCP comm", event);
	}
}

 

SystemSignal 클래스 : TcpComm 클래스와 같다.

package com.patterns.MediatorPattern;

public class SystemSignal implements ISource{
	  Mediator mediator;

	@Override
	public void setMediator(Mediator mediator) { // 중재자 설정
		this.mediator = mediator;
	}

	@Override
	public void eventOccured(String event) { // 이벤트의 전달
		mediator.onEvent("System", event);
	}
}

 

Mediator 클래스 : onEvent를 받으면 해당하는 메시지를 receiveEvent를 통해 보낸다.

package com.patterns.MediatorPattern;

import java.util.ArrayList;
import java.util.List;

public class Mediator {
	
	List<IDestination> list = new ArrayList<IDestination>();

	public void addDestination(IDestination destination) {
		list.add(destination);
	}

	public void onEvent(String from, String event) {
		for (IDestination each : list) { // 이벤트의 전송
			each.receiveEvent(from, event);
		}
	}
}

 

IDestionation 인터페이스

package com.patterns.MediatorPattern;

public interface IDestination {
	public void receiveEvent(String from, String event);
}

 

Display 클래스 : Idestianation 인터페이스를 구현하고 있다.

package com.patterns.MediatorPattern;

public class Display implements IDestination {
	@Override
	public void receiveEvent(String from, String event) {
		System.out.println("Display : from " + from + " event : " + event);
	}
}

 

Log 클래스 : Display 클래스와 같다.

package com.patterns.MediatorPattern;

public class Log implements IDestination{

	@Override
	public void receiveEvent(String from, String event) {
		 System.out.println("Log : from " + from + " event : " + event);
	}
}

 

MediatorTest 

각 생성자를 만들고 destination은 Display, Log로 해준후 이벤트를 전달하여 아래와 같은 결과값을 얻을 수 있다.

package com.patterns.MediatorPattern;

public class MediatorTest {
	public static void main(String[] args) {
		Mediator mediator = new Mediator();
		  
	    ISource tcp = new TcpComm();
	    tcp.setMediator(mediator);
	    ISource system = new SystemSignal();
	    system.setMediator(mediator);
	  
	    mediator.addDestination(new Display());
	    mediator.addDestination(new Log());
	    tcp.eventOccured("connected");
	    tcp.eventOccured("disconnected");
	  
	    system.eventOccured("key input");
	    system.eventOccured("mouse input");
	}
}
Display : from TCP comm event : connected
Log : from TCP comm event : connected
Display : from TCP comm event : disconnected
Log : from TCP comm event : disconnected
Display : from System event : key input
Log : from System event : key input
Display : from System event : mouse input
Log : from System event : mouse input

출처: https://www.crocus.co.kr/1542?category=337544 

 

중재자 패턴(Mediator Pattern)

중재자 패턴(Mediator Pattern) 모든 클래스간의 복잡한 로직(상호작용)을 캡슐화하여 하나의 클래스에 위임하여 처리하는 패턴이다. 즉, M:N의 관계에서 M:1의 관계로 복잡도를 떨어뜨려 유지 보수

www.crocus.co.kr

 

+ Recent posts