• 设计模式(装饰模式)


    什么是装饰模式(Decorator):
      装饰模式是为已有功能动态的添加更多功能的一种方式;在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能。它是通过创建一个包装对象,也就是装饰来包裹真实的对象;

    装饰模式由4种角色组成:
      抽象构件(Component)角色:给出一个抽象接口,以规范准备接收附加职责的对象;
      具体构件(Concrete Component)角色:定义一个将要接收附加职责的类;
      装饰(Decorator)角色:持有一个构件(Component)对象的实例,并实现一个与抽象构件接口一致的接口,从外类来扩展Component类的功能,但对于Component类来说,是无需知道Decorato的存在的;
      具体装饰(Concrete Decorator)角色:负责给构件对象添加上附加的职责;

    装饰模式的优点:
      1.把类中的装饰功能从类中搬移出去,这样可以简化原有的类;
      2.有效的把类的核心职责和装饰功能分开,而且可以去除相关类中重复的装饰逻辑;
      3.装饰模式与继承关系的目的都是要扩展对象的功能,但是装饰模式可以提供比继承更多的灵活性;
      4.通过使用不同的具体装饰类以及这些装饰类的排列组合,设计师可以创造出很多不同行为的组合;

    装饰模式的应用场景,以下引自百度百科:
      1. 需要扩展一个类的功能,或给一个类添加附加职责;
      2. 需要动态的给一个对象添加功能,这些功能可以再动态的撤销;
      3. 需要增加由一些基本功能的排列组合而产生的非常大量的功能,从而使继承关系变的不现实;
      4. 当不能采用生成子类的方法进行扩充时。
        一种情况是,可能有大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长。
        另一种情况可能是因为类定义被隐藏,或类定义不能用于生成子类;

    模式简化
      如果只有一个Concrete Component类而没有抽象的Component接口时,可以让Decorator继承Concrete Component;
      如果只有一个Concrete Decorator类时,可以将Decorator和Concrete Decorator合并;

    UML类图

    根据UML生成一个简单的Demo:

    interface Component{
        void operation();
    }
    
    class ConcreateComponent implements Component{
        @Override
        public void operation() {
            System.out.println("balabala....");
        }
    }
    
    abstract class Decorator implements Component{
        private Component comp;
    
        public Decorator(Component comp){
            this.comp = comp;
        }
    
        @Override
        public void operation() {
            comp.operation();
        }
    }
    
    class ConcreateDecorator extends Decorator{
        public ConcreateDecorator(Component comp) {
            super(comp);
        }
    
        @Override
        public void operation() {
            System.out.println("begin...");
            super.operation();
            System.out.println("end...");
        }
    }
    
    public class TestMain {
        public static void main(String[] args) {
            Component component = new ConcreateComponent();
            component = new ConcreateDecorator(component);
            component.operation();
        }
    }

     输出的结果为:

    begin...
    balabala....
    end...

    在Mybatis的Executor也采用了装饰模式,不过在使用方法上稍微有些区别,我们先看一下Executor的实现图:

    以下是我从Mybatis中分离出来的一部分代码,标红部分可以重点关注一下:

    package org.apache.ibatis.executor;
    
    import org.apache.ibatis.cache.CacheKey;
    import org.apache.ibatis.mapping.BoundSql;
    import org.apache.ibatis.mapping.MappedStatement;
    import org.apache.ibatis.session.ResultHandler;
    import org.apache.ibatis.session.RowBounds;
    import org.apache.ibatis.transaction.Transaction;
    
    import java.sql.SQLException;
    import java.util.List;
    
    public interface Executor {
        ResultHandler NO_RESULT_HANDLER = null;
    
        <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey cacheKey, BoundSql boundSql) throws SQLException;
    
        void commit(boolean required) throws SQLException;
    
        void rollback(boolean required) throws SQLException;
    
        CacheKey createCacheKey(MappedStatement ms, Object parameterObject, RowBounds rowBounds, BoundSql boundSql);
    
        Transaction getTransaction();
    
        void setExecutorWrapper(Executor var1);
    }
    package org.apache.ibatis.executor;
    
    import org.apache.ibatis.cache.CacheKey;
    import org.apache.ibatis.logging.Log;
    import org.apache.ibatis.logging.jdbc.ConnectionLogger;
    import org.apache.ibatis.mapping.BoundSql;
    import org.apache.ibatis.mapping.MappedStatement;
    import org.apache.ibatis.session.Configuration;
    import org.apache.ibatis.session.ResultHandler;
    import org.apache.ibatis.session.RowBounds;
    import org.apache.ibatis.transaction.Transaction;
    
    import java.sql.Connection;
    import java.sql.SQLException;
    import java.util.List;
    
    public abstract class BaseExecutor implements Executor {
    
        protected Transaction transaction;
        protected Executor wrapper;
    
        protected Configuration configuration;
    
        protected int queryStack;
    
        protected BaseExecutor(Configuration configuration, Transaction transaction) {
            this.transaction = transaction;
            this.configuration = configuration;
            this.wrapper = this;
        }
    
        @Override
        public <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey cacheKey, BoundSql boundSql) throws SQLException {
            return null;
        }
    
        @Override
        public void commit(boolean required) throws SQLException {
    
        }
    
        @Override
        public void rollback(boolean required) throws SQLException {
    
        }
    
        @Override
        public CacheKey createCacheKey(MappedStatement ms, Object parameterObject, RowBounds rowBounds, BoundSql boundSql) {
            return null;
        }
    
        @Override
        public Transaction getTransaction() {
            return null;
        }
    
        @Override
        public void setExecutorWrapper(Executor var1) {
            this.wrapper = wrapper;
        }
    
        protected Connection getConnection(Log statementLog) throws SQLException {
            Connection connection = transaction.getConnection();
            if (statementLog.isDebugEnabled()) {
                return ConnectionLogger.newInstance(connection, statementLog, queryStack);
            } else {
                return connection;
            }
        }
    
    }
    
    package org.apache.ibatis.executor;
    
    import org.apache.ibatis.executor.statement.StatementHandler;
    import org.apache.ibatis.logging.Log;
    import org.apache.ibatis.session.Configuration;
    import org.apache.ibatis.transaction.Transaction;
    
    import java.sql.Connection;
    import java.sql.SQLException;
    import java.sql.Statement;
    
    public class SimpleExecutor extends BaseExecutor {
    
        protected SimpleExecutor(Configuration configuration, Transaction transaction) {
            super(configuration, transaction);
        }
    
        private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException {
            Statement stmt;
            Connection connection = getConnection(statementLog);
            stmt = handler.prepare(connection, transaction.getTimeout());
            handler.parameterize(stmt);
            return stmt;
        }
    
    }
    
    package org.apache.ibatis.executor;
    
    import org.apache.ibatis.cache.CacheKey;
    import org.apache.ibatis.cache.TransactionalCacheManager;
    import org.apache.ibatis.mapping.BoundSql;
    import org.apache.ibatis.mapping.MappedStatement;
    import org.apache.ibatis.session.ResultHandler;
    import org.apache.ibatis.session.RowBounds;
    import org.apache.ibatis.transaction.Transaction;
    
    import java.sql.SQLException;
    import java.util.List;
    
    public class CachingExecutor implements Executor{
    
        private final Executor delegate;
        private final TransactionalCacheManager tcm = new TransactionalCacheManager();
    
        public CachingExecutor(Executor delegate) {
            this.delegate = delegate;
            delegate.setExecutorWrapper(this);
        }
    
        @Override
        public <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey cacheKey, BoundSql boundSql) throws SQLException {
            return null;
        }
    
        @Override
        public void commit(boolean required) throws SQLException {
    
        }
    
        @Override
        public void rollback(boolean required) throws SQLException {
    
        }
    
        @Override
        public CacheKey createCacheKey(MappedStatement ms, Object parameterObject, RowBounds rowBounds, BoundSql boundSql) {
            return null;
        }
    
        @Override
        public Transaction getTransaction() {
            return null;
        }
    
        @Override
        public void setExecutorWrapper(Executor var1) {
            throw new UnsupportedOperationException("This method should not be called");
        }
    }
    
    package org.apache.ibatis.session;
    
    import org.apache.ibatis.executor.*;
    import org.apache.ibatis.plugin.InterceptorChain;
    import org.apache.ibatis.transaction.Transaction;
    
    public class Configuration {
    
        private Configuration conf;
        public Configuration(Configuration conf){
            this.conf = conf;
        }
    
        protected boolean cacheEnabled = true;
        protected ExecutorType defaultExecutorType = ExecutorType.SIMPLE;
    
        protected final InterceptorChain interceptorChain = new InterceptorChain();
    
        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(conf, transaction);
            }
            if (cacheEnabled) {
                executor = new CachingExecutor(executor);
            }
            executor = (Executor) interceptorChain.pluginAll(executor);
            return executor;
        }
    }
    

      

  • 相关阅读:
    显示非模式窗口和模式窗口
    delphi 版本号
    数字证书和签名
    DLL知道自己的位置
    拖动处理
    驱动配置相关
    python sturct模块操作C数据
    Lambda学习笔记
    【转】update select
    [转]视频格式分类
  • 原文地址:https://www.cnblogs.com/jiangyaxiong1990/p/9236764.html
Copyright © 2020-2023  润新知