设计模式(装饰模式)
什么是裝飾模式(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{@Overridepublic void operation() {System.out.println("balabala....");} }abstract class Decorator implements Component{private Component comp;public Decorator(Component comp){this.comp = comp;}@Overridepublic void operation() {comp.operation();} }class ConcreateDecorator extends Decorator{public ConcreateDecorator(Component comp) {super(comp);}@Overridepublic 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;}@Overridepublic <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey cacheKey, BoundSql boundSql) throws SQLException {return null;}@Overridepublic void commit(boolean required) throws SQLException {}@Overridepublic void rollback(boolean required) throws SQLException {}@Overridepublic CacheKey createCacheKey(MappedStatement ms, Object parameterObject, RowBounds rowBounds, BoundSql boundSql) {return null;}@Overridepublic Transaction getTransaction() {return null;}@Overridepublic 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);}@Overridepublic <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey cacheKey, BoundSql boundSql) throws SQLException {return null;}@Overridepublic void commit(boolean required) throws SQLException {}@Overridepublic void rollback(boolean required) throws SQLException {}@Overridepublic CacheKey createCacheKey(MappedStatement ms, Object parameterObject, RowBounds rowBounds, BoundSql boundSql) {return null;}@Overridepublic Transaction getTransaction() {return null;}@Overridepublic 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;} }
?
轉載于:https://www.cnblogs.com/jiangyaxiong1990/p/9236764.html
總結
以上是生活随笔為你收集整理的设计模式(装饰模式)的全部內容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: FFmpeg命令行工具学习(三):媒体文
- 下一篇: 太行山大峡谷退伍军人免票吗
