Understand the Strategy pattern by comparing JavaScript and Java code

Introduction

Details and other patterns will be written in ** Understanding design patterns by comparing implementations in JavaScript and Java **. I wrote an example of JavaScript by looking at Java. We do not take advantage of differences in features such as class type / prototype type, typed strength, and access modifiers. Please note.

Strategy strategy means "strategy" Strategies for solving problems, that is, algorithms can be exchanged for other algorithms The Strategy pattern is a pattern that makes it easier to solve the same problem differently.

Implementation in Java

Class diagram

Strategy.png

code

Main.java


public class Main {
    public static void main(String[] args) {
        if (args.length != 2) {
            System.out.println("Usage: java Main randomseed1 randomseed2");
            System.out.println("Example: java Main 314 15");
            System.exit(0);
        }
        int seed1 = Integer.parseInt(args[0]);
        int seed2 = Integer.parseInt(args[1]);
        Player player1 = new Player("Taro", new WinningStrategy(seed1));
        Player player2 = new Player("Hana", new ProbStrategy(seed2));
        for (int i = 0; i < 1; i++) {
            Hand nextHand1 = player1.nextHand();
            Hand nextHand2 = player2.nextHand();
            if (nextHand1.isStrongerThan(nextHand2)) {
                System.out.println("Winner:" + player1);
                player1.win();
                player2.lose();
            } else if (nextHand2.isStrongerThan(nextHand1)) {
                System.out.println("Winner:" + player2);
                player1.lose();
                player2.win();
            } else {
                System.out.println("Even...");
                player1.even();
                player2.even();
            }
        }
        System.out.println("Total result:");
        System.out.println(player1.toString());
        System.out.println(player2.toString());
    }
}

Strategy.java


public interface Strategy {
    public abstract Hand nextHand();
    public abstract void study(boolean win);
}

WinningStrategy.java


import java.util.Random;

public class WinningStrategy implements Strategy {
    private Random random;
    private boolean won = false;
    private Hand prevHand;
    public WinningStrategy(int seed) {
        random = new Random(seed);
    }
    public Hand nextHand() {
        if (!won) {
            prevHand = Hand.getHand(random.nextInt(3));
        }
        return prevHand;
    }
    public void study(boolean win) {
        won = win;
    }
}

ProbStrategy.java


import java.util.Random;

public class ProbStrategy implements Strategy {
    private Random random;
    private int prevHandValue = 0;
    private int currentHandValue = 0;
    private int[][] history = {
        {1, 1, 1,},
        {1, 1, 1,},
        {1, 1, 1,},
    };
    public ProbStrategy(int seed) {
        random = new Random(seed);
    }
    public Hand nextHand() {
        int bet = random.nextInt(getSum(currentHandValue));
        int handvalue = 0;
        if (bet < history[currentHandValue][0]) {
            handvalue = 0;
        } else if (bet < history[currentHandValue][0] + history[currentHandValue][1]) {
            handvalue = 1;
        } else {
            handvalue = 2;
        }
        prevHandValue = currentHandValue;
        currentHandValue = handvalue;
        return Hand.getHand(handvalue);
    }
    private int getSum(int hv) {
        int sum = 0;
        for (int i = 0; i < 3; i++) {
            sum += history[hv][i];
        }
        return sum;
    }
    public void study(boolean win) {
        if (win) {
            history[prevHandValue][(currentHandValue + 1) % 3]++;
            history[prevHandValue][(currentHandValue + 2) % 3]++;
        }
    }
}

Player.java


public class Player {
    private String name;
    private Strategy strategy;
    private int wincount;
    private int losecount;
    private int gamecount;
    public Player(String name, Strategy strategy) {
        this.name = name;
        this.strategy = strategy;
    }
    public Hand nextHand() {
        return strategy.nextHand();
    }
    public void win() {
        strategy.study(true);
        wincount++;
        gamecount++;
    }
    public void lose() {
        strategy.study(false);
        losecount++;
        gamecount++;
    }
    public void even() {
        gamecount++;
    }
    public String toString() {
        return "[" + name + ":" + gamecount + " games, " + wincount + " wind, " + losecount + "lose" + "]";
    }
}

Hand.java


public class Hand {
    public static final int HANDVALUE_GUU = 0;
    public static final int HANDVALUE_CHO = 1;
    public static final int HANDVALUE_PAA = 2;
    public static final Hand[] hand = {
        new Hand(HANDVALUE_GUU),
        new Hand(HANDVALUE_CHO),
        new Hand(HANDVALUE_PAA),
    };
    private static final String[] name = {
        "Goo", "Choki", "Par",
    };
    private int handvalue;
    private Hand(int handvalue) {
        this.handvalue = handvalue;
    }
    public static Hand getHand(int handvalue) {
        return hand[handvalue];
    }
    public boolean isStrongerThan(Hand h) {
        return fight(h) == 1;
    }
    public boolean isWeakerThan(Hand h) {
        return fight(h) == -1;
    }
    private int fight(Hand h) {
        if (this == h) {
            return 0;
        } else if ((this.handvalue + 1) % 3 == h.handvalue) {
            return 1;
        } else {
            return -1;
        }
    }
    public String toString() {
        return name[handvalue];
    }
}

JavaScript

code

index.html


<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>Strategy</title>
</head>
<body>
    <script src="Main.js"></script>
    <script src="WinningStrategy.js"></script>
    <script src="ProbStrategy.js"></script>
    <script src="Player.js"></script>
    <script src="Hand.js"></script>
</body>
</html>

Main.js


MAIN = {};

MAIN.init = function() {
    'use strict';
    var player1 = new Player("Taro", new WinningStrategy());
    var player2 = new Player("Hana", new ProbStrategy());
    for (var i = 0; i < 1000; i++) {
        var nextHand1 = player1.nextHand();
        var nextHand2 = player2.nextHand();
        console.log(Hand.jankenName[nextHand1.handvalue], Hand.jankenName[nextHand2.handvalue]);
        if (nextHand1.isStrongerThan(nextHand2)) {
            console.log("Winner:" + player1.name);
            player1.win();
            player2.lose();
        } else if (nextHand2.isStrongerThan(nextHand1)) {
            console.log("Winner:" + player2.name);
            player2.win();
            player1.lose();
        } else {
            console.log("Even...");
            player1.even();
            player2.even();
        }
    }
    console.log("Total result:");
    console.log(player1.toString());
    console.log(player2.toString());
}
window.addEventListener("load", MAIN.init);

Player.js


var Player = function(name, strategy) {
    this.name = name;
    this.strategy = strategy;
    this.wincount = 0;
    this.losecount = 0;
    this.gamecount = 0;
}

Player.prototype = {
    constructor: "Player",

    nextHand: function() {
        return this.strategy.nextHand();
    },
    win: function() {
        this.strategy.study(true);
        this.wincount++;
        this.gamecount++;
    },
    lose: function() {
        this.strategy.study(false);
        this.losecount++;
        this.gamecount++;
    },
    even: function() {
        this.gamecount++;
    },
    toString: function() {
        return "[" + this.name + ":" + this.gamecount + " games, " + this.wincount + " wind, " + this.losecount + " lose" + "]";
    }
}

WinningStrategy.js


var WinningStrategy = function() {
    this.random = Math.floor(Math.random() * 3);
    this.won = false;
    this. prevHand;
}
WinningStrategy.prototype = {
    constructor: "WinningStrategy",

    nextHand: function() {
        return Hand.getHand(this.random);
    },
    study: function(win) {
        if (win) {
            won = win;
        }
    }
};

ProbStrategy.js


var ProbStrategy = function() {
    this.random = Math.floor(Math.random() * 3);
    this.prevHandValue = 0;
    this.currentHandValue = 0;
    this.history = [
        [1, 1, 1],
        [1, 1, 1],
        [1, 1, 1]
    ];
};

