JavaRush /Java Blog /Random EN /Template Strategy (Strategy)

Template Strategy (Strategy)

Published in the Random EN group
The Strategy pattern defines a family of algorithms, encapsulates each of them, and ensures that they are interchangeable. It allows algorithms to be modified independently of their use on the client side (this definition is taken from the book “Head First. Design Patterns” by Eric Freeman and Elizabeth Robson). This definition looks a little confusing, so we need to explain this definition in more detail in normal language . Let's start with religion :) There are many religions in the world (confessions, movements, beliefs, etc.). How could we describe this in code. Well, for example, we could take the Religion class and inherit other religions from it. Let’s abstract away the unnecessary stuff and use one believe() method in the Religion class.
public abstract class Religion {
    public void believe() {
        System.out.println("Я верю в Бога-творца этого мира");
    }
}
All other religions can be inherited from this class. If we had limited ourselves to Christianity and even Islam and Judaism, then there would have been no problems.
public class Judaism extends Religion {
}
public class Islam extends Religion {
}
public class Christianity extends Religion {
}
But if you think about the other religions that exist now (or existed before, but disappeared), then problems will arise, at least with Buddhists. You'll have to override their believe method.
public class Buddhism extends Religion {
    @Override
    public void believe() {
        System.out.println("Есть Бог or боги or нет, это не важно, главное достичь нирваны :)");
    };
}
And since there are many religions and they even believe in the pasta monster (Pastafarianism), then in all these religions you will have to redefine the believe method. But can we do it differently, move this method to the Faith interface and implement the believe method in it and implement this method in each class (and accordingly implement it in each class as we wish)? But then we will get duplication of code, well, at least among Jews and Christians. Muslims of God can write in Arabic.
public interface Faith {
    public void believe();
}
public class Christianity implements Faith {
    @Override
    public void believe() {
        System.out.println("Я верю в Бога-творца этого мира");
    }
}
public class Judaism implements Faith {
    @Override
    public void believe() {
        System.out.println("Я верю в Бога-творца этого мира");
    }
}
Implementing the default method will not help much here; there are so many religions that even if you define this method by default in the Faith interface, you will have to implement this method in your own way in all non-monotheistic religions, and repeat it somewhere. What does the Strategy pattern offer us in this case: it offers to create ready-made template classes for the current interface, which will then be substituted into the constructor of a specific religion. Those. define and create the same family of algorithms that was mentioned at the beginning of the definition.
public interface Faith {
    public void believe();
}
public class AbrahamicReligion implements Faith {
    @Override
    public void believe() {
        System.out.println("Я верю в Бога-творца этого мира");
    }
}
public class BuddismReligion implements Faith {
    @Override
    public void believe() {
        System.out.println("Есть Бог or боги or нет, это не важно, главное достичь нирваны :)");
    }
}
public class JediismReligion implements Faith {
    @Override
    public void believe() {
        System.out.println("Да пребудет с вами Сила!");
    }
}
And in each class in the constructor, substitute them.
public abstract class Religion {
    Faith faith;
}
public class Judaism extends Religion{

    public Judaism() {
        this.faith = new AbrahamicReligion();
    }
}
public class Christianity extends Religion{

    public Christianity() {
        this.faith = new AbrahamicReligion();
    }
}
public class Buddhism extends Religion {

    public Buddhism() {
        this.faith = new BuddismReligion();
    }
}
Thus, if you need to include another religion in your project, you will not have to redefine the believe method for all classes or parts of classes. And you will only need to implement the missing class (if there is none already) that implements the Faith interface and add this class in the constructor of the new religion.
public class PastafarianismReligion implements Faith{

    @Override
    public void believe() {
        System.out.println("Кто съел мои макароны???");
    }
}
public class Pastafarianism extends Religion {

    public Pastafarianism() {
        this.faith = new PastafarianismReligion();
    }
}
Comments
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION