스트레티지 패턴은 기능을 부품화 하는 것을 말한다.


이 패턴을 사용하면 클라이언트와 무관하게 독립적으로 알고리즘을 변경할 수 있고(quickSortbubbleSort), 클라이언트는 독립적으로 원하는 알고리즘을 사용할 수 있다. 즉 이 패턴은 클라이언트에게 알고리즘이 사용하는 데이터나 그 구조를 숨겨주는 역할을 한다. strategy 패턴은 알고리즘을 사용하는 곳과, 알고리즘을 제공하는 곳을 분리시킨 구조로 알고리즘을 동적으로 교체할 수 있다.


스트레티지 패턴(Strategy Pattern)

알고리즘 군을 정의하고 각각을 캡슐화하여 교환해서 사용할 수 있도록 만든다.

스트래티지를 활용하면 알고리즘을 사용하는 클라이언트와는 독립적으로 알고리즘을 변경할 수 있다.

 

조금 말이 어려울 것입니다쉽게 말하면어떤 객체를 만들 때 객체가 가지는 기능들이 다양하게 존재할 것 니다이러한 기능들을 추상화 하여 언제든지 적용할수 있게 만드는 것 입니다즉 기능을 부품화 하는 것 입니다.

예를 들어 포니와 그랜저 자동차가 있습니다포니에 들어가는 기어 연결부분과 그랜저에 들어가는 연결부분이 동일하다고(추상화하면저급기어중급기어고급기어를 만들어 두고 상황에 따라서 적당한 기어를 적용할수 있을것 입니다즉 포니에는 저급기어를그랜저에는 고급기어를 적용하는것 입니다.

이렇게 기능을 부품화하여 구조를 만드는 것을 스트레티지라고 생각하시면 됩니다.

 

개인적으로 실무에서 가장 많이 사용했고알아두면 아주 유용하게 사용할 수 있는 패턴 입니다노파심에 말씀 드리면한번에 모든 것을 알 수는 없습니다그리고 안다고 하여도 실제 본인의 개발 소스에 적용하시란 쉽지 않습니다꾸준히 살펴보고고민해 보는 자세가 중요 합니다.

 

이번에 살펴 볼 예제는 로봇을 프로그램으로 만들어 보는 것 입니다.

시나리오

1.로봇 모양은 팔다리머리몸통으로 이루어져 있습니다.
2.모든 로봇은 기본적으로 걷고달릴 수 있어야 합니다.
3.Super로봇은 날수 있고미사일을 쏠 수 있으며레이저 검을 가지고 있습니다.
4.Standard 로봇은 날수는 없지만 미사일을 쏠 수 있습니다그리고 레이저 검은 없지만목검은 가지고 있습니다.
5.Low 로봇은 날수도 없고미사일을 쏠 수도 없습니다그리고 레이저검 또는 목검도 없습니다.

 

위 3가지 형태의 로봇을 만들어 보도록 하고추후 다른 로봇을 만들어야 할 경우를 생각하여 유연한 프로그램을 만들어 보도록 합니다.  

​1. 상속, 추상클래스를 하지 않고 일반적으로 class를 만들고 메소드를 만들면 코드에 양이 많아지고 똑같은 기능에 코드를 반복적으로 코딩을 해야하는 불편함이 있다. 나중에 다른 사용자가 기능을 추가하기 불편하다.

​exntends = 상속

2. 위에 class (super, standard, Low) 에서 공통적인 기능들은 따로 Robot.class를 만들어서 상속 기능을 통해 코드를 줄여서 효율적으로 만들수 있다.

상속 - 공통적인 기능 : 걷고, 달린다, 로봇 모양은 팔, 다리, 머리, 몸통 이다.

abstract = 추상클래스

3. 새로운 사용자가 로봇을 만들려고할때 ​

​메소드를 추상화 시켜놓고 무조건 구현하게 만든다

( 날다, 미사일, 레이저검(목검) 기능​

​  public abstract void actionFly();
  public abstract void actionMisail(); 
  public abstract void actionKnife();  )


참고: https://www.youtube.com/watch?v=YqqkElW8PR0&list=PLieE0qnqO2kTyzAlsvxzoulHVISvO8zA9&index=22

  http://hwan1402.tistory.com/9




'프로그래밍 > JAVA' 카테고리의 다른 글

자바빈(DTO), DAO  (0) 2018.07.28
JAVA 관련 사이트 기술 커리큘럼  (0) 2018.07.25
Java for-each 쉽게 이해하기  (0) 2018.07.19
JAVA 싱글턴 패턴  (0) 2018.07.19
자바 interface(인터페이스)  (0) 2018.07.18

ava for-each에 대해서 쉽게 이해하기 



 



 for-each


: jdk 1.5 이후에 추가 된 문법이다. 따로 키워드가 있는 것은 아니다. 기존의 for문을 그대로 사용한다. 



코드의 가독성이 좋아지고, 반복자나 변수를 사용하지 않아 오류 가능성을 없앤다. 



/**
*
* @author hoTire
*
*/

for (int i = 0; i < 10; i++) {
System.out.println(list.get(i));
}
    
for (Integer integer : list) {
System.out.println(integer);
}


아래가 for-each 방법이다. 


for-each를 구현하기 위해선 


public interface Iterable<T> {
/**
* Returns an iterator over elements of type {@code T}.
*
* @return an Iterator.
*/
Iterator<T> iterator();
}


Iterable 인터페이스를 implements 구현하면 된다. 







성능 차이




@Benchmark
    public void testFor() {
        int[] classicFor = new int[200000000];
        int size = classicFor.length;
        int a;
        for (int i = 0; i< size; i++) {
            a = classicFor[i];
        }
    }
    
    @Benchmark
    public void testFor2() {
        int[] classicFor = new int[200000000];
        int a;
        for (int i = 0; i< classicFor.length; i++) {
            a = classicFor[i];
        }
    }
    
    @Benchmark
    public void testForEach() {
        int[] forEach = new int[200000000];
        int a;
        for (int n : forEach) {
            a = n;
        }
    }

Benchmark Mode Cnt Score Error Units
MyBenchmark.testFor avgt 5 390.766 ± 42.219 ms/op
MyBenchmark.testFor2 avgt 5 418.466 ± 219.746 ms/op
MyBenchmark.testForEach avgt 5 386.739 ± 47.636 ms/op

 


for문 안에 size나 length를 알아내는 코드가 있다면 느리다. 

계속해서 lenght, size를 알아내는 비용이 발생한다. 


크기가 크면 클수록 for-each가 빠르다. 

JIT컴파일러가 최적화를 하기 때문이다. 







이렇게 좋은 for-each를 사용하지 못할 때가 있다.


1. 필터링(filtering) : 순회하는 도중 특정한 원소를 삭제해야할 경우 


2. 변환(transforming) : 순회하는 도중 원소의 값을 수정해야할 경우


3. 병렬순회(parallel iteration) : 병렬적으로 순회할 경우 



'프로그래밍 > JAVA' 카테고리의 다른 글

JAVA 관련 사이트 기술 커리큘럼  (0) 2018.07.25
스트레티지 패턴  (0) 2018.07.23
JAVA 싱글턴 패턴  (0) 2018.07.19
자바 interface(인터페이스)  (0) 2018.07.18
JAVA 상속(Override) 재정의, super  (0) 2018.07.17
싱글턴 패턴

소프트웨어 디자인 패턴에서 싱글턴 패턴(Singleton pattern)을 따르는 클래스는, 생성자가 여러 차례 호출되더라도 실제로 생성되는 객체는 하나이고 최초 생성 이후에 호출된 생성자는 최초의 생성자가 생성한 객체를 리턴한다. 이와 같은 디자인 유형을 싱글턴 패턴이라고 한다. 주로 공통된 객체를 여러개 생성해서 사용하는 DBCP(DataBase Connection Pool)와 같은 상황에서 많이 사용된다.


예제는 아래와 같다.



싱글턴 패턴은 데이터타입을 자신의 클래스로 한다. 객체를 생성하지 못해서(객체 접근 안되도록 private로 막음) 객체를 생성하기 전 클래스 생성 단계(static)으로 자기 자신을 생성해서 리턴해 주어야한다. 즉 생성자가 여러 차례 호출되더라도 실제로 생성되는 객체는 하나가 된다(하나의 객체를 전역적으로 공유해서 쓴다)

'프로그래밍 > JAVA' 카테고리의 다른 글

스트레티지 패턴  (0) 2018.07.23
Java for-each 쉽게 이해하기  (0) 2018.07.19
자바 interface(인터페이스)  (0) 2018.07.18
JAVA 상속(Override) 재정의, super  (0) 2018.07.17
자바 Static 변수  (0) 2018.07.16

자바 Interface 문법


0.인테페이스는 작업 명세서(작업 지시서) 라고 불린다. 

1.인터페이스는 상수와 추상메소드만 존재 한다.

2.자바는 다중 상속(extends)는 불가하지만 인터페이스는 여러개의 클래스를 imprement(다중 구현) 가능하다.

3.인터페이스 안의 추상 메소드를 각각 재정의 해서 사용해야 한다.


객체 타입으로 인터페이스로 사용 할 수있다. ==> 배열의 타입으로 사용할 수 있다.

  


  3개의 데이터타입을 하나로 묶어주는 Toy


 PoohToyClass를 다양한 형식의 타입으로 나타낼 수 있다. (다형성)



인터페이스와 추상클래스의 공통점과 차이점


'프로그래밍 > JAVA' 카테고리의 다른 글

Java for-each 쉽게 이해하기  (0) 2018.07.19
JAVA 싱글턴 패턴  (0) 2018.07.19
JAVA 상속(Override) 재정의, super  (0) 2018.07.17
자바 Static 변수  (0) 2018.07.16
리펙토링(Refactoring)의 원칙과 정의  (0) 2018.07.16

JAVA 상속

 ->재정의 하고자 하는 자식 클래스에서 메소드 위에 @Override 적어주면 된다.



 ->재정의한 자식 클래스에서 재정의 한 메소드에서 부모 클래스의 메소드를 사용하고 싶으면 super.메소드() 를 사용한다.


->MainClass 에서 클래스를 자식 클래스를 생성하는데 오른쪽에 ParentClass의 생성자 부터 작동하는 것을 볼 수 있다. 즉, 부모클래스가 먼저 생성되고 자식 클래스가 생성된다는 것이다.

'프로그래밍 > JAVA' 카테고리의 다른 글

JAVA 싱글턴 패턴  (0) 2018.07.19
자바 interface(인터페이스)  (0) 2018.07.18
자바 Static 변수  (0) 2018.07.16
리펙토링(Refactoring)의 원칙과 정의  (0) 2018.07.16
[JAVA 자바] 백준 1152번 단어의 개수  (1) 2018.07.08

 static 변수는 팀원들과의 '공유'라고 생각할 수 있다.

 static은 클래수 변수이기 때문에 변수를 static으로 선언하면 다른 패키지에서 객체를 생성하지 않고도 바로 변수에 접근 할 수 있다.



MONEY 를 static 변수로 선언한다.



import를 위와 같이 해주고 바로 MONEY 변수에 접근한다.



이제 메인 클래스에서 FirstChild 클래스에 있는 메소드를 불러와 사용한다.


static 의 장점과 단점



리펙토링 원칙

코드의 양을 줄어야 합니다. 한 메쏘드에 5줄이 넘어가면 의심해 봐야 합니다.

모든 것을 다 할 수 있는 슈퍼 메쏘드/객체는 없어야 합니다. 한가지 기능을 하도록 단순하게 해야 합니다.

작고 응집력있게 만들어야 합니다. - SOLID 중에 SRP

중복제거! - DRY Don't repeat yourself!!

종속성 제거 - 종속성을 줄이기 위해 노력해야하는 것이 아니라 없애야 합니다.

자체 문서 작성 코드 - 주석이 필요 없이 코드를 보고 이해할 수 있도록 해야 합니다.

코드는 보는 즉시 이해할 수 있어야 합니다. - 코드의 양을 줄이는 것을 의미하는 것이 아니라 명확하게 표현되어야 합니다. 

원시적인 강박관념을 피하세요. - 높은 추상화 생성에 집중해야 합니다.

자주 확인하고 작은 단계로 진행하세요. - 모든 커밋은 한 개의 변경사항만 가지고 있어야 합니다.- 1 commit 1 change

피드백 주기를 단축시키세요.

다른 개발자는 루프에 보관하세요.

커다란 고통스러운 머지는 피하세요.

코드를 한 종류의 추상화 수준으로 맞추세요. - 모든 메소드는 한가지만 해야 하고, 각 메서드는 각각 한 가지 작업을 하는 다른 메서드에 위임해야 합니다.



리펙터링 하지 말아야 할 때.

다른 코드를 변경하는 동안 리펙터링하지 마세요. 리펙토링을 기록하고 버그 수정이나 기능 변경이 커밋되면 완료하세요. 절대로 다른 코드가 변경되는 동안에 리펙토링을 수행하지 마세요. 

나쁜 냄새를 맡으면 메모를 남깁니다.

하던 일을 마무리 짓습니다.

커밋합니다.

리펙터링 시작

혼자서 리펙토링하지 마세요. 문제에 대해 눈 2개를 같이 가지고 진행해야 합니다. 페어 프로그래밍은 리펙토링하는 동안에 필수적입니다. 짝은 코드를 이해하기 쉽게 만들고, 좋은 이름을 가지고 기존 로직을 망치지 않는데 도움을 줍니다.



리펙토링 해야 할 

버그 수정이나 기능 변경 전이나 후에 리팩토링 할 수 있습니다.

변경으로 인해 코드 디자인이 개선된다고 생각한다면

변경으로 인해 다른 개발자를위한 코드의 가독성이 향상된다고 생각한다면




Refactoring(리펙토링)의 정의 



String 변수에 입력 받은 값을 charAt()을 사용하기 위해 String으로 다시 변환하려면 String.valueOf(char형)을 사용해야

한다는 것을 알았다. 

다음은 코드이다.

다음은 꼼수(?) 코드이다.

소수점 자리를 표현 하는 방법에 대해서 포스팅 하려한다.



출처 : https://linediffuser.blog.me/220840699390

성능 향상 보조 스트림이란?

 : 프로그램의 성능은 입출력이 가장 늦은 장치를 따라가게 되는데요.

예를 들어서 CPU 랑 메모리의 성능이 아무리 좋다고 해도 하드 디스크의 입출력 늦다면

프로그램의 실행 성능은 하드 디스크의 처리 속도에 따라 맞춰갑니다.

네트워크도 느린 네트워크 환경이라면 컴퓨터의 성능이 좋더라도 메신저 또는 게임의 속도가 느려집니다.

이에 대한 완전한 해결책은 없는데요, 프로그램이 입출력 소스와 직접 작업하는 대신에

중간에 메모리 버퍼와 작업함으로써 실행 성능을 어느 정도 향상 시킬 수는 있습니다.

BufferedInputStream 과 BufferedOutputStream은 바이트 기반의 성능 향상 보조 스트림이고,

BufferedReader 와 BufferedWriter는 문자 기반 성능 향상 스트림입니다.


BufferedInputStream과 BufferedReader :

 BufferedInputStream은 바이트 입력 스트림에 연결되어서 버퍼를 제공해주는 보조 스트림입니다.

BufferedReader는 문자 입력 스트림에 연결되어서 버퍼를 제공해주는 스트림입니다.


위의 스트림은 둘 다 입력 소스로부터 자신의 내부 버퍼 크기만큼 데이터를 미리 읽고 버퍼에 저장합니다.

생성자 매개값으로 준 입력 스트림과 연결되어 8918 내부 버퍼 사이즈를 갖습니다.

BufferedInputStream bis = new BufferedInputStream(바이트 입력 스트림); //  최대 8912 바이트

BufferedReader br = new BufferedReader(문자 입력 스트림); // 최대 8912 문자


스트림이 데이터를 읽어들이는 방법은 InputStream / Reader 와 갖습니다.


예제)

