• 设计模式——策略模式


    一、定义与简单实现

    1、定义

    策略模式的定义包含三点:

    • 定义一类算法(接口)。
    • 封装每个算法(实现类)。
    • 这类算法的算法可互相替换(实现类之间可互相替换)。

    2、UML类图

    前两点已经成了我们的职业习惯(项目中一般都是一接口对应一实现类),重点是要弄清楚后面的算法互相替换,这个替换是在哪里实现的,需要达到什么效果?下面是一个简单的策略模式的UML图。

     

    • 定义一类算法(接口FlyBehavior)
    • 封装每个算法(实现类CanFly + NotFly)
    • Duck中定义一个FlyBehavior变量,然后运用组合的方式,CanFly、NotFly可以互换

    定义算法族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化独立于使用算法的客户,使Duck与Fly()解耦,

    运用的设计模式原则:

    • 封装变化
    • 多用组合,少用继承
    • 针对接口编程,不针对实现编程

    3、简单代码实现

    /*
     * 飞翔行为
     */
    public interface FlyBehavior {
    
        void fly();
    }
    
    public class CanFly implements FlyBehavior {
        @Override
        public void fly() {
            System.out.println("I can fly!");
        }
    }
    
    public class NotFly implements FlyBehavior{
        @Override
        public void fly() {
            System.out.println("I cant fly!");
        }
    }
    
    /*
     * 叫声
     */
    public interface QuackBehavior {
    
        void quack();
    }
    
    public class GaGa implements QuackBehavior{
        @Override
        public void quack() {
            System.out.println("ga  ga  ...");
        }
    }
    
    public class GuaGua implements QuackBehavior {
        @Override
        public void quack() {
            System.out.println("gua  gua  ...");
        }
    }
    
    public class NotQuack implements QuackBehavior {
        @Override
        public void quack() {
            System.out.println("...... ??");
        }
    }
    
    /* 
     * 鸭子
     */
    public interface DuckInterface {
    
        void swim();
    
        void display();
    
        void performFly();
    
        void performQuack();
    
        void setFlyBehavior(FlyBehavior flyBehavior);
        
        void setQuackBehavior(QuackBehavior quackBehavior);
    }
    
    public class Duck implements DuckInterface {
    
        private FlyBehavior flyBehavior;
        private QuackBehavior quackBehavior;
    
        @Override
        public void swim() {
            System.out.println("I am swimming!");
        }
    
        @Override
        public void display() {
            System.out.println("I have white feathers!");
        }
    
        @Override
        public void performFly() {
            if (flyBehavior == null){
                System.out.println("no flyBehavior!");
                return;
            }
            flyBehavior.fly();
        }
    
        @Override
        public void performQuack() {
            if (quackBehavior == null){
                System.out.println("no quackBehavior!");
                return;
            }
            quackBehavior.quack();
        }
    
        @Override
        public void setFlyBehavior(FlyBehavior flyBehavior) {
            this.flyBehavior = flyBehavior;
        }
    
        @Override
        public void setQuackBehavior(QuackBehavior quackBehavior) {
            this.quackBehavior = quackBehavior;
        }
    }
    
    public class Main {
    
        public static void main(String[] args) {
    
            FlyBehavior canFly = new CanFly();
            FlyBehavior notFly = new NotFly();
            //一个会飞的鸭子
            DuckInterface duck = new Duck();
            duck.setFlyBehavior(canFly);
            duck.performFly();
            //现在翅膀断了
            duck.setFlyBehavior(notFly);
            duck.performFly();
        }
    }

    二、框架中的策略模式

     框架中实现最明显的就是Mybatis中的执行器Executor,UML图

     

     虽然与给出的标准的策略模式UML有所差异,但是实现的效果一致。

    • 定义了一类一级缓存BaseExecutor(这里是个抽象类,由于方法有共同的逻辑,代码复用)
    • 一级缓存BaseExecutor有多个具体的实现封装(SimpleExecutor、ReuseExecutor、BatchExecutor、ClosedExecutor)
    • 二级缓存CachingExecutor中定义了一个一级缓存BaseExecutor变量(可用SimpleExecutor、ReuseExecutor、BatchExecutor互换,甚至可以用CachingExecutor互换,但是mybatis源码只是想达到前面的效果)

    CachingExecutor的实例化:

    /* org.apache.ibatis.session.Configuration#newExecutor(org.apache.ibatis.transaction.Transaction, org.apache.ibatis.session.ExecutorType) */
      public Executor newExecutor(Transaction transaction, ExecutorType executorType) {
        executorType = executorType == null ? defaultExecutorType : executorType;
        executorType = executorType == null ? ExecutorType.SIMPLE : executorType;
        Executor executor;
        if (ExecutorType.BATCH == executorType) {
          executor = new BatchExecutor(this, transaction);
        } else if (ExecutorType.REUSE == executorType) {
          executor = new ReuseExecutor(this, transaction);
        } else {
          executor = new SimpleExecutor(this, transaction);
        }
        if (cacheEnabled) {//默认为true
          executor = new CachingExecutor(executor);
        }
        executor = (Executor) interceptorChain.pluginAll(executor);
        return executor;
      }

    1

  • 相关阅读:
    面试高频题:讲讲项目中的技术难点?
    看完本文还不会安装mysql吗?
    spring中如何向一个单例bean中注入非单例bean
    一次性讲清楚spring中bean的生命周期之三:bean是如何实例化的
    java面试一日一题:字节java后端工程师面试题
    VMware 安装 Centos 7 虚拟机配置网络
    基于 Blazor 打造一款实时字幕
    MVP on Board 没用小技巧 👌
    数据治理实践:元数据管理架构的演变
    Apache Superset1.2.0教程(四)—— CentOS环境安装
  • 原文地址:https://www.cnblogs.com/wqff-biubiu/p/12613936.html
Copyright © 2020-2023  润新知