ProbStrategy.prototype = {
    constructor: "ProbStrategy",

    nextHand: function() {
        let bet = Math.floor(Math.random() * this.getSum(this.currentHandValue));
        let handvalue = 0;
        if (bet < this.history[this.currentHandValue][0]) {
            handvalue = 0;
        } else if (bet < this.history[this.currentHandValue][0] + this.history[this.currentHandValue][1]) {
            handvalue = 1;
        } else {
            handvalue = 2;
        }
        this.prevHandValue = this.currentHandValue;
        this.currentHandValue = handvalue;
        return Hand.getHand(handvalue);
    },
    getSum: function(hv) {
        let sum = 0;
        for (var i = 0; i < 3; i++) {
            sum += this.history[hv][i];
        }
        return sum;
    },
    study: function(win) {
        if (win) {
            this.history[this.prevHandValue][(this.currentHandValue + 1) % 3]++;
            this.history[this.prevHandValue][(this.currentHandValue + 2) % 3]++;
        }
    }
}

Hand.js


var Hand = function(handvalue) {
    this.handvalue = handvalue;
};

Hand.prototype = {
    constructor: "Hand",

    isStrongerThan: function(h) {
        return this.fight(h) == 1;
    },
    fight(h) {
        if (this == h) {
            return 0;
        } else if ((this.handvalue + 1) % 3 == h.handvalue) {
            return 1;
        } else {
            return -1;
        }
    }
};

Hand.HANDVALUE_GUU = 0;
Hand.HANDVALUE_CHO = 1;
Hand.HANDVALUE_PAA = 2;
Hand.hand = [
    new Hand(Hand.HANDVALUE_GUU),
    new Hand(Hand.HANDVALUE_CHO),
    new Hand(Hand.HANDVALUE_PAA),
];
Hand.jankenName = ["Goo", "Choki", "Par"];

Hand.getHand = function(handvalue) {
    return Hand.hand[handvalue];
}

Characters in the Decorator pattern

** The role of Strategy **

Define only the interface (API) Sample program → Strategy (interface)

** The role of Concreate Strategy **

The role that implements the interface of the Strategy role Program a concrete strategy Sample program → WinningStrategy (class)           ProbStrategy(class)

** The role of Context **

A role that uses the Strategy role Have a ConcreateStrategy role Sample program → player (class)

Decorator pattern class diagram

Strategy2..png

The need for a Decorator pattern

Basically I write the algorithm in the method However, the Strategy pattern consciously separates the algorithm part. By using the algorithm by delegation If you want to modify the algorithm, modify ConcreateStrategy If you want to change the algorithm, you can modify the Context.

It is also possible to change dynamically by separating the algorithm

When using the Decorator pattern

I think there are situations where you can see it on your smartphone or on your computer today. When you want to use different algorithms with a weak CPU like a smartphone and a powerful CPU like a personal computer Enable by using the Strategy pattern

Related patterns

reference

[Introduction to Design Patterns Learned in the Augmented and Revised Java Language](https://www.amazon.co.jp/%E5%A2%97%E8%A3%9C%E6%94%B9%E8%A8%82% E7% 89% 88Java% E8% A8% 80% E8% AA% 9E% E3% 81% A7% E5% AD% A6% E3% 81% B6% E3% 83% 87% E3% 82% B6% E3% 82% A4% E3% 83% B3% E3% 83% 91% E3% 82% BF% E3% 83% BC% E3% 83% B3% E5% 85% A5% E9% 96% 80-% E7% B5 % 90% E5% 9F% 8E-% E6% B5% A9 / dp / 4797327030)

Recommended Posts

Understand the Strategy pattern by comparing JavaScript and Java code
Understand the Decorator pattern by comparing JavaScript and Java code
Understand the State pattern by comparing JavaScript and Java code
Understand the Composite pattern by comparing JavaScript and Java code
Understand design patterns by comparing implementations in JavaScript and Java [Updated from time to time]
Try to implement and understand the segment tree step by step (python)
Java compilation and execution understood by CLI
Read the file by specifying the character code.
Understand the Decision Tree and classify documents
Learn the design pattern "Strategy" in Python