import java.io.BufferedInputStream;

import java.io.FileInputStream;


public class Example {

 public static void main(String[] args) throws Exception {

  long start = 0;

  long end = 0;

  

  FileInputStream fis1 = new FileInputStream("파일 경로/image.jpg");

  start = System.currentTimeMillis();

  while(fis1.read() != -1) {}

  end = System.currentTimeMillis();

  System.out.println("사용하지 않았을 때 걸린 시간: " + (end-start) + "ms");

  fis1.close();

  

  FileInputStream fis2 = new FileInputStream("C:/apache-tomcat-8.0.20/webapps/thisisjava/src/forest.jpg");

  BufferedInputStream bis = new BufferedInputStream(fis2);

  start = System.currentTimeMillis();

  while(bis.read() != -1) {}

  end = System.currentTimeMillis();

  System.out.println("사용했을 때 걸린 시간: " + (end-start) + "ms");

  bis.close();

  fis2.close();

 }

}

예제를 실행시켜보면 시간 차이가 꽤 많이 나는 것을 확인할 수 있습니다.


예제2)

예제2) BufferedReader / readLine()메서드를 추가적으로 가지고 있음. 

import java.io.BufferedReader;

import java.io.InputStream;

import java.io.InputStreamReader;

import java.io.Reader;


