21世纪的设计模式:适配器模式
這是我的演講“ 21世紀(jì)的設(shè)計(jì)模式”的第三部分。
適配器模式橋接世界。 在一個(gè)世界中,我們有一個(gè)概念的界面。 在另一個(gè)世界,我們有不同的界面。 這兩個(gè)接口有不同的用途,但有時(shí)我們需要進(jìn)行轉(zhuǎn)移。 在一個(gè)編寫(xiě)良好的世界中,我們可以使用適配器使遵循一種協(xié)議的對(duì)象遵守另一種協(xié)議。
適配器模式有兩種。 我們不會(huì)談?wù)撨@個(gè):
interface Fire {<T> Burnt<T> burn(T thing); }interface Oven {Food cook(Food food); }class WoodFire implements Fire { ... }class MakeshiftOven extends WoodFire implements Oven {@Override public Food cook(Food food) {Burnt<Food> noms = burn(food);return noms.scrapeOffBurntBits();} }這種形式( 類Adapter模式)使我感到驚訝,因?yàn)閑xtends給了我希比(heebie)jeebies。 為什么不在本文的討論范圍之內(nèi)? 隨時(shí)問(wèn)我,我會(huì)很樂(lè)意談?wù)撃愕亩?#xff08;可能是你的鼻子)。
取而代之的是讓我們談?wù)搶?duì)象適配器模式 ,該模式通常被認(rèn)為在所有方面都更加有用和靈活。
讓我們看一下相同的類,遵循以下替代方法:
class MakeshiftOven implements Oven {private final Fire fire;public MakeshiftOven(Fire fire) {this.fire = fire;}@Override public Food cook(Food food) {Burnt<Food> noms = fire.burn(food);return noms.scrapeOffBurntBits();} }我們將像這樣使用它:
Oven oven = new MakeshiftOven(fire); Food bakedPie = oven.cook(pie);該模式通常遵循以下簡(jiǎn)單結(jié)構(gòu):
很好,對(duì)嗎?
是。 有點(diǎn)。 我們可以做得更好。
我們已經(jīng)有一個(gè)關(guān)于Fire的引用,因此構(gòu)造另一個(gè)對(duì)象來(lái)玩它似乎有點(diǎn)…過(guò)大了。 該對(duì)象實(shí)現(xiàn)了Oven 。 其中有一個(gè)抽象方法 。 我在這里看到一種趨勢(shì)。
相反,我們可以創(chuàng)建一個(gè)功能相同的函數(shù)。
Oven oven = food -> fire.burn(food).scrapeOffBurntBits(); Food bakedPie = oven.cook(pie);我們可以再進(jìn)一步編寫(xiě)方法引用,但實(shí)際上情況更糟。
// Do *not* do this. Function<Food, Burnt<Food>> burn = fire::burn; Function<Food, Food> cook = burn.andThen(Burnt::scrapeOffBurntBits); Oven oven = cook::apply; Food bakedPie = oven.cook(pie);這是因?yàn)镴ava不能在功能接口之間進(jìn)行隱式轉(zhuǎn)換,因此我們需要為它提供有關(guān)操作的每個(gè)階段的提示。 另一方面,Lambda對(duì)于具有正確類型的任何函數(shù)接口都是隱式強(qiáng)制的,并且編譯器在弄清楚如何做到這一點(diǎn)方面做得很好。
我們的新UML圖將如下所示:
通常,我們真正需要的只是方法參考。 例如,使用Executor界面。
package java.util.concurrent;/*** An object that executes submitted {@link Runnable} tasks.*/ public interface Executor {void execute(Runnable command); }它消耗了Runnable對(duì)象,這是一個(gè)非常有用的界面。
現(xiàn)在,我們將其中一個(gè)和一堆Runnable任務(wù)保存在Stream 。
Executor executor = ...; Stream<Runnable> tasks = ...;我們?nèi)绾卧趫?zhí)行Executor上執(zhí)行所有這些Executor ?
這行不通:
tasks.forEach(executor);事實(shí)證明, Stream 上的forEach方法確實(shí)需要使用方,但是它是一個(gè)非常特定的類型:
public interface Stream<T> {...void forEach(Consumer<? super T> action);... }Consumer看起來(lái)像這樣:
@FunctionalInterface public interface Consumer<T> {void accept(T t);... }乍一看,這似乎沒(méi)有什么幫助。 但是請(qǐng)注意, Consumer是一個(gè)功能接口,因此我們可以使用lambda真正輕松地指定它們。 這意味著我們可以這樣做:
tasks.forEach(task -> executor.execute(task));這可以進(jìn)一步簡(jiǎn)化:
tasks.forEach(executor::execute);Java 8使適配器變得非常簡(jiǎn)單,以至于我猶豫不再將它們稱為模式。 這個(gè)概念仍然非常重要。 通過(guò)顯式創(chuàng)建適配器,我們可以將這兩個(gè)世界分開(kāi),除了在定義的邊界點(diǎn)處。 的實(shí)現(xiàn),但是? 它們只是功能。
翻譯自: https://www.javacodegeeks.com/2015/04/design-patterns-in-the-21st-century-the-adapter-pattern.html
總結(jié)
以上是生活随笔為你收集整理的21世纪的设计模式:适配器模式的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: iphonedns设置(iphonedn
- 下一篇: 夏天当季蔬菜有哪些 夏天当季蔬菜介绍