Jekyll Liquid 템플릿에서 배열을 만들고 원소를 추가하는 방법을 알아보자


환경

  • Linux
  • Jekyll


Jekyll 배열 생성 및 추가

생성

  • split 필터 사용
  • 문자열을 ,로 구분해 배열로 만드는 필터로 문자열이 없기 때문에 빈 배열을 만듭니다.
{% assign ARRAY_NAME = "" | split: ',' %}


추가

  • push 사용해 배열에 추가하고 추가한 배열을 변수에 다시 할당합니다.
  • push를 하면 현재 배열에 추가된채로 저장되는게 아니기 때문에 새로 할당해야 합니다.
{% assign ARRAY_NAME = ARRAY_NAME | push: ELEMENT %}


예제

  • 아래는 블로그에서 특정 collections를 가져와서 새로 배열을 만드는 예시
  • opensource-contributions : 배열
  • post : 원소
{% assign opensource-contributions = "" | split: ',' %}
{% for post in site.opensource-contributions %}
  {% if post.post_id != page.post_id %}
     {% assign opensource-contributions = opensource-contributions | push: post %}
  {% endif %}
{% endfor %}


참고자료

Summarize making array and adding element in Jekyll Liquid


Environment and Prerequisite

  • Linux
  • Jekyll


Jekyll Array Create and Add

Create

  • Use split filter
  • It is used to convert comma-separated items from a string to an array but there is no string so it makes empty array.
{% assign ARRAY_NAME = "" | split: ',' %}


Add

  • Use push to add element to array and reassign to original variable.
  • push does not actually add to current array so it needs to be reassigned.
{% assign ARRAY_NAME = ARRAY_NAME | push: ELEMENT %}


Example

  • Example of making new array from specific collections in my blog.
  • opensource-contributions : Array
  • post : Element
{% assign opensource-contributions = "" | split: ',' %}
{% for post in site.opensource-contributions %}
  {% if post.post_id != page.post_id %}
     {% assign opensource-contributions = opensource-contributions | push: post %}
  {% endif %}
{% endfor %}


Reference

싱글턴 패턴(Singleton Pattern)에 대해서 알아보자

해당 내용은 책 ‘JAVA 객체지향 디자인 패턴’을 참고해서 작성하였습니다.


환경

  • Java


싱글턴 패턴(Singleton Pattern)이란?

싱글턴 패턴(Singleton Pattern)

  • 싱글턴 패턴(Singleton Pattern) : 클래스가 오직 하나의 인스턴스만을 유지하도록 하는 패턴이며 한번 만들어지면 getInstance()와 같은 함수 또는 메소드 호출을 통해서 객체에 접근한다.
  • 이미지 출처 : https://en.wikipedia.org/wiki/Singleton_pattern


구현

일반적인 구현

  • 프린터를 만든다고 가정해보자.
  • 프린터는 하나의 객체만 만들어져야한다고 생각하면 싱글턴 패턴으로 아래처럼 구현이 가능하다.

Printer

public class Printer {
    private static Printer printer = null;
    private Printer() {}

    public static Printer getPrinter(){
        if(printer == null){
            printer = new Printer();
        }
        return printer;
    }

    public void print(String str){
        System.out.println(str);
    }
}

User

public class User {
    private String name;

    public User(String name){
        this.name = name;
    }

    public void print() {
        Printer.getPrinter().print(this.name + " " + "print using" + " " + Printer.getPrinter().toString());
    }
}

Main

public class Main {
    public static void main(String[] args) {
        final int CNT = 6;
        User[] user = new User[CNT];
        for (int i = 0; i < CNT; i++){
            user[i] = new User(i + "-user");
            user[i].print();
        }
    }
}

Result