public class Example2 {

 public static void main(String[] args) throws Exception {  

  InputStream inputStream = System.in;

  Reader reader = new InputStreamReader(inputStream); 

  BufferedReader bufferedReader = new BufferedReader(reader);

  

  System.out.print("입력: ");

  String lineString = bufferedReader.readLine();

  

  System.out.println("출력: " + lineString); 

 }

 

}



BufferedOutPutStream :

바이트 출력 스트림에 연결되어서 버퍼를 제공해 주는 보조 스트림입니다.

BufferedWriter :

문자 출력 스트림에 연결되어 버퍼를 제공해주는 스트림입니다.


위 두 스트림은 프로그램에서 전송한 데이터를 내부에 두었다가 버퍼가 꽉 차면 버퍼의 모든

데이터들을 한번에 보냅니다.

BufferedOutputStream bufferedOutputStream

 = new BufferedOutputStream(바이트출력스트림); // 최대 8912바이트

BufferedWriter bufferedWriter

 = new BufferedWriter(문자출력스트림); // 최대 8912 문자


출력 방법은 OutputStream/ Writer 과 동일합니다.

예제)

성능차이를 보여주는 예제

import java.io.BufferedInputStream;

import java.io.BufferedOutputStream;

import java.io.FileInputStream;

import java.io.FileOutputStream;


