Java8 Practical Combat [Chapter 8] Refactoring, testing and debugging, using Lambda expressions to refactor code, taking three design patterns as examples Strategy pattern, Observer pattern, Template method

1. Strategy mode

Strategy pattern belongs to the behavior pattern of objects.

Its purpose is to encapsulate each algorithm into an independent class with a common interface for a set of algorithms, so that they can be replaced with each other. The strategy pattern allows the algorithm to change without affecting the client.

Declare strategy pattern interface:

/**
 * 策略模式接口
 * @version 1.0
 * @description: TODO 策略模式
 */
public interface StrategyPatternMain {

      // 执行的方法
//    EntityPayInfo execute(String info);

    // 另一种使用方式
    boolean isTrue(String s);

}

Implement two strategies through the interface: Strategy 1

/**
 * @version 1.0
 * @description: TODO 策略模式
 */
public class StrategyPatternAliPay implements StrategyPatternMain{

    // 封装支付宝信息
//    @Override
//    public EntityPayInfo execute(String info) {
//        return EntityPayInfo.builder()
//                .id(RandomStringUtils.randomAlphanumeric(16))
//                .name("测试员01")
//                .money(10.67)
//                .phone("183xxx12323")
//                .sex(1)
//                .payType("支付宝")
//                .info(info)
//                .build();
//    }

    @Override
    public boolean isTrue(String s) {
        return s.matches("[a-z]+");
    }
}

Implement two strategies through the interface: Strategy 2

/**
 * @version 1.0
 * @description: TODO 策略模式
 */
public class StrategyPatternWXPay implements StrategyPatternMain{

    // 封装微信信息
//    @Override
//    public EntityPayInfo execute(String info) {
//        return EntityPayInfo.builder()
//                .id(RandomStringUtils.randomAlphanumeric(16))
//                .name("测试员02")
//                .money(12.67)
//                .phone("183xxx12324")
//                .sex(0)
//                .payType("微信支付")
//                .info(info)
//                .build();
//    }

    @Override
    public boolean isTrue(String s) {
        return s.matches("自定义");
    }
}

Apply strategy mode:

/**
 * @version 1.0
 * @description: TODO 策略模式
 */

@Slf4j
@RestController
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
@RequestMapping("/start01")
public class StrategyPatternStart {

    private StrategyPatternMain strategyPatternMain;

    public StrategyPatternStart(StrategyPatternMain main){
        this.strategyPatternMain = main;
    }

    /**
     * 灵活使用微信、支付宝对象信息
     * @param info 保存的参数
     * @return EntityPayInfo 返回的实体
     */
//    public EntityPayInfo obtainInfo(String info){
//        return strategyPatternMain.execute(info);
//    }

    /**
     * 校验参数信息是否正确
     * @param info 保存的参数
     * @return boolean 返回的信息
     */
    public boolean obtainInfo(String info){
        return strategyPatternMain.isTrue(info);
    }

    @GetMapping("/test01")
    public String testA(int type){

//        StrategyPatternMain StrategyPatternMain;
//
//        根据传入的类型选择支付的类型
//        if (type == 1)
//        {
//            StrategyPatternMain = new StrategyPatternAliPay();
//        }
//        else
//        {
//            StrategyPatternMain = new StrategyPatternWXPay();
//        }
//        StrategyPatternStart strategyPatternMain = new StrategyPatternStart(StrategyPatternMain);
//        EntityPayInfo info = strategyPatternMain.obtainInfo("支付完成!");
//
//        return info.toString();

        /**
         * 使用Lambda表达式之后
         */
        StrategyPatternStart strategyPatternStart = new StrategyPatternStart((String s) -> s.matches("[a-z]+"));
        System.out.println(strategyPatternStart.obtainInfo("abc"));

        return "nice";
    }

}

2. Observer mode

The simple understanding of the observer mode is to get what you need. Just like the several newspapers mentioned in the article, such as the New York Times, the Guardian and Le Monde, they all subscribe to the news. They hope that when the news they receive contains They can get special notifications when keywords interest them.

Declaration information prompt interface:

/**
 * @author jcs
 * @version 1.0
 * @description: TODO 观察者模式
 * @date 2022/9/4 14:41
 */
public interface Observer {

    // 提醒信息
    String remindInfo(String message);

}

Observer 1:

/**
 * @version 1.0
 * @description: TODO 观察者01
 */
public class ObserverSub01 implements Observer{

    /**
     * 收到消息提醒
     * @return String
     */
    @Override
    public String remindInfo(String message) {
        if (StringUtils.isNotBlank(message) && message.contains("java")){
            return "观察者01: 已接收消息通知";
        }
        return "观察者01: 等候中...";
    }

}