0-user print using com.company.Printer@60e53b93
1-user print using com.company.Printer@60e53b93
2-user print using com.company.Printer@60e53b93
3-user print using com.company.Printer@60e53b93
4-user print using com.company.Printer@60e53b93
5-user print using com.company.Printer@60e53b93
  • 위 클래스에서는 객체가 있는지 확인하고 있으면 반환하고 없다면 만들어서 반환해주는 구조
  • static를 사용해서 printer 변수와 getPrinter() 메소드를 만들었으며 이렇게 했기에 이 둘은 클래스 자체에 속하며 인스턴스 없이도 호출이 및 사용이 가능하다.
  • 이러한 방식을 통해 단 하나의 객체만 만들어서 사용할 수 있다.
  • 결과를 보면 모두 동일한 프린터를 사용했다.


문제점

  • 만약 여러 스레드가 이 객체가 생성되기 전에 동시에 접근한다면 경합 조건(Race Condition)이 발생할 수 있다.
  • 객체를 만들기전에 스레드가 동시에 접근하면 객체를 여러개 만들게되는 상황에 직면할 수 있다.
  • 하단의 예제는 Thread.sleep(1)을 통해 객체를 여러개 생성하는 경우를 만들어본 결과이다.

Printer

public class Printer {
    private static Printer printer = null;
    private Printer() {}

    public static Printer getPrinter(){
        if(printer == null){
            try{
                Thread.sleep(1);
            }
            catch (InterruptedException e) { }
            printer = new Printer();
        }
        return printer;
    }

    public void print(String str){
        System.out.println(str);
    }
}

UserThread

public class UserThread extends Thread {
    public UserThread(String name){
        super(name);
    }

    public void run(){
        Printer.getPrinter().print(Thread.currentThread().getName()
                + " " + "print using" +
                " " + Printer.getPrinter().toString());
    }
}

Main

public class Main {
    public static void main(String[] args) {
        final int CNT = 6;
        UserThread[] user = new UserThread[CNT];
        for (int i = 0; i < CNT; i++){
            user[i] = new UserThread(i + "-user");
            user[i].start();
        }
    }
}

Result

0-user print using com.company.Printer@4f90c612
5-user print using com.company.Printer@17a724
4-user print using com.company.Printer@d156cd4
3-user print using com.company.Printer@4f90c612
1-user print using com.company.Printer@6fa76e7
2-user print using com.company.Printer@4f90c612
  • 이처럼 스레드가 동시에 접근하게 되면 하나의 객체만을 만들어서 사용하려는 싱글턴 패턴의 구현에 실패하게 된다.


문제 해결 구현법 - 정적 변수에 바로 초기화

  • 클래스에서 변수를 생성함과 동시에 객체를 만든다.
  • private static Printer printer = new Printer();처럼 생성과 동시에 객체를 만들어준다.

Printer

public class Printer {
    private static Printer printer = new Printer();
    private Printer() {}

    public static Printer getPrinter(){
        return printer;
    }

    public void print(String str){
        System.out.println(str);
    }
}

UserThread

public class UserThread extends Thread {
    public UserThread(String name){
        super(name);
    }

    public void run(){
        Printer.getPrinter().print(Thread.currentThread().getName()
                + " " + "print using" +
                " " + Printer.getPrinter().toString());
    }
}

Main

public class Main {
    public static void main(String[] args) {
        final int CNT = 6;
        UserThread[] user = new UserThread[CNT];
        for (int i = 0; i < CNT; i++){
            user[i] = new UserThread(i + "-user");
            user[i].start();
        }
    }
}

Result

3-user print using com.company.Printer@651f2f3d
1-user print using com.company.Printer@651f2f3d
2-user print using com.company.Printer@651f2f3d
0-user print using com.company.Printer@651f2f3d
4-user print using com.company.Printer@651f2f3d
5-user print using com.company.Printer@651f2f3d
  • 모두 똑같이 하나의 객체에 접근했음을 알 수 있다.


문제 해결 구현법 - 인스턴스 생성 메소드 동기화

  • synchronized를 이용해 여러 스레드가 동시에 메소드에 접근하는걸 방지한다.

Printer

public class Printer {
    private static Printer printer = null;
    private Printer() {}

    public synchronized static Printer getPrinter(){
        if(printer == null){
            printer = new Printer();
        }
        return printer;
    }

    public void print(String str){
        System.out.println(str);
    }
}

