Jadual Kandungan
#🎜🎜🎜🎜🎜 hiasan, ia kelihatan sangat hodoh, tetapi dengan sedikit hiasan, ia akan menjadi lebih cantik, dan anda boleh mandi, tidur, memasak, dan lain-lain, tetapi ia masih rumah pada dasarnya. Kereta pada asalnya adalah kenderaan untuk pengangkutan, tetapi Mary membesarkannya dan menaik taraf konfigurasinya, dan kemudian ia menjadi kereta mewah, tetapi pada dasarnya ia masih merupakan kenderaan untuk pengangkutan. " >Kes dalam hidup #🎜🎜🎜🎜🎜 hiasan, ia kelihatan sangat hodoh, tetapi dengan sedikit hiasan, ia akan menjadi lebih cantik, dan anda boleh mandi, tidur, memasak, dan lain-lain, tetapi ia masih rumah pada dasarnya. Kereta pada asalnya adalah kenderaan untuk pengangkutan, tetapi Mary membesarkannya dan menaik taraf konfigurasinya, dan kemudian ia menjadi kereta mewah, tetapi pada dasarnya ia masih merupakan kenderaan untuk pengangkutan.
#🎜🎜 🎜#" >#🎜🎜 🎜#
装饰器模式中的角色 " >装饰器模式中的角色
小结" >小结
实战 " >实战
大神们是怎么用的 " >大神们是怎么用的
JDK源码中" >JDK源码中
Spring源码中" >Spring源码中
Mybatis源码中" >Mybatis源码中
Rumah Java javaTutorial 3 tahun bekerja mod penghias penting

3 tahun bekerja mod penghias penting

Aug 28, 2023 pm 03:09 PM
Corak penghias


Okay, jom masuk topik kita Hari ini saya akan berkongsi dengan anda 装饰器模式 dalam corak reka bentuk. Gunakan kisah hidup yang sesuai dan senario projek sebenar untuk bercakap tentang corak reka bentuk, dan akhirnya meringkaskan corak reka bentuk dalam satu ayat.

Cerita

Bak kata pepatah lama: Lelaki bergantung pada pakaiannya dan kuda bergantung pada pelananya. Marilah kita membiasakan diri dengan latar belakang ayat ini:

Orang ramai bergantung pada pakaian, kuda bergantung pada pelana, dan anjing bergantung pada loceng untuk berlari dengan gembira Ia datang dari bab kesepuluh "Pavilion Wanghu" Shen Zijin: "Namun begitu , Buddha bergantung pada pakaian emas "Orang ramai bergantung pada pakaian, dan dandanan juga sangat penting Jilid 1 "Kata-Kata Abadi untuk Membangkitkan Dunia": "Dua pembesar daerah bersaing untuk anak yatim perkahwinan yang soleh:" Seperti kata pepatah: " Buddha berpakaian emas, orang berpakaian dalam pakaian, dan ramai orang di dunia mempunyai mata cetek." , hanya kulit, tiada tulang. '" Bak kata pepatah, orang dewasa bergantung pada pakaian dan kuda.

Kisah klasik ini mengingatkan saya pada corak reka bentuk: corak penghias.

Apakah corak penghias? Tolong dengar Lao Tian bercakap perlahan. . Dari segi menambah fungsi, corak penghias adalah lebih fleksibel daripada menjana subkelas dan merupakan corak reka bentuk struktur.

Bahasa Inggeris:

Lampirkan tanggungjawab tambahan pada objek secara dinamik mengekalkan antara muka yang sama.Penghias menyediakan alternatif yang fleksibel kepada subkelas untuk melanjutkan kefungsian Alternatif fleksibel (melanjutkan kefungsian objek asal) melampirkan kefungsian pada objek. Oleh itu, teras corak penghias adalah sambungan berfungsi. Gunakan corak penghias untuk memanjangkan kefungsian kelas secara telus dan dinamik.

Kes dalam hidup #🎜🎜🎜🎜🎜 hiasan, ia kelihatan sangat hodoh, tetapi dengan sedikit hiasan, ia akan menjadi lebih cantik, dan anda boleh mandi, tidur, memasak, dan lain-lain, tetapi ia masih rumah pada dasarnya. Kereta pada asalnya adalah kenderaan untuk pengangkutan, tetapi Mary membesarkannya dan menaik taraf konfigurasinya, dan kemudian ia menjadi kereta mewah, tetapi pada dasarnya ia masih merupakan kenderaan untuk pengangkutan.

