“This is the fourth day of my participation in the First Challenge 2022. For details: First Challenge 2022”

preface

Hello everyone, MY name is Kano, a full stack full stick engineer!

In the first three chapters, Lambda is described in the way of theory and cases, which should basically solve the problems of Lambda encountered in daily development. In order to better show the charm of Lambda and deepen and consolidate the knowledge of Lambda, today we discuss how Lambda reconstructs the design mode!

About Design Patterns

As we all know, a design pattern is a scheme by which a group of big programmers sum up their experience in programming. It is not a syntax specification, but a set of solutions to improve code reusability, maintainability, readability, robustness, and security.

This article will not go into too much detail about design patterns, but by default you are familiar with them (I will cover all of them separately later).

Lambda refactoring design pattern

Next, a list of common design patterns, through the traditional and lambda form contrast writing method, let everyone feel different, lambda version of the design pattern!

Simple Factory model

The simple Factory mode is also called Static Factory Method mode because internal methods are usually defined as Static. It is used by a Factory object to create an instance of a product class by the type required by the client. Simple Factory mode is the most simple and practical mode in the Factory mode family. It can be understood as a special implementation of a different factory pattern.

Case study: Fruit factory

Including oranges, bananas and apples

  • The traditional writing
/** * simple factory *@author : uu
 * @version : v1.0
 * @Date2022/1/20 * /
public class FruitFactory {
    public static Fruit getFruit(String fruitName) {
        Fruit fruit = null;
        switch (fruitName) {
            case "Banana":
                fruit = new Banana();
                break;
            case "Apple":
                fruit = new Apple();
                break;
        }
        returnfruit; }}Copy the code

The essence of the factory pattern is to return an object when called. Recall that Supplier seems to do just that in Java’s built-in functional interface.

  • Lambda method
/** * Lambda form factory mode *@author : uu
 * @version : v1.0
 * @Date2022/1/20 * /
public class FruitLambdaFactory {
    /** * Initial chemical plant data */
    private static Map<String, Supplier<Fruit>> FRUIT_FACTORY = new HashMap<String, Supplier<Fruit>>(){{
       put("Banana", Banana::new);
       put("Apple", Apple::new);
    }};

    public static Fruit getLambdaFruit(String fruit) {
        Supplier<Fruit> fruitSupplier = FRUIT_FACTORY.get(fruit);
        return Objects.nonNull(fruitSupplier) ? fruitSupplier.get() : null; }}Copy the code

For example, to add a new fruit category, you have to change the factory static method, which violates the open and close principle, and it is easy to misspell by passing in string form. In practice, we can use reflection to solve this problem.

  • Reflective writing
/** * Reflective factory mode **@author : uu
 * @version : v1.0
 * @Date2022/1/20 * /
public class FruitReflectFactory {

    public static <T extends Fruit> T getLambdaFruit(Class<T> fruitCls) {
        try {
            return fruitCls.newInstance();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        return null; }}Copy the code

The strategy pattern

The strategy pattern is to encapsulate a series of algorithms that can be replaced with each other at run time, which is a good solution to the excessive use of if… else if… Else question!

Case in point: Multiple channels for sending messages

Including mail channel and WebSocket channel

  • The traditional model
/** * Send channel policy *@author : uu
 * @version : v1.0
 * @Date2022/1/20 prepare * /
public interface SendChannelStrategy {
    /** * send interface *@param msg
     */
    void send(String msg);
}

/** * Email policy *@author : uu
 * @version : v1.0
 * @Date 2022/1/20  20:19
 */
public class EmailChannelStrategy implements SendChannelStrategy{
    @Override
    public void send(String msg) {
        System.out.println("Send by email:"+ msg); }}/** * websocket policy *@author : uu
 * @version : v1.0
 * @Date 2022/1/20  20:19
 */