UserThread

public class UserThread extends Thread {
    public UserThread(String name){
        super(name);
    }

    public void run(){
        Printer.getPrinter().print(Thread.currentThread().getName()
                + " " + "print using" +
                " " + Printer.getPrinter().toString());
    }
}

Main

public class Main {
    public static void main(String[] args) {
        final int CNT = 6;
        UserThread[] user = new UserThread[CNT];
        for (int i = 0; i < CNT; i++){
            user[i] = new UserThread(i + "-user");
            user[i].start();
        }
    }
}

Result

3-user print using com.company.Printer@8f62e66
4-user print using com.company.Printer@8f62e66
0-user print using com.company.Printer@8f62e66
1-user print using com.company.Printer@8f62e66
2-user print using com.company.Printer@8f62e66
5-user print using com.company.Printer@8f62e66
  • 모두 똑같이 하나의 객체에 접근했음을 알 수 있다.


문제점

  • 스레드를 2가지 방식으로 해결했어도 아래처럼 클래스에서 상태를 유지해야하는 변수가 있다면 이야기가 달라진다.
  • cnt의 값이 일관적이지 않다.

Printer

public class Printer {
    private static Printer printer = null;
    private int cnt = 0;
    private Printer() {}

    public synchronized static Printer getPrinter(){
        if(printer == null){
            printer = new Printer();
        }
        return printer;
    }

    public void print(String str){
        cnt++;
        System.out.println(str + " " + "cnt : " + cnt);
    }
}

UserThread

public class UserThread extends Thread {
    public UserThread(String name){
        super(name);
    }

    public void run(){
        Printer.getPrinter().print(Thread.currentThread().getName()
                + " " + "print using" +
                " " + Printer.getPrinter().toString());
    }
}

Main

public class Main {
    public static void main(String[] args) {
        final int CNT = 6;
        UserThread[] user = new UserThread[CNT];
        for (int i = 0; i < CNT; i++){
            user[i] = new UserThread(i + "-user");
            user[i].start();
        }
    }
}

Result

2-user print using com.company.Printer@6fa76e7 cnt : 2
1-user print using com.company.Printer@6fa76e7 cnt : 4
3-user print using com.company.Printer@6fa76e7 cnt : 3
0-user print using com.company.Printer@6fa76e7 cnt : 2
4-user print using com.company.Printer@6fa76e7 cnt : 5
5-user print using com.company.Printer@6fa76e7 cnt : 6


문제 해결 구현법 - 메소드 안에 동기화 부분 추가

  • synchronized()를 이용해 스레드의 동시 접근을 막을 부분을 감싸주면 된다.

Printer

public class Printer {
    private static Printer printer = null;
    private int cnt = 0;
    private Printer() {}

    public synchronized static Printer getPrinter(){
        if(printer == null){
            printer = new Printer();
        }
        return printer;
    }

    public void print(String str){
        synchronized (this){
            cnt++;
            System.out.println(str + " " + "cnt : " + cnt);
        }
    }
}

UserThread

public class UserThread extends Thread {
    public UserThread(String name){
        super(name);
    }

    public void run(){
        Printer.getPrinter().print(Thread.currentThread().getName()
                + " " + "print using" +
                " " + Printer.getPrinter().toString());
    }
}

Main

public class Main {
    public static void main(String[] args) {
        final int CNT = 6;
        UserThread[] user = new UserThread[CNT];
        for (int i = 0; i < CNT; i++){
            user[i] = new UserThread(i + "-user");
            user[i].start();
        }
    }
}

Result

0-user print using com.company.Printer@4f90c612 cnt : 1
5-user print using com.company.Printer@4f90c612 cnt : 2
4-user print using com.company.Printer@4f90c612 cnt : 3
2-user print using com.company.Printer@4f90c612 cnt : 4
1-user print using com.company.Printer@4f90c612 cnt : 5
3-user print using com.company.Printer@4f90c612 cnt : 6
  • 이제 cnt 값도 정상적으로 나오며 객체도 하나만 생성된다.