Observer 2:

/**
 * @version 1.0
 * @description: TODO 观察者02
 */
public class ObserverSub02 implements Observer{

    /**
     * 收到消息提醒
     * @return String
     */
    @Override
    public String remindInfo(String message) {
        if (StringUtils.isNotBlank(message) && message.contains("hello world")){
            return "观察者02: 已接收消息通知";
        }
        return "观察者02: 等候中...";
    }

}

Information publisher:

/**
 * @version 1.0
 * @description: TODO 观察者模式
 */
@Slf4j
@RestController
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
@RequestMapping("/start03")
public class ObserverStart {

    @GetMapping("/test01")
    public String testA(){

        List<Observer> listUser = Lists.newArrayList();
        listUser.add(new ObserverSub01());
        listUser.add(new ObserverSub02());

        listUser.forEach(info-> System.out.println(info.remindInfo("hello java")));

        return "success";
    }
}

3. Template method

If you need to adopt the framework of a certain algorithm and at the same time hope to have a certain degree of flexibility and be able to improve some parts of it,
then using the template method to design the pattern is a more general solution. Okay, that sounds a bit abstract. In other words, the template method pattern is very useful when
you "want to use this algorithm, but need to improve certain lines in it to achieve the desired effect." Let's start with an example to see how this pattern works.

Declare an abstract class and define template methods:

/**
 * @version 1.0
 * @description: TODO 模板方法
 */
public abstract class TemplateMethods {

    /**
     * 复习:抽象类和接口的区别
     * 
     * 1、抽象类和接口都不能直接实例化。如果要实例化,抽象类变量必须指向实现所有抽象方法的子类对象,接口变量必须指向实现所有接口方法的类对象。
     *
     * 2、抽象类要被子类继承,接口要被类实现。
     *
     * 3、接口只能做方法申明,抽象类中可以做方法申明,也可以做方法实现。
     *
     * 4、接口里定义的变量只能是公共的静态的常量,抽象类中的变量是普通变量。
     *
     * 5、抽象类里的抽象方法必须全部被子类所实现,如果子类不能全部实现父类抽象方法,那么该子类只能是抽象类。同样,实现接口的时候,如不能全部实现接口方法,那么该类也只能为抽象类。
     *
     * 6、抽象方法只能申明,不能实现。
     *
     * 7、抽象类里可以没有抽象方法
     *
     * 8、如果—个类里有抽象方法,那么这个类只能是抽象类
     *
     * 9、抽象方法要被实现,所以不能是静态的,也不能是私有的。
     *
     * 10、接口可以继承接口,并且可多继承接口,但类只能单—继承。
     *
     * 11.接口可以通过匿名内部类实例化。接口是对动作的抽象,抽象类是对根源的抽象。抽象类表示的是,这个对象是什么。而接口表示的是,这个对象能做什么。
     */

    // 校验参数是否通过
    protected abstract boolean checkParams(String val);

    // 返回信息
    protected abstract String obtainResult();

    public String execute(String val){
        boolean status = checkParams(val);
        if (status) {
            System.out.println("true:" + obtainResult());
        } else {
            System.out.println("false:" + obtainResult());
        }
        return "执行完成...";

    }

}

Template method one:

/**
 * @version 1.0
 * @description: TODO 模板方法
 */
public class TemplateMethodsTemp01 extends TemplateMethods{

    @Override
    protected boolean checkParams(String val) {
        return StringUtils.isNotBlank(val);
    }

    @Override
    protected String obtainResult() {
        return "当前执行方法temp01... ";
    }
}

Template method two:

/**
 * @version 1.0
 * @description: TODO 模板方法
 */
public class TemplateMethodsTemp02 extends TemplateMethods{

    @Override
    protected boolean checkParams(String val) {
        return StringUtils.isNotBlank(val);
    }

    @Override
    protected String obtainResult() {
        return "当前执行方法temp02... ";
    }
}

Apply template method:

/**
 * @version 1.0
 * @description: TODO 模版方法
 */
@Slf4j
@RestController
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
@RequestMapping("/start02")
public class TemplateMethodsStart {

    @GetMapping("/test01")
    public String testA(){

        TemplateMethods templateMethods1 = new TemplateMethodsTemp01();
        String test01 = templateMethods1.execute("test");
        System.out.println("test01:" + test01);

        TemplateMethods templateMethods2 = new TemplateMethodsTemp02();
        String test02 = templateMethods2.execute("");
        System.out.println("test02:" + test02);

        return "success";

    }

}

Guess you like

Origin blog.csdn.net/amosjob/article/details/127062084