public class Example {

 public static void main(String[] args) throws Exception {

  FileInputStream fileInputStream = null;

  FileOutputStream fileOutputStream = null;

  BufferedInputStream bufferedInputStream = null;

  BufferedOutputStream bufferedOutputStream = null;

  

  int data = -1;

  long start = 0;

  long end = 0;

  

  fileInputStream = new FileInputStream("파일 경로/image.jpg");

  bufferedInputStream = new BufferedInputStream(fis);

  fileOutputStream = new FileOutputStream("C:/Temp/forest.jpg");    

  start = System.currentTimeMillis();

  while((data = bufferedInputStream.read()) != -1) {

   fileOutputStream.write(data);

  }

  fileOutputStream.flush();

  end = System.currentTimeMillis();

  fileOutputStream.close();

  bufferedInputStream.close();

  fileInputStream.close();

  System.out.println("사용하지 않았을 때 걸린 시간: " + (end-start) + "ms");

  

  fileInputStream = new FileInputStream("C:/apache-tomcat-8.0.20/webapps/thisisjava/src/forest.jpg");

  bufferedInputStream = new BufferedInputStream(fis);

  fileOutputStream = new FileOutputStream("C:/Temp/forest.jpg");  

  BufferedOutputStream = new BufferedOutputStream(fileOutputStream);

  start = System.currentTimeMillis(); // 시작시간

  while((data = bufferedInputStream.read()) != -1) {

   BufferedOutputStream.write(data);

  }

  BufferedOutputStream.flush();

  end = System.currentTimeMillis(); // 종료시간

  BufferedOutputStream.close();

  fileOutputStream.close();

  bufferedInputStream.close(); 

  fileInputStream.close();

  System.out.println("사용했을 때 걸린 시간: " + (end-start) + "ms");

 }

}



출처: http://altongmon.tistory.com/274 [IOS를 Java]

+ Recent posts