싱글턴 패턴과 정적 클래스의 비교


참고자료

Post about Singleton Pattern.

This post is based on book ‘JAVA 객체지향 디자인 패턴’.


Environment and Prerequisite

  • Java


What is Singleton Pattern?

Singleton Pattern

  • Singleton Pattern : Software design pattern that restricts the instantiation of a class to one single instance. It access to its instance by using like getInstance() method or function.
  • Image Source : https://en.wikipedia.org/wiki/Singleton_pattern


Implementation

Usual Case Implementation

  • Let’s imagine we make printer.
  • Consider printer should be only one instance, so then we can use singleton pattern like below.

Printer

public class Printer {
    private static Printer printer = null;
    private Printer() {}

    public static Printer getPrinter(){
        if(printer == null){
            printer = new Printer();
        }
        return printer;
    }

    public void print(String str){
        System.out.println(str);
    }
}

User

public class User {
    private String name;

    public User(String name){
        this.name = name;
    }

    public void print() {
        Printer.getPrinter().print(this.name + " " + "print using" + " " + Printer.getPrinter().toString());
    }
}

Main

public class Main {
    public static void main(String[] args) {
        final int CNT = 6;
        User[] user = new User[CNT];
        for (int i = 0; i < CNT; i++){
            user[i] = new User(i + "-user");
            user[i].print();
        }
    }
}

Result

0-user print using com.company.Printer@60e53b93
1-user print using com.company.Printer@60e53b93
2-user print using com.company.Printer@60e53b93
3-user print using com.company.Printer@60e53b93
4-user print using com.company.Printer@60e53b93
5-user print using com.company.Printer@60e53b93
  • Above class makes instance if there is no instance. If instance exists, then return the instance.
  • Use static to make printer variable and getPrinter() method. printer variable and getPrinter() method are belong to class so it can be used without instance.
  • By using like this, we can make only one instance.
  • Result shows that there is only one printer instance.


Problem

  • There can be a race condition if multi threads access to this instance simultaneously before instantiation.
  • There can be multiple instances if threads access simultaneously before making instance.
  • Below example uses Thread.sleep(1) to make multiple instances.

Printer

public class Printer {
    private static Printer printer = null;
    private Printer() {}

    public static Printer getPrinter(){
        if(printer == null){
            try{
                Thread.sleep(1);
            }
            catch (InterruptedException e) { }
            printer = new Printer();
        }
        return printer;
    }

    public void print(String str){
        System.out.println(str);
    }
}

UserThread

public class UserThread extends Thread {
    public UserThread(String name){
        super(name);
    }

    public void run(){
        Printer.getPrinter().print(Thread.currentThread().getName()
                + " " + "print using" +
                " " + Printer.getPrinter().toString());
    }
}

Main

public class Main {
    public static void main(String[] args) {
        final int CNT = 6;
        UserThread[] user = new UserThread[CNT];
        for (int i = 0; i < CNT; i++){
            user[i] = new UserThread(i + "-user");
            user[i].start();
        }
    }
}

Result

0-user print using com.company.Printer@4f90c612
5-user print using com.company.Printer@17a724
4-user print using com.company.Printer@d156cd4
3-user print using com.company.Printer@4f90c612
1-user print using com.company.Printer@6fa76e7
2-user print using com.company.Printer@4f90c612
  • Like this, if threads access simultaneously then it fails to make one instance in singleton pattern.


Solution - Instantiate when initialize class

  • Make instance immediately when make variable in class.
  • Like private static Printer printer = new Printer();, make instance immediately.

Printer

public class Printer {
    private static Printer printer = new Printer();
    private Printer() {}

    public static Printer getPrinter(){
        return printer;
    }

    public void print(String str){
        System.out.println(str);
    }
}

UserThread

public class UserThread extends Thread {
    public UserThread(String name){
        super(name);
    }

    public void run(){
        Printer.getPrinter().print(Thread.currentThread().getName()
                + " " + "print using" +
                " " + Printer.getPrinter().toString());
    }
}

Main

