The book “Head First. Design patterns. Updated Anniversary Edition »

    imageIn the world, someone is constantly faced with the same programming problems that you have. Many developers solve completely identical problems and find similar solutions. If you do not want to reinvent the wheel, use ready-made design patterns (patterns) that this book is devoted to working with.

    Patterns appeared because many developers were looking for ways to increase the flexibility and degree of reuse of their programs. The solutions found are embodied in a concise and easily practicable form.

    The peculiarity of this publication is a unique way of presenting material, highlighting the O'Reilly series of “Head First” among a number of boring books on programming. Dalla presents the passage "Simplifying RemoteControl Code with Lambda Expressions"

    As you have already seen, the Team pattern is fairly straightforward. However, the Java language provides a convenient tool that simplifies code even further - namely, lambda expressions. A lambda expression is an abbreviated form for writing a method (as a sequence of calculations) exactly where it is used. Instead of creating a separate class with a method, creating an instance of this class, and then calling the method, you simply indicate: “Here is the method to be called” using a lambda expression. In our case, the execute () method should be called.

    To understand how this is done, replace the LightOnCommand and LightOffCommand objects with
    lambda expressions. Follow these steps to make light on / off commands implemented by lambda expressions instead of command objects:

    Step 1. Create a receiver
    image

    Step 2. The implementation of the remote control commands using lambda expressions.

    Here the most interesting thing happens. Now, instead of creating LightOnCommand and LightOffCommand objects to pass remoteControl.setCommand (), we simply pass a lambda expression with the code from the corresponding execute () method instead of each object:

    image

    Step 3. Activating the buttons

    This step also has not changed - except for the fact that when the onButtonWasPushed (0) method is called, the command in slot 0 is represented by a function object (created using a lambda expression). When we call execute () on a command, this method maps to the method defined by the lambda expression, which is then executed.

    image

    We use lambda expressions to replace Command objects, and the Command interface contains just one method: execute (). The lambda expression that we use must have a compatible signature - the way it is: the execute () method does not receive arguments (like our lambda expression) and does not return a value (like our lambda expression). The compiler is happy with everything. The lambda expression is passed in the Command parameter of the setCommand () method:

    image

    Remember: if the parameter interface in which the lambda expression is passed contains one (and only one!) Method, and the signature of this method is compatible with the signature of the lambda expression, everything will work as it should.

    Method Links


    To simplify the code even further, you can use the links to the methods. If the passed lambda expression calls just one method, you can
    pass a method reference instead of the lambda expression . This is done like this:

    image

    Instead of passing a lambda expression that calls the on () method of the
    livingRoomLight object , we pass a reference to the method itself.

    But what if a lambda expression must perform several operations at once?

    Sometimes lambda expressions used to replace Command objects are not limited to one operation. Let's see how to replace stereoOnWithCDCommand and
    stereoOffCommand objects with lambda expressions. The following is the full RemoteLoader code so you can understand how all of these ideas fit together.

    The stereoOffCommand object executes just one simple command:

    stereo.off();

    For this command, instead of the lambda expression, you can use the link to the stereo :: off method.
    But stereoOnWithCDCommand performs not one, but three operations:

    stereo.on();
    stereo.setCD();
    stereo.setVolume(11);

    In this case, using the method link will fail. Instead, you will either have to write the lambda expression in the embedded form, or create it separately, assign a name, and then pass the remoteControl object by name to the setCommand () method. The option of creating a
    separate lambda expression and assigning a name to it looks like this:

    Command stereoOnWithCD = () -> {
             stereo.on(); stereo.setCD(); stereo.setVolume(11);
    };
    remoteControl.setCommand(3, stereoOnWithCD, stereo::off);

    Note: Command is used as a type of lambda expression. The lambda expression is
    mapped to the execute () method of the Command interface and to the Command parameter, in which
    it is passed to the setCommand () method.

    Test drive commands using lambda expressions


    To use lambda expressions to simplify the code of the original
    RemoteControl implementation (without canceling), we will modify the RemoteLoader code and replace specific
    Command objects with lambda expressions. You also need to modify the RemoteControl constructor
    to use lambda expressions instead of the NoCommand object. After that, you can
    delete all specific Command classes (LightOnCommand, LightOffCommand,
    HottubOnCommand, HottubOffCommand, etc.). That's all! Everything else remains the
    same. Do not accidentally remove the Command interface; it is necessary for comparing the type
    of function objects created by lambda expressions, which are stored in the
    remote control object and transmitted to various methods.

    The new code for the RemoteLoader class looks like this:

    public class RemoteLoader {
          public static void main(String[] args) {
                RemoteControl remoteControl = new RemoteControl();
                Light livingRoomLight = new Light("Living Room");
                Light kitchenLight = new Light("Kitchen");
                CeilingFan ceilingFan = new CeilingFan("Living Room");
                GarageDoor garageDoor = new GarageDoor("Main house");
                Stereo stereo = new Stereo("Living Room");
    Удаляем весь код создания конкретных объектов Command (вместе с самими классами). Код становится куда более компактным (а от 22 классов остается только 9).
                remoteControl.setCommand(0, livingRoomLight::on, livingRoomLight::off);
                remoteControl.setCommand(1, kitchenLight::on, kitchenLight::off);
                remoteControl.setCommand(2, ceilingFan::high, ceilingFan::off);
                Command stereoOnWithCD = () -> {
                         stereo.on(); stereo.setCD(); stereo.setVolume(11);
                };
                remoteControl.setCommand(3, stereoOnWithCD, stereo::off);
                remoteControl.setCommand(4, garageDoor::up, garageDoor::down);
    Мы используем ссылки на методы повсюду, где используются простые команды из одного метода, и полные лямбда-выражения там, где одного вызова метода недостаточно.(Ссылку на метод можно рассматривать как компактное лямбда-выражение. По сути это одно и то же; ссылка на метод — просто сокращенная запись для лямбда-выражения, которое вызывает всего один метод.)
                System.out.println(remoteControl);
                remoteControl.onButtonWasPushed(0);
                remoteControl.offButtonWasPushed(0);
                remoteControl.onButtonWasPushed(1);
                remoteControl.offButtonWasPushed(1);
                remoteControl.onButtonWasPushed(2);
                remoteControl.offButtonWasPushed(2);
                remoteControl.onButtonWasPushed(3);
                remoteControl.offButtonWasPushed(3);

    And don't forget: we must change the RemoteControl constructor, remove the NoCommand object construction code from it, and replace it with lambda expressions.

    public class RemoteControl {
          Command[] onCommands;
          Command[] offCommands;
          public RemoteControl() {
                onCommands = new Command[7];
                offCommands = new Command[7];
                for (int i = 0; i < 7; i++) {
                     onCommands[i] = () -> { };
                     offCommands[i] = () -> { };
                }
          }
          // Остальной код
    }

    Now, check the results of all these teams with lambda expressions ...

    image

    "For more information on the book is available on the website of the publishing house
    " Table of Contents
    " Extract

    To Habrozhiteley 20% discount coupon - Head A First

    Also popular now: