国产av日韩一区二区三区精品,成人性爱视频在线观看,国产,欧美,日韩,一区,www.成色av久久成人,2222eeee成人天堂

Table of Contents
Decorator pattern UML diagram " >Decorator pattern UML diagram
裝飾器模式中的角色 " >裝飾器模式中的角色
小結(jié)" >小結(jié)
實戰(zhàn) " >實戰(zhàn)
大神們是怎么用的 " >大神們是怎么用的
JDK源碼中" >JDK源碼中
Spring源碼中" >Spring源碼中
Mybatis源碼中" >Mybatis源碼中
Home Java javaTutorial 3 years of work essential decorator mode

3 years of work essential decorator mode

Aug 28, 2023 pm 03:09 PM
Decorator pattern


Okay, let’s enter our topic. Today I will share with you the Decorator Mode in the design mode. Use appropriate life stories and real project scenarios to talk about the design pattern, and finally summarize the design pattern in one sentence.

Story

As the old saying goes: A man relies on his clothes and a horse relies on his saddle. Let us first familiarize ourselves with the background of this sentence:

People rely on clothes, horses rely on saddles, and dogs run with bells for joy. It comes from the tenth chapter of Shen Zijin's "Wanghu Pavilion": "Although In this way, Buddha relies on gold clothing, and people rely on clothing. Dressing up is also very important." Volume 1 of "Awakening the World": Two county magistrates compete for orphans in righteous marriage: "As the saying goes: 'Buddhas rely on gold clothing, and people rely on clothing. The eyes of the world's people are much shallower, and they only have skin and no bones.'" As the saying goes, we say that adults rely on clothes and horses rely on saddles.

This classic story reminds me of a design pattern: the decorator pattern.

What is the decorator pattern? Please listen to Lao Tian speak slowly.

Overview of Decorator Pattern

Decorator Pattern is also called Wrapper Pattern ), refers to dynamically adding some additional responsibilities to an object without changing the original object. In terms of adding functionality, the decorator pattern is more flexible than generating subclasses and is a structural design pattern.

English:

Attach additional responsibilities to an object dynamicallykeeping the same interface.Decorators provide a flexible alternative to subclassing for extending functionality.

The decorator pattern provides a more flexible alternative to inheritance ( Extend the functionality of the original object) Attach functionality to the object. Therefore, the core of the decorator pattern is functional extension. Use the decorator pattern to transparently and dynamically extend the functionality of a class.

Cases in life

A rough house looks very ugly before decoration, but as long as With a little decoration, it will be much more beautiful, and it can be used for bathing, sleeping, cooking, etc., but the essence is still a house.

A car was originally a vehicle for transportation, but Mary enlarged it and upgraded its configuration, and then it became a luxury car, but it was still essentially a vehicle for transportation.

A girl was originally very ordinary and average-looking, but after some makeup and some nice clothes, she became a goddess in the hearts of many people.

In short, after some decoration, it is different and its functions are enhanced.

Universal code implementation of decorator pattern

We still use code to implement it. Programmers like to first Make a demo and then study it slowly.

//抽象組件
public abstract class Component {
    public abstract void operation();
}
//具體組件
public class ConcreteComponent extends Component {
    @Override
    public void operation() {
        System.out.println("ConcreteComponent operation");
    }
}
//裝飾器抽象
public abstract class Decorator extends Component {

    protected Component component;

    public Decorator(Component component) {
        this.component = component;
    }

    @Override
    public void operation() {
        component.operation();
    }
}
//具體裝飾器
public class ConcreteDecorator extends Decorator {
    public ConcreteDecorator(Component component) {
        super(component);
    }

    @Override
    public void operation() {
        System.out.println("開始前搞點事");
        super.operation();
        System.out.println("結(jié)束后搞點事");
    }
}
//測試
public class Client {
    public static void main(String[] args) {
        Component component = new ConcreteDecorator(new ConcreteComponent());
        component.operation();
    }
}

Running results:

開始前搞點事
ConcreteComponent operation
結(jié)束后搞點事

The above is the general code implementation of the decorator pattern. Let’s analyze it below.

Decorator pattern UML diagram

3 years of work essential decorator mode


##It can be seen from UML that the role

裝飾器模式中的角色

  • 抽象組件(Component):可以是一個接口或者抽象類,充當(dāng)被裝飾類的原始對象,規(guī)定了被裝飾對象的行為。
  • 具體組件(ConcreteComponent):實現(xiàn)/繼承Component的一個具體對象,即被裝飾對象。
  • 抽象裝飾器(Decorator):通用的裝飾ConcreteComponent的裝飾器,其內(nèi)部必然有一個屬性指向Component;其實現(xiàn)一般是一個抽象類,主要為了讓其子類按照其構(gòu)造形式傳入一個Component,這是強制的通用行為。如果系統(tǒng)中裝飾邏輯單一,則并不需要實現(xiàn)許多裝飾器,可以直接省略該類,而直接實現(xiàn)一個具體裝飾器即可。
  • 具體裝飾器(ConcreteDecorator):Decorator的具體實現(xiàn)類,理論上,每個ConcreteDecorator都擴展了Component對象的一種功能。