public class Main {
    public static void main(String[] args) {
        final int CNT = 6;
        UserThread[] user = new UserThread[CNT];
        for (int i = 0; i < CNT; i++){
            user[i] = new UserThread(i + "-user");
            user[i].start();
        }
    }
}

Result

3-user print using com.company.Printer@651f2f3d
1-user print using com.company.Printer@651f2f3d
2-user print using com.company.Printer@651f2f3d
0-user print using com.company.Printer@651f2f3d
4-user print using com.company.Printer@651f2f3d
5-user print using com.company.Printer@651f2f3d
  • All threads access to only one instance.


Solution - Synchronize instance construction method

  • Use synchronized to prevent from accessing multiple threads to method simultaneously.

Printer

public class Printer {
    private static Printer printer = null;
    private Printer() {}

    public synchronized static Printer getPrinter(){
        if(printer == null){
            printer = new Printer();
        }
        return printer;
    }

    public void print(String str){
        System.out.println(str);
    }
}

UserThread

public class UserThread extends Thread {
    public UserThread(String name){
        super(name);
    }

    public void run(){
        Printer.getPrinter().print(Thread.currentThread().getName()
                + " " + "print using" +
                " " + Printer.getPrinter().toString());
    }
}

Main

public class Main {
    public static void main(String[] args) {
        final int CNT = 6;
        UserThread[] user = new UserThread[CNT];
        for (int i = 0; i < CNT; i++){
            user[i] = new UserThread(i + "-user");
            user[i].start();
        }
    }
}

Result

3-user print using com.company.Printer@8f62e66
4-user print using com.company.Printer@8f62e66
0-user print using com.company.Printer@8f62e66
1-user print using com.company.Printer@8f62e66
2-user print using com.company.Printer@8f62e66
5-user print using com.company.Printer@8f62e66
  • All threads access to only one instance.


Problem

  • Even though above multiple thread problems are solved, if there is variable in class like below then there comes another problem.
  • cnt’s value is not consistent.

Printer

public class Printer {
    private static Printer printer = null;
    private int cnt = 0;
    private Printer() {}

    public synchronized static Printer getPrinter(){
        if(printer == null){
            printer = new Printer();
        }
        return printer;
    }

    public void print(String str){
        cnt++;
        System.out.println(str + " " + "cnt : " + cnt);
    }
}

UserThread

public class UserThread extends Thread {
    public UserThread(String name){
        super(name);
    }

    public void run(){
        Printer.getPrinter().print(Thread.currentThread().getName()
                + " " + "print using" +
                " " + Printer.getPrinter().toString());
    }
}

Main

public class Main {
    public static void main(String[] args) {
        final int CNT = 6;
        UserThread[] user = new UserThread[CNT];
        for (int i = 0; i < CNT; i++){
            user[i] = new UserThread(i + "-user");
            user[i].start();
        }
    }
}

Result

2-user print using com.company.Printer@6fa76e7 cnt : 2
1-user print using com.company.Printer@6fa76e7 cnt : 4
3-user print using com.company.Printer@6fa76e7 cnt : 3
0-user print using com.company.Printer@6fa76e7 cnt : 2
4-user print using com.company.Printer@6fa76e7 cnt : 5
5-user print using com.company.Printer@6fa76e7 cnt : 6


Solution - Add synchronized in method

  • Cover method with synchronized() to prevent from simultaneous threads access.

Printer

public class Printer {
    private static Printer printer = null;
    private int cnt = 0;
    private Printer() {}

    public synchronized static Printer getPrinter(){
        if(printer == null){
            printer = new Printer();
        }
        return printer;
    }

    public void print(String str){
        synchronized (this){
            cnt++;
            System.out.println(str + " " + "cnt : " + cnt);
        }
    }
}

UserThread

public class UserThread extends Thread {
    public UserThread(String name){
        super(name);
    }

    public void run(){
        Printer.getPrinter().print(Thread.currentThread().getName()
                + " " + "print using" +
                " " + Printer.getPrinter().toString());
    }
}

Main

