Java デザイン パターン - テンプレート パターン (行動パターン、テンプレート パターン、戦略パターン、状態パターンの違い)

1. デザインパターンの最初の紹介

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

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

2. テンプレートモード

テンプレート メソッドを使用すると、アルゴリズムの構造を変更せずに、サブクラスでアルゴリズムの特定のステップを再定義できます。つまり、親クラスはサブクラスのテンプレートである必要があり、各サブクラスを繰り返すのではなく、繰り返されるコードはすべて親クラスにアップグレードされる必要があります。サブクラスは、異なるアルゴリズム ステップのみを担当します。

1) 適用可能なシナリオ

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

2) コード

使用法: クラスの頻繁に変更される部分、または変更される可能性のある部分を抽象インターフェイス クラスとして抽出し、このオブジェクトのインスタンスをクラスに含めます。これにより、クラス インスタンスは、実行時にこのインターフェイスを実装するクラスの動作を自由に呼び出すことができます。 。
親クラスとサブクラス。親クラスのテンプレート メソッドは一般的なロジックを提供しますが、各メソッドはサブクラス自体によって実装される必要があります。

/**
 * 模板类
 */
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();
    }


}

結果を出力します。

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

列挙型を使用して実装クラスを取得することに加えて、環境クラスを使用することもできます。

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) メリットとデメリット

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


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

3. 戦略モデル

戦略パターンでは、アルゴリズムのファミリーを定義し、それらを個別にカプセル化し、相互に置き換えることができるようにします。このパターンにより、アルゴリズムの変更がアルゴリズムを使用する顧客に影響を与えないようになります。

1) 適用可能なシナリオ

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

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

2) コード

//策略接口类
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();
    }
}

テンプレート クラスは、テンプレート メソッドを含む抽象クラスであり、ストラテジ クラスはインターフェイス クラスです。これらは、ストラテジ サブクラスのアルゴリズムが異なるだけです。テンプレート クラスであってもストラテジ クラスであっても、サブクラスのアルゴリズムは固有かつ独立しています。ただし、ステート モード アルゴリズムの各サブクラスは相互接続されています。

4.ステータスモード

1) 適用可能なシナリオ

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

2) コード

//状态类
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();
    }
}

印刷結果

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

おすすめ

転載: blog.csdn.net/Little_Arya/article/details/129169781