Post about Strategy Pattern.


Environment and Prerequisite

  • Java


What is Strategy Pattern?

Strategy Pattern

  • Strategy Pattern: It is a design pattern which define set of algorithms and interchange those algorithms when it is needed. Those algorithms are encapsulated by class. Instead of implementing a single algorithm directly, code receives run-time instructions as to which in a family of algorithms to use.
  • In case of java, define strategy to interface and implement it in class to encapsulate it. Add it to object’s method when you use it. There will be an examples below.
  • Image Source: https://en.wikipedia.org/wiki/Strategy_pattern


Necessity

Robot Example

  • Let’s imagine we make robots. Robots will be TaekwonV, Atom and Gundam. How to implement them then? Make basic form in abstract Robot class and use inheritance(‘extends’ keyword in java).
  • First, let’s make abstract Robot class, TaekwonV class and Atom class.


Example

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("kick");
    }

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

Atom

public class Atom extends Robot {

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

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

    @Override
    public void move() {
        System.out.println("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();
    }
}


Problems in above code.

  • To modify existed code to new code, we need to modify existed code and it violates OCP(Open-Closed Principle). For example in above code if we like to use same move() method in both Atom and TaekwonV we need to modify existed code and it also cause duplicate code. As the number of robots grows, it is hard to manage code.
  • What if we like to make new robot and use same method of TaekwonV’s move() and Atom’s attack()? There will be a code duplication if we copy and paste it.


Solution

  • In implementing robot, we need to find which part of code are changeable. Find changing part, encapsulate it and make it interchangeable.
  • In above code, attack() and move() are changeable. So encapsulate those methods and use it when it is needed. It prevents from code duplication and code modifying.
  • Make each to java’s interface and make object when it is needed.
  • In case of move() method, make MovingStrategy interface and implements it in class.


Example

Robot

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

    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("kick");
    }
}

PunchingStrategy

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

WalkingStrategy

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

FlyingStrategy

public class FlyingStrategy implements MovingStrategy {
    @Override
    public void move() {
        System.out.println("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();

    }
}


Reference

cURL 사용 시 데이터(text/plain, x-www-form-urlencoded 또는 json)를 같이 보내는 법을 알아보자.


환경

  • Linux
  • cURL


cURL

옵션을 사용해 데이터를 포함한 요청 보내기

  • -d 옵션을 사용
curl -X<VERB> '<PROTOCOL>://<HOST>:<PORT>/<PATH>?<QUERY_STRING>' -d '<BODY>'


사용 예제

text/plain

  • -d 옵션을 사용하고 POST 방식으로 text 형태의 자료를 보내는 예제
curl -XPOST -H "Content-Type: text/plain" -d "raw text data" http://127.0.0.1:5000/test

application/x-www-form-urlencoded

  • -d 옵션을 사용하고 POST 방식으로 x-www-form-urlencoded 형태의 자료를 보내는 예제
curl -XPOST -H "Content-Type: application/x-www-form-urlencoded" -d "param1=value1&param2=value2" http://127.0.0.1:5000/test

application/json

  • -d 옵션을 사용하고 POST 방식으로 JSON 형태의 자료를 보내는 예제
curl -XPOST -H "Content-Type: application/json" http://127.0.0.1:5000/test -d '
{
   "test": "1234test",
   "child": {
      "child_1": "Hi",
      "cihld_2": "Hi"
   },
   "elements": [ "a", "b", "c" ]
}
'


참고자료

Summarize how to attach data(text/plain, x-www-form-urlencoded or json) when using cURL


Environment and Prerequisite

  • Linux
  • cURL


cURL

Send request with data using option

  • Use -d option.
curl -X<VERB> '<PROTOCOL>://<HOST>:<PORT>/<PATH>?<QUERY_STRING>' -d '<BODY>'


Usage Example

text/plain

  • Example of sending text format data with using -d option and POST method.
curl -XPOST -H "Content-Type: text/plain" -d "raw text data" http://127.0.0.1:5000/test

application/x-www-form-urlencoded

  • Example of sending x-www-form-urlencoded format data with using -d option and POST method.
curl -XPOST -H "Content-Type: application/x-www-form-urlencoded" -d "param1=value1&param2=value2" http://127.0.0.1:5000/test

application/json

  • Example of sending JSON format data with using -d option and POST method.
curl -XPOST -H "Content-Type: application/json" http://127.0.0.1:5000/test -d '
{
   "test": "1234test",
   "child": {
      "child_1": "Hi",
      "cihld_2": "Hi"
   },
   "elements": [ "a", "b", "c" ]
}
'


Reference

ssh 접속시 host의 key를 확인하지 않고 접속하는 방법을 알아보자.


환경

  • Linux
  • SSH(OpenSSH)


Host Key Checking

  • ssh를 이용해 원격에 있는 서버에 접근할 때 해당 서버에 대한 인증을 위해 로컬에 저장해둔 키와 서버의 키를 비교하는 작업을 진행한다.
  • 이런 작업을 통해 중간자 공격 같은 부분을 예방할 수 있다.


SSH 접속시 Host Key Checking 비활성화

  • 해당 옵션을 사용해도 만약 저장된 서버의 키가 없다면 ~/.ssh/known_hosts에 추가합니다.
  • 저장된 키가 서버의 키와 다르더라도 접속을 진행합니다.


1. ssh 명령어 사용 시 비활성화

  • StrictHostKeyChecking=no 옵션을 이용
ssh -o StrictHostKeyChecking=no [DOMAIN_OR_IP]


2. ssh config 파일을 수정

~/.ssh/config

  • 아래처럼 특정 호스트에 대해 옵션을 추가할 수 있다.
Host twpower-private-server
    HostName [IP ADDRESS]
    StrictHostKeyChecking no
    Port 22
    User [USERNAME]
    IdentityFile [IDENTITY KEY FILE]

/etc/ssh/ssh_config

  • 아래처럼 StrictHostKeyChecking no를 추가하며 *가 있기 때문에 접속하는 모든 호스트에 대해 Key 확인을 하지 않습니다.
  • /etc/ssh/ssh_config 파일은 해당 시스템에 있는 모든 유저에게 적용되는 옵션을 담고 있습니다.
Host *
    StrictHostKeyChecking no


참고자료

Summarize methods to disable host key checking while connecting ssh.


Environment and Prerequisite

  • Linux
  • SSH(OpenSSH)


Host Key Checking

  • When we connect to remote server by using ssh, client compares client’s saved key and remote server’s key to authenticate server.
  • This process prevents from Man-in-the-middle attack.


Disable Host Key Checking When Using SSH

  • Remote host’s key will be added if there is no added key in ~/.ssh/known_hosts.
  • Connect to remote server even though saved key is different from server’s key.


1. Disable when using ssh command

  • Use StrictHostKeyChecking=no option.
ssh -o StrictHostKeyChecking=no [DOMAIN_OR_IP]


2. Edit ssh config file

~/.ssh/config

  • Add option to specific host like below.
Host twpower-private-server
    HostName [IP ADDRESS]
    StrictHostKeyChecking no
    Port 22
    User [USERNAME]
    IdentityFile [IDENTITY KEY FILE]

/etc/ssh/ssh_config

  • There is * in config file. So this disables host key checking to all hosts.
  • /etc/ssh/ssh_config defines all the default settings for the client utilities for all users on that system.
Host *
    StrictHostKeyChecking no


Reference