public class Main {
    public static void main(String[] args) {
        final int CNT = 6;
        UserThread[] user = new UserThread[CNT];
        for (int i = 0; i < CNT; i++){
            user[i] = new UserThread(i + "-user");
            user[i].start();
        }
    }
}

Result

0-user print using com.company.Printer@4f90c612 cnt : 1
5-user print using com.company.Printer@4f90c612 cnt : 2
4-user print using com.company.Printer@4f90c612 cnt : 3
2-user print using com.company.Printer@4f90c612 cnt : 4
1-user print using com.company.Printer@4f90c612 cnt : 5
3-user print using com.company.Printer@4f90c612 cnt : 6
  • Now cnt is printed well and there is only one instance.


Comparison between singleton pattern and static class


Reference

스트레티지 패턴(Strategy Pattern)에 대해서 알아보자

해당 내용은 책 ‘JAVA 객체지향 디자인 패턴’을 참고해서 작성하였습니다.


환경

  • Java


스트레티지 패턴(Strategy Pattern)이란?

스트레티지 패턴(Strategy Pattern)

  • 스트레티지 패턴(Strategy Pattern) : 특정한 알고리즘을 정의하고 이를 캡슐화하여 해당 알고리즘이 필요한 대상들이 이를 상호 교체 가능하게 하는 구조
  • Java의 경우 인터페이스를 생성하고 해당 부분을 구현해서 캡슐화 하고 이를 원하는 객체의 메소드에 붙여주면 된다. 자세한 설명과 예제는 아래 참고
  • 이미지 출처 : https://en.wikipedia.org/wiki/Strategy_pattern


필요성

로봇 사례

  • 로봇을 만든다고 생각해보자. 로봇은 태권V도 있고 아톰도 있고 건담도 있다. 이때 어떤 방법으로 만들어야할까? 가장 기본틀인 로봇을 추상 클래스로 만들고 상속을 통해 각각을 만들어보자.
  • 우선 로봇 추상 클래스를 만들고 태권V와 아톰만 만들어보자.


예제

Robot

public abstract class Robot {
    private String name;
    public Robot(String name){ this.name = name; }

    public String getName(){ return name;}

    public abstract void attack();
    public abstract void move();
}

TaekwonV

public class TaekwonV extends Robot {

    public TaekwonV(String name){
        super(name);
    }

    @Override
    public void attack() {
        System.out.println("I can kick");
    }

    @Override
    public void move() {
        System.out.println("I can walk");
    }
}

Atom

public class Atom extends Robot {

    public Atom (String name){
        super(name);
    }

    @Override
    public void attack() {
        System.out.println("I can punch");
    }

    @Override
    public void move() {
        System.out.println("I can fly");
    }
}

Main

public class Main {
    public static void main(String[] args) {

        Robot taekwonV = new TaekwonV("TaekwonV");
        Robot atom = new Atom("Atom");

        System.out.println("I am " + taekwonV.getName());
        taekwonV.attack();
        taekwonV.move();

        System.out.println();

        System.out.println("I am " + atom.getName());
        atom.attack();
        atom.move();
    }
}


해당 코드의 문제점

  • 기존 로봇의 공격 방법을 수정하려면 새로운 기능을 위해 기존 코드를 수정하기 때문에 OCP(Open-Closed Principle)에 위반된다. 예를들어 위의 예제에서 아톰이 태권V와 똑같은 move()를 사용하려 하면 코드를 직접 수정해야하고 나아가 중복이 발생하며 로봇의 종류가 많아질수록 코드의 관리는 어려워진다.
  • 새로운 로봇을 만들어서 아톰과 같은 공격과 태권V와 같은 이동을 하게 하고 싶다면? 동일한 코드를 복사하게 작성하게 되면 중복이 발생하게 된다. 예를 들어서 건담을 만들때 아톰의 attack()과 태권V의 move() 코드를 또 동일하게 작성하기 때문에 중복이 발생한다.