小結(jié)

裝飾器模式角色分配符合設(shè)計模式的里氏替換原則、依賴倒置原則,從而使得其具備很強的擴展性,最終滿足開閉原則。

裝飾器模式的實現(xiàn)原理是,讓裝飾器實現(xiàn)與被裝飾類(例如ConcreteComponent)相同的接口(例如Component),使得裝飾器與被擴展類類型一致,并在構(gòu)造函數(shù)中傳入該接口對象,然后在實現(xiàn)這個接口的被包裝類對象的現(xiàn)有功能上添加新功能。由于裝飾器與被包裝類屬于同一類型(均為Component),且構(gòu)造函數(shù)的參數(shù)為其實現(xiàn)接口類(Component),因此裝飾器模式具備嵌套擴展功能,這樣就能使用裝飾器模式一層一層地對底層被包裝類進行功能擴展了。

實戰(zhàn)

在實際開發(fā)中,都會存在系統(tǒng)與系統(tǒng)之間的調(diào)用,假如說我們現(xiàn)在有個支付功能,現(xiàn)在一切都是沒問題的,但是 我們此時需要對發(fā)起支付前的請求參數(shù)和支付后的相應(yīng)參數(shù)。進行統(tǒng)一處理,原功能不變,只是在原功能上做了一點擴展(增強)。

老功能代碼如下:

/**
 * @author 田先生
 * @date 2021-06-02
 *
 * 歡迎關(guān)注公眾號:java后端技術(shù)全棧
 */
public interface IOrderPayService {
    String payment(Long orderId, BigDecimal amount);
}
public class OrderPayServiceImpl implements IOrderPayService {

    @Override
    public String payment(Long orderId, BigDecimal amount) {
        //先調(diào)用余額查詢是否足夠
        System.out.println("發(fā)起支付,訂單號:" + orderId + ", 支付金額:" + amount.toString());
        //調(diào)用支付系統(tǒng)
        String result = "訂單id=" + orderId + "支付完成";
        System.out.println("支付結(jié)果:" + result);
        return result;
    }
}
public class OrderClient {
    public static void main(String[] args) {
        IOrderPayService orderPayService = new OrderPayServiceImpl();
        orderPayService.payment(10001L,new BigDecimal("5000"));
    }
}

運行輸出:

發(fā)起支付,訂單號:10001, 支付金額:5000
支付結(jié)果:訂單id=10001支付完成

新需求,需要把這些請求參數(shù)和相應(yīng)結(jié)果進行單獨搜集處理,此時為了不影響原有功能,于是我們可以對其進行功能增強。

/**
 * @author 田先生
 * @date 2021-06-02
 *
 * 歡迎關(guān)注公眾號:java后端技術(shù)全棧
 */
public class OrderPayDecorator implements IOrderPayService {

    private IOrderPayService orderPayService;

    public OrderPayDecorator(IOrderPayService orderPayService) {
        this.orderPayService = orderPayService;
    }

    @Override
    public String payment(Long orderId, BigDecimal amount) {
        System.out.println("把這個訂單信息(發(fā)起支付)" + "訂單id=" + orderId + "支付金額=" + amount.toString() + " 【發(fā)送給MQ】");
        String result = orderPayService.payment(orderId, amount);
        System.out.println("把訂單支付結(jié)果信息" + result + " 【發(fā)送給MQ】");
        return result;
    }
}
public class OrderClient {
    public static void main(String[] args) {
        IOrderPayService orderPayService =new OrderPayDecorator(new OrderPayServiceImpl());
        orderPayService.payment(10001L,new BigDecimal("5000"));
    }
}

運行輸出:

把這個訂單信息(發(fā)起支付)訂單id=10001支付金額=5000 【發(fā)送給MQ】
發(fā)起支付,訂單號:10001, 支付金額:5000
支付結(jié)果:訂單id=10001支付完成
把訂單支付結(jié)果信息訂單id=10001支付完成 【發(fā)送給MQ】

整個過程,大家有沒有發(fā)現(xiàn),我們并沒動原有的代碼,僅僅只是做了功能增強。

裝飾器模式在新項目中基本上不會用到,通常都是在老項目中使用,因為已有的功能不變,只是做了一些功能增強。

大神們是怎么用的

裝飾器設(shè)計模式在JDK源碼、Spring源碼以及Mybatis源碼中都有。

JDK源碼中

