高频变压器_变压器图案
高頻變壓器
Transformer模式是Java(以及可能僅具有使用場所差異和不變參數類型的其他OO語言)的設計模式,可幫助子類型層次結構內的對象將自己流暢地轉換為任何類型的對象。
語境
我一直在關注與Jim Laskey發行的JDK-8203703有關的OpenJDK線程( 9月18-21日 , 11月12-13日, 11月13-30日, 12月3-4日 ),然后我想到了一個主意。 讓我回顧一下討論的相關部分。
String.transform的建議
根據JDK-8203703的提案可歸結為以下新增內容:
public final class String implements /*...*/ CharSequence {// ...public <R> R transform(Function<? super String, ? extends R> f) {return f.apply(this);}// ... }如您所見,此方法本身僅調用給定的Function即可。 但是,它對于鏈接實用程序方法非常有用,例如Apache Commons的 StringUtils中的方法:
String result = string.toLowerCase().transform(StringUtils::stripAccents).transform(StringUtils::capitalize);通常,我們必須寫:
String result = StringUtils.capitalize(StringUtils.stripAccents(string.toLowerCase()));考慮CharSequence.transform
在某個時候,艾倫·貝特曼(Alan Bateman) 提出了 transform CharSequence中的transform定義為以下問題:
<R> R transform(Function<? super CharSequence, ? extends R> f)這將具有能夠在任何CharSequence上應用基于CharSequence的實用程序方法(例如StringUtils.isNumeric )的好處,例如:
boolean isNumeric = charSequence.transform(s -> StringUtils.defaultIfBlank('0')).transform(StringUtils::isNumeric);但是,正如RémiForax 指出的那樣 ,此簽名的問題在于:
- 如果它是由String 繼承的:大多數實用程序方法都將String作為參數–這樣的方法將不起作用(例如StringUtils :: capitalize ),
- 如果它被String 覆蓋 :由于以下原因,無法進行有用的覆蓋:
- Function<? super String, R>
結果, CharSequence.transform的主題已被刪除。
問題
綜上所述,問題在于能夠進行轉換 :
- 一個CharSequence ,使用Function即需要CharSequence或Object ( ? super CharSequence ),
- 一個String ,使用接受String或其任何父類型( ? super String )的Function 。
當我在這里查看這些下 限時 ,我意識到我已經看到了這種問題(參見Filterer Pattern )。
因此,這個問題歸結為:如何協變地指定Function的反 變界。
解
Java不支持逆變參數類型 ,并且其語法也不提供在單個聲明中協變( ? extends )指定逆變( ? super )綁定的方法。 然而,有可能做到這一點在兩個分開的宣言,通過中間輔助類型的裝置。
假設我們要為泛型Function<? super T, ? extends R> Function<? super T, ? extends R> Function<? super T, ? extends R> ,我們需要:
- 將上面的Function參數移動到參數為T的輔助接口中 ,
- 將此輔助接口與上限 ( ? extends T )一起用作返回類型。
變壓器接口
我定義了這樣的幫助程序接口(我稱之為Transformer ),如下所示:
@FunctionalInterface interface Transformer<T> {<R> R by(Function<? super T, ? extends R> f); }可轉換的接口
定義了Transformer ,我們可以定義以下稱為Transformable基本接口:
interface Transformable {Transformer<?> transformed(); }該接口本身并不能做很多事情,但我將其視為以下方面的規范 :
- 子類型實現器 :提醒他們使用適當的上限覆蓋已transformed方法,并加以實現,
- 子類型用戶 :提醒他們可以調用transformed().by(f) 。
總結起來,這對( Transformer & Transformable )讓我們替換:
- obj.transform(function)
- 使用: obj.transformed().by(function)
樣例實施
回到String之前,讓我們看看實現這兩個接口有多么容易:
class Sample implements Transformable {@Overridepublic Transformer<Sample> transformed() {return this::transform; // method reference}private <R> R transform(Function<? super Sample, ? extends R> f) {return f.apply(this);} }如您所見,所需要的只是對transform的方法引用 。
transform方法被設為私有,因此當子類型定義自己的(適當地, 下界 ) transform時,它們之間不會發生沖突。
上下文中的解決方案
上下文中的實現
它如何應用于CharSequence和String ? 首先,我們將CharSequence擴展為Transformable :
public interface CharSequence extends Transformable {// ...@OverrideTransformer<? extends CharSequence> transformed();// ... }然后,我們transformed在String實現transformed ,返回對public transform方法( 在JDK 12中添加 )的方法引用:
public final class String implements /*...*/ CharSequence {// ...@Overridepublic Transformer<String> transformed() {return this::transform;}// ... }請注意,我們對transformed的返回類型進行了協變更改: Transformer<? extends CharSequence> Transformer<? extends CharSequence> → Transformer<String> 。
相容性風險
我認為添加CharSequence.transformed的兼容性風險很小。 僅對于那些已經具有無參數transformed方法的CharSequence子類,這可能會破壞向后兼容性(這似乎不太可能)。
上下文中的用法
對于使用String不會改變,因為有呼吁沒有一點transformed().by()在transform()
但是,通用CharSequence的用法將需要訴諸transformed().by()因為它可能有許多實現,因此transform方法必須是private :
boolean isNumeric = charSequence.transformed().by(s -> StringUtils.defaultIfBlank('0')).transformed().by(StringUtils::isNumeric);性能
如果您不熟悉JVM (最常表示HotSpot )及其JIT編譯器的工作方式,那么您可能會懷疑這種額外對象的明顯創建( Transformer in transformed )是否不會影響性能。
幸運的是,由于進行了轉義分析 *和標量替換 ,因此該對象永遠不會在堆上分配。 答案是:不,不會。
* 此Wikipedia條目包含錯誤的陳述:“ 因此,編譯器可以安全地在堆棧上分配兩個對象。 ”正如 AlekseyShipilёv解釋的那樣 ,Java不會在堆棧上分配整個對象。
基準測試
如果您需要證明,這里有一些基準(使用AlekseyShipilёv出色的JMH基準線束 )。 因為我不能(容易),添加必要的方法,以String ,我創建了一個簡單的包裝過String ,并實現了在它之上的標桿。
基準測試toLowerCase()操作:
- 在兩個字符串上:
- "no change" (無操作)
- "Some Change"
- 使用三種通話類型:
- 直接(基準)
- transform()
- transformed().by()
您可以在GitHub gist中找到此基準測試的完整源代碼。
結果如下(在Oracle JDK 8上運行,耗時50分鐘):
Benchmark (string) Mode Cnt Score Error UnitsTransformerBenchmark.baseline no change avgt 25 22,215 ± 0,054 ns/op TransformerBenchmark.transform no change avgt 25 22,540 ± 0,039 ns/op TransformerBenchmark.transformed no change avgt 25 22,565 ± 0,059 ns/opTransformerBenchmark.baseline Some Change avgt 25 63,122 ± 0,541 ns/op TransformerBenchmark.transform Some Change avgt 25 63,405 ± 0,196 ns/op TransformerBenchmark.transformed Some Change avgt 25 62,930 ± 0,209 ns/op如您所見,對于這兩個字符串,這三種調用類型之間沒有性能差異。
摘要
我意識到, Transformable可能過于“奢侈”,以致于無法真正將其納入JDK。 實際上,即使僅由CharSequence和String返回的Transformer也不值得。 這是因為對CharSequence的一元運算似乎并不常見(例如StringUtils僅包含少數幾個)。
但是,我發現“ Transformer和“ Transformable的基本概念很誘人。 因此,我希望您喜歡閱讀,并且在某些情況下會發現它很有用
翻譯自: https://www.javacodegeeks.com/2019/02/transformer-pattern.html
高頻變壓器
總結
以上是生活随笔為你收集整理的高频变压器_变压器图案的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 男朋友用英语怎么说 如何用英语表达男朋友
- 下一篇: 钉钉群里怎么不显示已读未读