해결 방법

  • 로봇을 만드는 과정에 있어서 변화하는 부분이 무엇인지 먼저 찾아야한다. 변화될 수 있는 는 부분을 찾아서 이를 캡슐화하고 상호 교체 가능하도록 만드는것이 중요하다.
  • 예제 코드들에서는 attack()과 move()의 코드들이 계속 변경될 수 있으며 이를 캡슐화해서 필요할때 붙여주면 코드의 중복도 줄이고 코드의 변경도 줄일 수 있다.
  • 직접적인 구현은 각각을 interface로 구현해서 객체를 만들때 붙여주면 된다.
  • 그림에서 보면 move()의 경우에 MovingStrategy라는 인터페이스를 만들고 각각의 방법에 대한 구현을 implements를 통해서 클래스화 시키면된다.


예제

Robot

public abstract class Robot {
    private String name;
    private MovingStrategy movingStrategy;
    private AttackStrategy attackStrategy;

    public Robot(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void attack() {
        attackStrategy.attack();
    }

    public void move() {
        movingStrategy.move();
    }

    public void setAttackStrategy(AttackStrategy attackStrategy) {
        this.attackStrategy = attackStrategy;
    }

    public void setMovingStrategy(MovingStrategy movingStrategy) {
        this.movingStrategy = movingStrategy;
    }

}

AttackStrategy

public interface AttackStrategy {
    public void attack();
}

MovingStrategy

public interface MovingStrategy {
    public void move();
}

KickingStrategy

public class KickingStrategy implements AttackStrategy {
    @Override
    public void attack() {
        System.out.println("I can kick");
    }
}

PunchingStrategy__

public class PunchingStrategy implements AttackStrategy {
    @Override
    public void attack() {
        System.out.println("I can punch");
    }
}

WalkingStrategy

public class WalkingStrategy implements MovingStrategy {
    @Override
    public void move() {
        System.out.println("I can walk");
    }
}

FlyingStrategy

public class FlyingStrategy implements MovingStrategy {
    @Override
    public void move() {
        System.out.println("I can fly");
    }
}

TaekwonV

public class TaekwonV extends Robot {
    public TaekwonV(String name) {
        super(name);
    }
}

Atom

public class Atom extends Robot {
    public Atom(String name) {
        super(name);
    }
}

Gundam

public class Gundam extends Robot {
    public Gundam(String name) {
        super(name);
    }
}

Main

public class Main {
    public static void main(String[] args) {

        Robot taekwonV = new TaekwonV("TaekwonV");
        Robot atom = new Atom("Atom");
        Robot gundam = new Gundam("Gundam");

        taekwonV.setAttackStrategy(new KickingStrategy());
        taekwonV.setMovingStrategy(new WalkingStrategy());

        atom.setAttackStrategy(new PunchingStrategy());
        atom.setMovingStrategy(new FlyingStrategy());

        gundam.setAttackStrategy(new PunchingStrategy());
        gundam.setMovingStrategy(new WalkingStrategy());

        System.out.println("I am " + taekwonV.getName());
        taekwonV.attack();
        taekwonV.move();

        System.out.println();

        System.out.println("I am " + atom.getName());
        atom.attack();
        atom.move();

        System.out.println();

        System.out.println("I am " + gundam.getName());
        gundam.attack();
        gundam.move();

    }
}public class Main {
    public static void main(String[] args) {

        Robot taekwonV = new TaekwonV("TaekwonV");
        Robot atom = new Atom("Atom");
        Robot gundam = new Gundam("Gundam");

        taekwonV.setAttackStrategy(new KickingStrategy());
        taekwonV.setMovingStrategy(new WalkingStrategy());

        atom.setAttackStrategy(new PunchingStrategy());
        atom.setMovingStrategy(new FlyingStrategy());

        gundam.setAttackStrategy(new PunchingStrategy());
        gundam.setMovingStrategy(new WalkingStrategy());

        System.out.println("I am " + taekwonV.getName());
        taekwonV.attack();
        taekwonV.move();

        System.out.println();

        System.out.println("I am " + atom.getName());
        atom.attack();
        atom.move();

        System.out.println();

        System.out.println("I am " + gundam.getName());
        gundam.attack();
        gundam.move();

    }
}


참고자료