裝飾器模式比較經(jīng)典的應(yīng)用就是 JDK 中的 java.io 包下,InputStream、OuputStream、Reader、Writer 及它們的子類。

以 InputStream 為例

  • FileInputStream 是 InputStream 的子類,用來讀取文件字節(jié)流
  • BufferedInputStream 是 InputStream 的子類的子類,可緩存的字節(jié)流
  • DataInputStream 也是 InputStream 的子類的子類,可直接讀取 Java 基本類型的字節(jié)流

UML圖

3 years of work essential decorator mode


DataInputStream 中構(gòu)造器入?yún)⒈闶亲约旱母割悾↖nputStream)。

3 years of work essential decorator mode

如果希望提供一個可以讀取文件 + 可緩存的字節(jié)流,使用繼承方式,就需要派生 FileBufferedInputStream;

如果希望提供一個可以讀取文件 + 直接讀取基本類型的字節(jié)流,使用繼承方式,就需要派生 FileDataInputStream。

字節(jié)流功能的增強還包括支持管道 pipe、字節(jié)數(shù)組 bytearray、字節(jié)對象 object、字節(jié)流字符流的轉(zhuǎn)換 等維度,如果用繼承方式,那類的層級與種類會多到爆炸。

為了解決問題,這邊就使用了裝飾器模式。

Spring源碼中

在Spring中,我們可以嘗試?yán)斫庖幌耇ransactionAwareCacheDecorator類,這個類主要用來處理事務(wù)緩存,代碼如下。

public class TransactionAwareCacheDecorator implements Cache {
    private final Cache targetCache;
    //構(gòu)造方法入?yún)㈩愋蜑樽约旱母割悾ń涌陬愋停?    public TransactionAwareCacheDecorator(Cache targetCache) {
        Assert.notNull(targetCache, "Target Cache must not be null");
        this.targetCache = targetCache;
    }

    public Cache getTargetCache() {
        return this.targetCache;
    }
    //...
}

TransactionAwareCacheDecorator就是對Cache的一個包裝,因此,這里也是使用了裝飾器模式。

Mybatis源碼中

MyBatis中關(guān)于Cache和CachingExecutor接口的實現(xiàn)類也使用了裝飾者設(shè)計模式。Executor是MyBatis執(zhí)行器,是MyBatis 調(diào)度的核心,負(fù)責(zé)SQL語句的生成和查詢緩存的維護;CachingExecutor是一個Executor的裝飾器,給一個Executor增加了緩存的功能。此時可以看做是對Executor類的一個增強,故使用裝飾器模式是合適的。

在CachingExecutor 中

public class CachingExecutor implements Executor {
  //持有組件對象
  private Executor delegate;
  private TransactionalCacheManager tcm = new TransactionalCacheManager();
    //構(gòu)造方法,傳入組件對象
  public CachingExecutor(Executor delegate) {
    this.delegate = delegate;
    delegate.setExecutorWrapper(this);
  }
  @Override
  public int update(MappedStatement ms, Object parameterObject) throws SQLException {
      //轉(zhuǎn)發(fā)請求給組件對象,可以在轉(zhuǎn)發(fā)前后執(zhí)行一些附加動作
    flushCacheIfRequired(ms);
    return delegate.update(ms, parameterObject);
  }
  //...
 }

總結(jié)

看完裝飾器模式后,你是否有感覺,裝飾器模式和代理模式非常的相像,下面我們就來做個對比。

1.裝飾器模式可以理解為一種特殊的代理模式。

2.裝飾器模式強調(diào)自身的功能擴展,透明的擴展(即用戶想增強什么功能就增強什么功能),可動態(tài)定制的擴展。

3.代理模式強調(diào)的是代理過程的控制。

優(yōu)點

  • 裝飾器是繼承的有力補充,比繼承靈活,在不改變原有對象的情況下,動態(tài)地給一個對象擴展功能,即插即用。
  • 通過使用不同裝飾類及這些裝飾類的排列組合,可以實現(xiàn)不同效果。
  • 裝飾器模式完全遵守開閉原則。

缺點

  • 會出現(xiàn)更多的代碼、更多的類,增加程序的復(fù)雜性。
  • 動態(tài)裝飾在多層裝飾時會更復(fù)雜。

The above is the detailed content of 3 years of work essential decorator mode. For more information, please follow other related articles on the PHP Chinese website!

Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn

Hot AI Tools

Undress AI Tool

Undress AI Tool

Undress images for free

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Clothoff.io

Clothoff.io

AI clothes remover

Video Face Swap

Video Face Swap

Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Tools

Notepad++7.3.1

Notepad++7.3.1

Easy-to-use and free code editor

SublimeText3 Chinese version

SublimeText3 Chinese version

Chinese version, very easy to use

Zend Studio 13.0.1

Zend Studio 13.0.1

Powerful PHP integrated development environment

Dreamweaver CS6

Dreamweaver CS6

Visual web development tools

SublimeText3 Mac version

SublimeText3 Mac version

God-level code editing software (SublimeText3)

Difference between HashMap and Hashtable? Difference between HashMap and Hashtable? Jun 24, 2025 pm 09:41 PM

The difference between HashMap and Hashtable is mainly reflected in thread safety, null value support and performance. 1. In terms of thread safety, Hashtable is thread-safe, and its methods are mostly synchronous methods, while HashMap does not perform synchronization processing, which is not thread-safe; 2. In terms of null value support, HashMap allows one null key and multiple null values, while Hashtable does not allow null keys or values, otherwise a NullPointerException will be thrown; 3. In terms of performance, HashMap is more efficient because there is no synchronization mechanism, and Hashtable has a low locking performance for each operation. It is recommended to use ConcurrentHashMap instead.

Why do we need wrapper classes? Why do we need wrapper classes? Jun 28, 2025 am 01:01 AM

Java uses wrapper classes because basic data types cannot directly participate in object-oriented operations, and object forms are often required in actual needs; 1. Collection classes can only store objects, such as Lists use automatic boxing to store numerical values; 2. Generics do not support basic types, and packaging classes must be used as type parameters; 3. Packaging classes can represent null values ??to distinguish unset or missing data; 4. Packaging classes provide practical methods such as string conversion to facilitate data parsing and processing, so in scenarios where these characteristics are needed, packaging classes are indispensable.

What are static methods in interfaces? What are static methods in interfaces? Jun 24, 2025 pm 10:57 PM

StaticmethodsininterfaceswereintroducedinJava8toallowutilityfunctionswithintheinterfaceitself.BeforeJava8,suchfunctionsrequiredseparatehelperclasses,leadingtodisorganizedcode.Now,staticmethodsprovidethreekeybenefits:1)theyenableutilitymethodsdirectly

How does JIT compiler optimize code? How does JIT compiler optimize code? Jun 24, 2025 pm 10:45 PM

The JIT compiler optimizes code through four methods: method inline, hot spot detection and compilation, type speculation and devirtualization, and redundant operation elimination. 1. Method inline reduces call overhead and inserts frequently called small methods directly into the call; 2. Hot spot detection and high-frequency code execution and centrally optimize it to save resources; 3. Type speculation collects runtime type information to achieve devirtualization calls, improving efficiency; 4. Redundant operations eliminate useless calculations and inspections based on operational data deletion, enhancing performance.

What is an instance initializer block? What is an instance initializer block? Jun 25, 2025 pm 12:21 PM

Instance initialization blocks are used in Java to run initialization logic when creating objects, which are executed before the constructor. It is suitable for scenarios where multiple constructors share initialization code, complex field initialization, or anonymous class initialization scenarios. Unlike static initialization blocks, it is executed every time it is instantiated, while static initialization blocks only run once when the class is loaded.

What is the `final` keyword for variables? What is the `final` keyword for variables? Jun 24, 2025 pm 07:29 PM

InJava,thefinalkeywordpreventsavariable’svaluefrombeingchangedafterassignment,butitsbehaviordiffersforprimitivesandobjectreferences.Forprimitivevariables,finalmakesthevalueconstant,asinfinalintMAX_SPEED=100;wherereassignmentcausesanerror.Forobjectref

What is the Factory pattern? What is the Factory pattern? Jun 24, 2025 pm 11:29 PM

Factory mode is used to encapsulate object creation logic, making the code more flexible, easy to maintain, and loosely coupled. The core answer is: by centrally managing object creation logic, hiding implementation details, and supporting the creation of multiple related objects. The specific description is as follows: the factory mode handes object creation to a special factory class or method for processing, avoiding the use of newClass() directly; it is suitable for scenarios where multiple types of related objects are created, creation logic may change, and implementation details need to be hidden; for example, in the payment processor, Stripe, PayPal and other instances are created through factories; its implementation includes the object returned by the factory class based on input parameters, and all objects realize a common interface; common variants include simple factories, factory methods and abstract factories, which are suitable for different complexities.

What is type casting? What is type casting? Jun 24, 2025 pm 11:09 PM

There are two types of conversion: implicit and explicit. 1. Implicit conversion occurs automatically, such as converting int to double; 2. Explicit conversion requires manual operation, such as using (int)myDouble. A case where type conversion is required includes processing user input, mathematical operations, or passing different types of values ??between functions. Issues that need to be noted are: turning floating-point numbers into integers will truncate the fractional part, turning large types into small types may lead to data loss, and some languages ??do not allow direct conversion of specific types. A proper understanding of language conversion rules helps avoid errors.

See all articles