Seorang gadis pada asalnya sangat biasa dan berpenampilan sederhana, tetapi selepas memakai solek dan memakai beberapa pakaian yang cantik, dia menjadi dewi di hati ramai orang.

Pendek kata, selepas beberapa hiasan, ia berbeza dan fungsinya dipertingkatkan.

Perlaksanaan kod sejagat corak penghias

#🎜🎜🎜🎜🎜🎜🎜🎜🎜 Untuk melaksanakannya, pengaturcara suka membuat demo dahulu dan kemudian mengkajinya perlahan-lahan.
//抽象组件
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("结束后搞点事");
    }
}
//测试
public class Client {
    public static void main(String[] args) {
        Component component = new ConcreteDecorator(new ConcreteComponent());
        component.operation();
    }
}
Hasil berjalan:
开始前搞点事
ConcreteComponent operation
结束后搞点事
Di atas ialah pelaksanaan kod umum corak penghias.

Rajah UML corak penghias

#🎜🎜 🎜#

3 tahun bekerja mod penghias pentingDapat dilihat dari perjalanan UML bahawa peranan

装饰器模式中的角色

  • 抽象组件(Component):可以是一个接口或者抽象类,充当被装饰类的原始对象,规定了被装饰对象的行为。
  • 具体组件(ConcreteComponent):实现/继承Component的一个具体对象,即被装饰对象。
  • 抽象装饰器(Decorator):通用的装饰ConcreteComponent的装饰器,其内部必然有一个属性指向Component;其实现一般是一个抽象类,主要为了让其子类按照其构造形式传入一个Component,这是强制的通用行为。如果系统中装饰逻辑单一,则并不需要实现许多装饰器,可以直接省略该类,而直接实现一个具体装饰器即可。
  • 具体装饰器(ConcreteDecorator):Decorator的具体实现类,理论上,每个ConcreteDecorator都扩展了Component对象的一种功能。

小结

装饰器模式角色分配符合设计模式的里氏替换原则、依赖倒置原则,从而使得其具备很强的扩展性,最终满足开闭原则。

装饰器模式的实现原理是,让装饰器实现与被装饰类(例如ConcreteComponent)相同的接口(例如Component),使得装饰器与被扩展类类型一致,并在构造函数中传入该接口对象,然后在实现这个接口的被包装类对象的现有功能上添加新功能。由于装饰器与被包装类属于同一类型(均为Component),且构造函数的参数为其实现接口类(Component),因此装饰器模式具备嵌套扩展功能,这样就能使用装饰器模式一层一层地对底层被包装类进行功能扩展了。

实战

在实际开发中,都会存在系统与系统之间的调用,假如说我们现在有个支付功能,现在一切都是没问题的,但是 我们此时需要对发起支付前的请求参数和支付后的相应参数。进行统一处理,原功能不变,只是在原功能上做了一点扩展(增强)。

老功能代码如下:

/**
 * @author 田先生
 * @date 2021-06-02
 *
 * 欢迎关注公众号:java后端技术全栈
 */
public interface IOrderPayService {
    String payment(Long orderId, BigDecimal amount);
}
public class OrderPayServiceImpl implements IOrderPayService {

    @Override
    public String payment(Long orderId, BigDecimal amount) {
        //先调用余额查询是否足够
        System.out.println("发起支付,订单号:" + orderId + ", 支付金额:" + amount.toString());
        //调用支付系统
        String result = "订单id=" + orderId + "支付完成";
        System.out.println("支付结果:" + result);
        return result;
    }
}
public class OrderClient {
    public static void main(String[] args) {
        IOrderPayService orderPayService = new OrderPayServiceImpl();
        orderPayService.payment(10001L,new BigDecimal("5000"));
    }
}

运行输出:

发起支付,订单号:10001, 支付金额:5000
支付结果:订单id=10001支付完成

新需求,需要把这些请求参数和相应结果进行单独搜集处理,此时为了不影响原有功能,于是我们可以对其进行功能增强。

/**
 * @author 田先生
 * @date 2021-06-02
 *
 * 欢迎关注公众号:java后端技术全栈
 */
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("把这个订单信息(发起支付)" + "订单id=" + orderId + "支付金额=" + amount.toString() + " 【发送给MQ】");
        String result = orderPayService.payment(orderId, amount);
        System.out.println("把订单支付结果信息" + result + " 【发送给MQ】");
        return result;
    }
}
public class OrderClient {
    public static void main(String[] args) {
        IOrderPayService orderPayService =new OrderPayDecorator(new OrderPayServiceImpl());
        orderPayService.payment(10001L,new BigDecimal("5000"));
    }
}

运行输出:

把这个订单信息(发起支付)订单id=10001支付金额=5000 【发送给MQ】
发起支付,订单号:10001, 支付金额:5000
支付结果:订单id=10001支付完成
把订单支付结果信息订单id=10001支付完成 【发送给MQ】

整个过程,大家有没有发现,我们并没动原有的代码,仅仅只是做了功能增强。

装饰器模式在新项目中基本上不会用到,通常都是在老项目中使用,因为已有的功能不变,只是做了一些功能增强。

大神们是怎么用的

装饰器设计模式在JDK源码、Spring源码以及Mybatis源码中都有。

JDK源码中

装饰器模式比较经典的应用就是 JDK 中的 java.io 包下,InputStream、OuputStream、Reader、Writer 及它们的子类。

以 InputStream 为例

  • FileInputStream 是 InputStream 的子类,用来读取文件字节流
  • BufferedInputStream 是 InputStream 的子类的子类,可缓存的字节流
  • DataInputStream 也是 InputStream 的子类的子类,可直接读取 Java 基本类型的字节流

UML图

3 tahun bekerja mod penghias penting


DataInputStream 中构造器入参便是自己的父类(InputStream)。

3 tahun bekerja mod penghias penting

如果希望提供一个可以读取文件 + 可缓存的字节流,使用继承方式,就需要派生 FileBufferedInputStream;

如果希望提供一个可以读取文件 + 直接读取基本类型的字节流,使用继承方式,就需要派生 FileDataInputStream。

字节流功能的增强还包括支持管道 pipe、字节数组 bytearray、字节对象 object、字节流字符流的转换 等维度,如果用继承方式,那类的层级与种类会多到爆炸。

为了解决问题,这边就使用了装饰器模式。

Spring源码中

在Spring中,我们可以尝试理解一下TransactionAwareCacheDecorator类,这个类主要用来处理事务缓存,代码如下。

public class TransactionAwareCacheDecorator implements Cache {
    private final Cache targetCache;
    //构造方法入参类型为自己的父类(接口类型)
    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中关于Cache和CachingExecutor接口的实现类也使用了装饰者设计模式。Executor是MyBatis执行器,是MyBatis 调度的核心,负责SQL语句的生成和查询缓存的维护;CachingExecutor是一个Executor的装饰器,给一个Executor增加了缓存的功能。此时可以看做是对Executor类的一个增强,故使用装饰器模式是合适的。

在CachingExecutor 中

public class CachingExecutor implements Executor {
  //持有组件对象
  private Executor delegate;
  private TransactionalCacheManager tcm = new TransactionalCacheManager();
    //构造方法,传入组件对象
  public CachingExecutor(Executor delegate) {
    this.delegate = delegate;
    delegate.setExecutorWrapper(this);
  }
  @Override
  public int update(MappedStatement ms, Object parameterObject) throws SQLException {
      //转发请求给组件对象,可以在转发前后执行一些附加动作
    flushCacheIfRequired(ms);
    return delegate.update(ms, parameterObject);
  }
  //...
 }

总结

看完装饰器模式后,你是否有感觉,装饰器模式和代理模式非常的相像,下面我们就来做个对比。

1.装饰器模式可以理解为一种特殊的代理模式。

2.装饰器模式强调自身的功能扩展,透明的扩展(即用户想增强什么功能就增强什么功能),可动态定制的扩展。

3.代理模式强调的是代理过程的控制。

优点

  • 装饰器是继承的有力补充,比继承灵活,在不改变原有对象的情况下,动态地给一个对象扩展功能,即插即用。
  • 通过使用不同装饰类及这些装饰类的排列组合,可以实现不同效果。
  • 装饰器模式完全遵守开闭原则。

缺点

