Java design pattern - template pattern (behavioral pattern, with differences between template pattern, strategy pattern and state pattern)

1. First introduction to design patterns

设计模式的目的是为了重用代码,让代码更容易被他人理解,以及保证代码可靠性。
总体来说,设计模式分为三大类:

创建型模式:共5种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式
结构型模式:共7种:适配器模式、装饰器模式、代理模式、桥接模式、外观模式、组合模式、享元模式
行为型模式:共11种:策略模式、模板方法模式、观察者模式、责任链模式、访问者模式、中介者模式、迭代器模式、命令模式、状态模式、备忘录模式、解释器模式

2. Template mode

Template methods allow subclasses to redefine specific steps of an algorithm without changing the structure of the algorithm. That is to say, the parent class should be the template for the child class, and all repeated codes should be upgraded to the parent class, instead of having each child class repeat it. The child class is only responsible for different algorithm steps.

1) Applicable scenarios

工作中遇到一个场景,就是几乎系统的每一个页面都会去调用同一个方法,但是调用方法前的逻辑不一致。
如: function A(){
           B; //各个页面自己的逻辑
           C;//通用逻辑
  }
这时可以想到模板模式,将公共的方法C放父类去,子类做不同的功能实现。

2) Code

Usage : Extract the frequently changing or possibly changing parts of the class as an abstract interface class, and then include an instance of this object in the class, so that the class instance can freely call the behavior of the class that implements this interface at runtime.
Parent class and subclass, the template method in the parent class gives the general logic, but each method needs to be implemented by the subclass itself

/**
 * 模板类
 */
public abstract class StrategyHandler {

    //抽象方法 供不同子类实现
    public abstract void method();

    public void equalWay(){
        method();
        //模板方法
        System.out.println("ABC通用方法");
    }

}
/**
 * 第一个实现类
 */
@Service("strategyImplA")
public class StrategyImplA extends StrategyHandler {

    public void method() {
        System.out.println("第一个实现类的方法");
    }
}

/**
 * 第二个实现类
 */
@Service("strategyImplB")
public class StrategyImplB extends StrategyHandler {

    public void method() {
        System.out.println("第二个实现类的方法");
    }
}

/**
 * 第三个实现类
 */
@Service("strategyImplC")
public class StrategyImplC extends StrategyHandler {

    public void method() {
        System.out.println("第三个实现类的方法");
    }
}
/**
 * 模板枚举类
 */
public enum TypeEnum {
    A("strategyImplA", "第一个实现类"),
    B("strategyImplB", "第二个实现类"),
    C("strategyImplC", "第三个实现类"),
    ;

    private String handler;
    private String description;

    TypeEnum(String handler, String description) {
        this.handler = handler;
        this.description = description;
    }


    public String getHandler() {
        return handler;
    }

    public void setHandler(String handler) {
        this.handler = handler;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }
}
@SpringBootApplication
public class DemoApplication {


    //启动类里 初始化ApplicationContext  1
    private static ApplicationContext context;

    // 初始化ApplicationContext 2
    @Bean
    public ApplicationContext getApplicationContext() {
        return context;
    }

    public static void main(String[] args) {
        //初始化ApplicationContext 3   1,2,3固定位置放
        context = SpringApplication.run(DemoApplication.class, args);

        // 若别的Controller需要获得实现类bean 则这样引入bean:  @Autowired  ApplicationContext context;

        //用枚举值获得实现类bean
        StrategyHandler serviceA = (StrategyHandler)context.getBean(TypeEnum.A.getHandler());
        serviceA.equalWay();

        StrategyHandler serviceB = (StrategyHandler)context.getBean(TypeEnum.B.getHandler());
        serviceB.equalWay();

        StrategyHandler serviceC = (StrategyHandler)context.getBean(TypeEnum.C.getHandler());
        serviceC.equalWay();
    }


}

Print the result:

第一个实现类的方法
ABC通用方法
第二个实现类的方法
ABC通用方法
第三个实现类的方法
ABC通用方法

In addition to using enumerations to obtain implementation classes, you can also use environment classes:

public class Context {

    StrategyHandler strategyHandler;

    public Context(StrategyHandler strategyHandler) {
        this.strategyHandler = strategyHandler;
    }

    public void testHandler(){
        strategyHandler.equalWay();
    }
}


调用的时候只需:
       //不用枚举类 直接给出实现类
        Context ctx = new Context(new StrategyImplA());
        ctx.testHandler();