public class WebSocketChannelStrategy implements SendChannelStrategy{
    @Override
    public void send(String msg) {
        System.out.println("Send using websocket:"+ msg); }}/** * Message service, using the send policy *@author : uu
 * @version : v1.0
 * @Date2022/1/20 * /
@AllArgsConstructor
@Getter@Setter
public class SendService {
    private SendChannelStrategy sendChannelStrategy;
    
    public void send(String msg) { sendChannelStrategy.send(msg); }}// Use it as follows
public void test(a){
    SendService sendService = new SendService(new EmailChannelStrategy());
    sendService.send("Kano"); // Send by email to: Kano
    sendService.setSendChannelStrategy(new WebSocketChannelStrategy());
    sendService.send("Kano"); // Use websocket to send: kano
}
Copy the code

The above policy mode interface is a functional interface (with only one abstract method). The method has an input parameter and no return value. Let’s take a look at how Lambda is handled.

  • Lambda method
public void testLambda(a){
    SendService sendService = new SendService(msg -> System.out.println("Send using Lambda Email:" + msg));
    sendService.send("Kano"); // Send by email to: Kano
    
    sendService.setSendChannelStrategy(msg -> System.out.println("Send using websocket:" + msg));
    sendService.send("Kano"); // Use websocket to send: kano
}
Copy the code

Instead of using Consumer, we can omit the EmailChannelStrategy and WebSocketChannelStrategy class definitions.

Template method pattern

The template method pattern means that the parent class defines the process and allows subclasses to implement one or more steps in the process. This allows subclasses to implement their own personalized operations without changing the overall process.

Case in point: The process of the game

Choose a position to play the game (lying/sitting), start the game, end the game

  • The traditional writing
/** * game *@author : uu
 * @version : v1.0
 * @Date 2022/1/20  20:49
 */
public abstract class Game {

    public void play(String posture) {
        selectPlayPosture(posture);
        System.out.println("Start the game");
        System.out.println("End the game.");
    }

    /** * Select the game pose */
    public abstract void selectPlayPosture(String posture);
}
/** ** lie down and play *@author : uu
 * @version : v1.0
 * @Date2022/1/20 20:53 * /
public class LieGame extends Game{
    @Override
    public void selectPlayPosture(String posture) {
        System.out.println("On the sofa:"+ posture); }}/** ** sit and play *@author : uu
 * @version : v1.0
 * @Date2022/1/20 20:52 * /
public class SitGame extends Game{
    @Override
    public void selectPlayPosture(String posture) {
        System.out.println("On the bench:"+ posture); }}/ / test
public void test(a){
    Game game = new LieGame();
    game.play("Lying");
    game = new SitGame();
    game.play("Sit");
}
Copy the code

From the code above, we may find template mode to realize the need to be a subclass of the abstract interface is a ginseng, abstract method has no return value, Java built-in functional interface Consumer to match, we will need to subclass implementation method, extracted by Consumer as the game process parameters, can greatly reduce code, As follows:

  • Lambda method
/** * Lambda form template method *@author : uu
 * @version : v1.0
 * @Date 2022/1/20  20:49
 */
public class LambdaGame {

    public void play(String posture, Consumer<String> consumer) {
        consumer.accept(posture);
        System.out.println("Start the game");
        System.out.println("End the game."); }}// The usage mode
public void testLambda(a){
    LambdaGame game = new LambdaGame();
    game.play("Lying", System.out::println);
    game.play("Sit", System.out::println);
}
Copy the code

Doesn’t it look a lot easier to rewrite Lambda?

The source code

  • 👉 source can be accessed here

conclusion

  • This chapter shows the convenience that Lambda brings to code writing by using the Lambda refactoring design pattern.

  • This list only lists a few commonly used design pattern rewriting, friends interested to discuss other pattern rewriting oh;

  • The code in the case is relatively simple, but the actual development still depends on the needs of the business, rather than simply for the sake of simplicity.

Related articles

  • Lambda must know, must know
  • Lambda built-in functional interface
  • Lambda method references, you can figure it out!

The last

  • Thank you for your patience. If you find this article helpful, please like 👍 or follow ➕.

  • Due to my limited technology, the article and code may be wrong, I hope you comment pointed out, very grateful 🙏;

  • At the same time, I also welcome you to discuss learning front-end, Java knowledge, volume and progress together.