  • 会出现更多的代码、更多的类,增加程序的复杂性。
  • 动态装饰在多层装饰时会更复杂。

Atas ialah kandungan terperinci 3 tahun bekerja mod penghias penting. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn

Alat AI Hot

Undress AI Tool

Undress AI Tool

Gambar buka pakaian secara percuma

Undresser.AI Undress

Undresser.AI Undress

Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover

AI Clothes Remover

Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Clothoff.io

Clothoff.io

Penyingkiran pakaian AI

Video Face Swap

Video Face Swap

Tukar muka dalam mana-mana video dengan mudah menggunakan alat tukar muka AI percuma kami!

Alat panas

Notepad++7.3.1

Notepad++7.3.1

Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina

SublimeText3 versi Cina

Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1

Hantar Studio 13.0.1

Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6

Dreamweaver CS6

Alat pembangunan web visual

SublimeText3 versi Mac

SublimeText3 versi Mac

Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

Apakah jenis `enum` di Java? Apakah jenis `enum` di Java? Jul 02, 2025 am 01:31 AM

Enums di Java adalah kelas khas yang mewakili bilangan tetap nilai tetap. 1. Gunakan definisi kata kunci enum; 2. Setiap nilai enum adalah contoh akhir statik awam jenis enum; 3. Ia boleh termasuk bidang, pembina dan kaedah untuk menambah tingkah laku kepada setiap pemalar; 4. Ia boleh digunakan dalam pernyataan suis, menyokong perbandingan langsung, dan menyediakan kaedah terbina dalam seperti nama (), ordinal (), nilai () dan nilai (); 5. Penghitungan boleh meningkatkan jenis keselamatan, kebolehbacaan dan fleksibiliti kod, dan sesuai untuk senario pengumpulan terhad seperti kod status, warna atau minggu.

Apakah prinsip pemisahan antara muka? Apakah prinsip pemisahan antara muka? Jul 02, 2025 am 01:24 AM

Prinsip pengasingan antara muka (ISP) menghendaki pelanggan tidak bergantung pada antara muka yang tidak digunakan. Inti adalah untuk menggantikan antara muka yang besar dan lengkap dengan pelbagai antara muka kecil dan halus. Pelanggaran prinsip ini termasuk: Pengecualian yang tidak diletakkan dilemparkan apabila kelas melaksanakan antara muka, sebilangan besar kaedah tidak sah dilaksanakan, dan fungsi yang tidak relevan secara paksa diklasifikasikan ke antara muka yang sama. Kaedah permohonan termasuk: membahagikan antara muka mengikut kaedah biasa, menggunakan antara muka berpecah mengikut pelanggan, dan menggunakan kombinasi dan bukannya pelaksanaan pelbagai antara muka jika perlu. Sebagai contoh, perpecahan antara muka mesin yang mengandungi kaedah percetakan, pengimbasan, dan faks ke dalam pencetak, pengimbas, dan faxmachine. Peraturan boleh dilonggarkan dengan sewajarnya apabila menggunakan semua kaedah pada projek kecil atau semua pelanggan.

Teknik Pengaturcaraan Asynchronous di Java Moden Teknik Pengaturcaraan Asynchronous di Java Moden Jul 07, 2025 am 02:24 AM

Java menyokong pengaturcaraan asynchronous termasuk penggunaan aliran yang boleh diselesaikan, aliran responsif (seperti ProjectReactor), dan benang maya di Java19. 1.CompletableFuture meningkatkan kebolehbacaan dan penyelenggaraan kod melalui panggilan rantai, dan menyokong orkestrasi tugas dan pengendalian pengecualian; 2. ProjectReactor menyediakan jenis mono dan fluks untuk melaksanakan pengaturcaraan responsif, dengan mekanisme tekanan belakang dan pengendali yang kaya; 3. Thread maya mengurangkan kos konvensional, sesuai untuk tugas I/O-intensif, dan lebih ringan dan lebih mudah untuk berkembang daripada benang platform tradisional. Setiap kaedah mempunyai senario yang berkenaan, dan alat yang sesuai harus dipilih mengikut keperluan anda dan model campuran harus dielakkan untuk mengekalkan kesederhanaan

Perbezaan antara boleh dipanggil dan boleh dijalankan di Java Perbezaan antara boleh dipanggil dan boleh dijalankan di Java Jul 04, 2025 am 02:50 AM

Terdapat tiga perbezaan utama antara yang boleh dipanggil dan boleh dijalankan di Jawa. Pertama, kaedah yang boleh dipanggil boleh mengembalikan hasilnya, sesuai untuk tugas -tugas yang perlu mengembalikan nilai, seperti yang boleh dipanggil; Walaupun kaedah run () runnable tidak mempunyai nilai pulangan, sesuai untuk tugas -tugas yang tidak perlu kembali, seperti pembalakan. Kedua, Callable membolehkan untuk membuang pengecualian yang diperiksa untuk memudahkan penghantaran ralat; Walaupun Runnable mesti mengendalikan pengecualian secara dalaman. Ketiga, Runnable boleh dihantar secara langsung ke benang atau executorservice, sementara yang boleh dipanggil hanya boleh dikemukakan ke executorservice dan mengembalikan objek masa depan untuk

Amalan terbaik untuk menggunakan enum di java Amalan terbaik untuk menggunakan enum di java Jul 07, 2025 am 02:35 AM

Di Java, enums sesuai untuk mewakili set tetap tetap. Amalan terbaik termasuk: 1. Gunakan enum untuk mewakili keadaan tetap atau pilihan untuk meningkatkan keselamatan jenis dan kebolehbacaan; 2. Tambah sifat dan kaedah untuk meningkatkan fleksibiliti, seperti menentukan bidang, pembina, kaedah penolong, dan lain -lain; 3. Gunakan enummap dan enumset untuk meningkatkan prestasi dan jenis keselamatan kerana mereka lebih cekap berdasarkan tatasusunan; 4. Elakkan penyalahgunaan enum, seperti nilai dinamik, perubahan kerap atau senario logik kompleks, yang harus digantikan dengan kaedah lain. Penggunaan enum yang betul boleh meningkatkan kualiti kod dan mengurangkan kesilapan, tetapi anda perlu memberi perhatian kepada sempadannya yang berkenaan.

Memahami Java Nio dan kelebihannya Memahami Java Nio dan kelebihannya Jul 08, 2025 am 02:55 AM

Javanio adalah IOAPI baru yang diperkenalkan oleh Java 1.4. 1) bertujuan untuk penampan dan saluran, 2) mengandungi komponen teras penampan, saluran dan pemilih, 3) menyokong mod tidak menyekat, dan 4) mengendalikan sambungan serentak lebih cekap daripada IO tradisional. Kelebihannya dicerminkan dalam: 1) IO yang tidak menyekat mengurangkan overhead thread, 2) Buffer meningkatkan kecekapan penghantaran data, 3) pemilih menyedari multiplexing, dan 4) memori pemetaan memori sehingga membaca dan menulis fail. Nota Apabila menggunakan: 1) Operasi flip/jelas penampan mudah dikelirukan, 2) Data yang tidak lengkap perlu diproses secara manual tanpa menyekat, 3) Pendaftaran pemilih mesti dibatalkan dalam masa, 4) NIO tidak sesuai untuk semua senario.

Bagaimana Pemuat Kelas Java Berfungsi Secara Dalaman Bagaimana Pemuat Kelas Java Berfungsi Secara Dalaman Jul 06, 2025 am 02:53 AM

Mekanisme pemuatan kelas Java dilaksanakan melalui kelas, dan aliran kerja terasnya dibahagikan kepada tiga peringkat: memuatkan, menghubungkan dan memulakan. Semasa fasa pemuatan, kelas muat turun secara dinamik membaca bytecode kelas dan mencipta objek kelas; Pautan termasuk mengesahkan ketepatan kelas, memperuntukkan memori kepada pembolehubah statik, dan rujukan simbol parsing; Inisialisasi melakukan blok kod statik dan tugasan pembolehubah statik. Pemuatan kelas mengamalkan model delegasi induk, dan mengutamakan loader kelas induk untuk mencari kelas, dan cuba bootstrap, lanjutan, dan appliclassloader pada gilirannya untuk memastikan perpustakaan kelas teras selamat dan mengelakkan pemuatan pendua. Pemaju boleh menyesuaikan kelas, seperti UrlClassl

Meneroka mekanisme penyegerakan yang berbeza di Java Meneroka mekanisme penyegerakan yang berbeza di Java Jul 04, 2025 am 02:53 AM

JavaprovidesmultiplesynchronizationToolsforthreadsafety.1.SynchronizedBlockSensensureMutualExclusionByLockingMethodsorspecificcodesections.2.reentrantlockoffersadvancedControl, termasuktrylockandfairnesspolicies.condition

See all articles