打印结果:
第一个实现类的方法
ABC通用方法

3) Advantages and Disadvantages

优点:
  1)模板模式符合开闭原则(对拓展开放,对修改关闭);
  2)避免使用多重条件转移语句,如if...else...语句和switch 语句;
  3)恰当使用继承可以把公共的代码移到父类里面(当某个类继承父类,即可调用父类的非私有方法),
  从而避免代码重复。 


缺点:很明显就是实现类很多

3. Strategy model

The strategy pattern defines a family of algorithms and encapsulates them separately so that they can be replaced with each other. This pattern allows changes in the algorithm to not affect the customers who use the algorithm.

1) Applicable scenarios

   (1)应用程序需要实现特定的功能服务,而该程序有多种实现方式使用,所以需
   要动态地在几种算法中选择一种;
   
   (2)一个类定义了多种行为算法,并且这些行为在类的操作中以多个条件语句的
   形式出现,就可以将相关的条件分支移入它们各自的Strategy类中以代替这些条
   件语句。

   (3)策略模式就是用来封装算法的,在实践中,可以用策略模式封装几乎任何类型的规则,
    只要在分析过程中听到需要在不同时间应用不同的业务规则,就可以考虑使用策略模式。
    选择哪种策略是客户端决定的,可以把new哪种策略改为switch结构,甚至使用反射。

2) Code

//策略接口类
public interface Strategy {
    void algorithm();
}
//不同的策略的实现类
public class ConcreteStrategyA implements Strategy{
    @Override
    public void algorithm() {
        System.out.println("算法A");
    }
}

public class ConcreteStrategyB implements Strategy{
    @Override
    public void algorithm() {
        System.out.println("算法B");
    }
}

public class ConcreteStrategyC implements Strategy{
    @Override
    public void algorithm() {
        System.out.println("算法C");
    }
}

//环境类
public class Context {
    private Strategy strategy;

    public Context(String type) throws Exception {
        switch (type){
            case "A":
                strategy = new ConcreteStrategyA();
                break;
            case "B":
                strategy = new ConcreteStrategyB();
                break;
            case "C":
                strategy = new ConcreteStrategyC();
                break;
            default:
                throw new Exception();
        }
    }

    public void contextInterface(){
        if(!Objects.isNull(strategy)){
            strategy.algorithm();
        }
    }
}

//方法调用
public class TestdemoApplication {
    public static void main(String[] args) {
        Context context = new Context("A");
        context.contextInterface();
    }
}

The template class is an abstract class, including template methods, and the strategy class is an interface class. They only have different strategy subclass algorithms. Whether it is a template class or a strategy class, the algorithms of the subclasses are specific and independent, but each subclass of the state mode Algorithms are interconnected.

4. Status mode

1) Applicable scenarios

1、当一个对象的行为取决于它的状态,并且它必须在运行时刻根据状态改变它的行为时,可以使用状态模式。
2、状态模式通过把各种状态转移逻辑分布到State的子类中

2) Code

//状态类
public interface State {
    public void handle(Context context);
}

//状态子类
public class ConcreteStateA implements State{
    @Override
    public void handle(Context context) {
    	//状态切为B
        context.setState((State) new ConcreteStateB());
    }
}

public class ConcreteStateB implements State{
    @Override
    public void handle(Context context) {
        //状态切为C
        context.setState((State) new ConcreteStateC());
    }
}

public class ConcreteStateC implements State{
    @Override
    public void handle(Context context) {
        context.setState((State) new ConcreteStateA());
    }
}
//环境类
public class Context {
    private State state;

    public Context(State state) {
        this.state = state;
    }

    public State getState() {
        return state;
    }

    public void setState(State state) {
        this.state = state;
        System.out.println("当前状态:" + this.state.getClass().getName());
    }

    public void request(){
        this.state.handle(this);
    }
}
//主方法调用
public class TestdemoApplication {
    public static void main(String[] args) {
        Context context = new Context(new ConcreteStateA());
        context.request();
        context.request();
        context.request();
        context.request();
    }
}

Print results

当前状态:com.example.design.state.ConcreteStateB
当前状态:com.example.design.state.ConcreteStateC
当前状态:com.example.design.state.ConcreteStateA
当前状态:com.example.design.state.ConcreteStateB

Guess you like

Origin blog.csdn.net/Little_Arya/article/details/129169781