除了邁騰帕薩特雅閣 20萬的B級車我們還能選什麼?

3{icon} {views}

99萬上汽大眾斯柯達 速派售價:16。98-27。68萬東風悅達起亞 K5售價:15。98-24。88萬總結:今天所介紹的這幾款中級車都各有特色,但卻是實力出眾的值得購買的車型。最新的C6作為雪鐵龍再次征戰中型車市場的車型,有着優雅大氣的外觀造型與寬敞的空間,配以較低的售價,整體還是很值得購買的。

目前SUV市場是很火,但作為傳統領域的中級車市場仍然保持以往的穩定;這是廠商努力穩住的細分市場;而這個級別當中有着眾多的車型可供選擇;但預算只有20萬的話要想購置一輛品質出眾的中級車還是有難度的,不過看完今天的推薦將會解除你的困惑。

廣汽豐田 凱美瑞

售價:18.48-32.98萬

東風雪鐵龍 C6

售價:18.99-27.99萬

上汽大眾斯柯達 速派

售價:16.98-27.68萬

東風悅達起亞 K5

售價:15.98-24.88萬

總結:今天所介紹的這幾款中級車都各有特色,但卻是實力出眾的值得購買的車型。

最新的C6作為雪鐵龍再次征戰中型車市場的車型,有着優雅大氣的外觀造型與寬敞的空間,配以較低的售價,整體還是很值得購買的。

現款速派已經上市了一段時間,整體外觀造型年輕了不少,出自MQB平台的產品,整體的做工精良,相比邁騰價格更低,除了品牌力差一些之外,其實是一款出眾的車型。

K5當年可謂是一時風頭,只是太過於犀利的外觀造型使得它比較適合年輕消費者,但偏低的起步價使得擁有一輛的中級車的門檻降低了很多。

凱美瑞作為這個級別長年的領跑者,在性價比、可靠性和實際體驗上都沒有明顯的短板,可以說誰選都不會錯的大眾情人,同時遇上網約車新規的出台,就如為凱美瑞定製一般,在跑滴滴方面有着特別的優勢。本站聲明:網站內容來源於http://www.auto6s.com/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!

※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※教你寫出一流的銷售文案?

※別再煩惱如何寫文案,掌握八大原則!

提車后六大惡俗習慣 老實交代你有沒有上榜…

1{icon} {views}

時常看到日系車車尾貼着壁虎,難道在庇護不要被…。(大家自行腦補吧)。第三、放鞭炮放鞭炮寓意着有好事到來,在4S店提車的時候,提車儀式時銷售通常會為客戶提車而燒串鞭炮賀一賀,滿地紅看着心情都開心一點。燒鞭炮同樣是好事,不過好事千萬就不要醞釀成壞事了。

也是農村長大的娃,不論是很久之前還是現在,這樣的情況還是會經常遇到的。拒絕吧,可能令家裡的老人不開心;接受吧,又怕太彆扭,不小心還會對新車造成損害。

全國各地的風俗習慣都不同,買新車之後老百姓們會有不同的慶祝方式。下面我們來看看,你中招了嗎?

第一、系紅繩

紅繩一般都是4S店為新車客戶而準備的,按照風俗習慣來說,紅色代表吉利、喜慶,而且可以避邪,所以很多車主都願意去為新車繫上紅繩,代表好意頭,為自己的平安出行作禱告。

系紅繩是好事,不過我們也要注意系紅繩的方式。一般來說紅繩系在後視鏡即可,而且不能太長太寬,不然行車過程中紅繩可能會影響后視鏡的視野,特別是雨天大風天氣。另一方面就是,紅繩的質量不好,可能會掉色,假若顏色粘在車身上,你肯定是極為不樂意的。同樣,不建議將紅繩綁在輪圈上,而且系紅繩的時間避免過長。

第二、“壁虎”車標

不少朋友上老司機的車,經常會遇到問為什麼前面的車後面貼着一隻壁虎的事情,通常都笑答說這是為了好看,其實真正的含義是什麼呢?

“壁虎”“庇護”,你沒想錯,也可以理解為“避禍”的意思,同樣是圖個吉利意頭。另外,其實壁虎也是奧迪Quattro全時四驅系統的Logo,不過現在很少奧迪會有這些裝飾了。時常看到日系車車尾貼着壁虎,難道在庇護不要被….(大家自行腦補吧)。

第三、放鞭炮

放鞭炮寓意着有好事到來,在4S店提車的時候,提車儀式時銷售通常會為客戶提車而燒串鞭炮賀一賀,滿地紅看着心情都開心一點。

燒鞭炮同樣是好事,不過好事千萬就不要醞釀成壞事了。不少新聞報道,客戶提車回家,因放炮而把新車炸得面目全非,眼睜睜看着自己辛勤勞動而得來的成果瞬間化為烏有,心疼啊有木有!這是多痛的領悟啊!放鞭炮是好事,不過千萬別把自己的車給炸了!

第四、祭拜汽車

老實說,買車提車放鞭炮就算了,但如果說要祭拜、開光汽車,是真的不建議,而且我真系接受唔到咯!

買新車回家通常不是自己一個人的事兒了,老一輩估計都會給新車祭拜一下,燒香蠟燭的是常事了,如果家裡老一輩的人要求,也不會太強硬地去拒絕,畢竟老人家也是為了往後孩子們的出入平安,並沒有錯。找法師幫汽車開光,雖說存在這樣的事情,但也沒真實見過,很多人都表示,聽過擇日提車而沒有聽過為汽車開光之事…

第五、車內掛件擺佛像

前段時間從西藏的活動歸來,也體驗到了那邊西域的風俗文化,他們本地居民的汽車大多車內都擺有佛像以及不同顏色哈達,可見西藏的文化是隨處可見的。

而在南方大多車主們也就擺香水或者公仔在中控台上,並沒有那麼雜亂,對了,還有擺車模的(注意是汽車模型,不是美女車模..)。雖說這些擺件確實漂亮好看有寓意,但是對於行車安全來說還是有一定的隱患的,車輛發生碰撞時擺件可能會脫落對車內人員造成不同程度的傷害,所以擺件一定要固定好!另外,建議擺件不擺就不擺,在中后視鏡掛上一个中國結圖意頭還是不錯的選擇。

第六、貼春聯

汽車貼春聯貌似現在不多見了,或許是孤陋寡聞?

同樣,汽車貼春聯也是圖個好意頭,本身是好事,不過貼這麼耀眼的春聯,不知道交警會怎樣想,雖說沒有明文規定是否合法,畢竟這樣做也是會影響到行車安全,萬一春聯在行車中脫離,無論是影響到自己的車輛還是後車的視野,都是十分危險的!

總結:

常話說,對於傳統文化或是風俗習慣,我們不能全部否定,要取其精華棄其糟粕。各地方民族的風俗習慣都不一樣,我們不要去破壞或是貶低,畢竟風俗習慣是前人所留下給我們子孫的。對於汽車的風俗習慣,大家看了的分析,也清楚到了不少是對行車安全有影響的,所以大家一定要千萬注意,不要為了討平安而過於盲目了。本站聲明:網站內容來源於http://www.auto6s.com/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

台北網頁設計公司這麼多該如何選擇?

※智慧手機時代的來臨,RWD網頁設計為架站首選

※評比南投搬家公司費用收費行情懶人包大公開

※回頭車貨運收費標準

網頁設計最專業,超強功能平台可客製化

※別再煩惱如何寫文案,掌握八大原則!

ASP.NET Core Blazor Webassembly 之 路由

2{icon} {views}

web最精妙的設計就是通過url把多個頁面串聯起來,並且可以互相跳轉。我們開發系統的時候總是需要使用路由來實現頁面間的跳轉。傳統的web開發主要是使用a標籤或者是服務端redirect來跳轉。那今天來看看Blazor是如何進行路由的。

使用@page指定組件的路由path

我們可以在Blazor里給每個組件指定一個path,當路由匹配的時候會显示這個組件。

@page "/page/a"

 <h2>
     PAGE A
 </h2>

@code {
 
}

訪問/page/a 看到Page A頁面被渲染出來了。

注意:如果是在瀏覽器里敲入url按回車切換頁面,會發生一次http請求,然後重新渲染blazor應用。

使用a標籤進行頁面跳轉

a標籤作為超鏈接是我們web開發最常用的跳轉方式,blazor同樣支持。
新建Page B

@page "/page/b"

 <h2>
     PAGE B
 </h2>

@code {
 
}

在Page A頁面添加一個a標籤進行跳轉:

@page "/page/a"

 <h2>
     PAGE A
 </h2>
<p>
    <a href="/page/b">Page B</a>
</p>

@code {
 
}

運行一下試試:

注意:使用a連接在頁面間進行跳轉不會發生http請求到後台,頁面是直接在前端渲染出來的。

通過路由傳參

通過http的url進行頁面間傳參是我們web開發的常規操作。下面我們演示下如何從Page A傳遞一個參數到Page B。我們預設Page A裏面有個UserName需要傳遞到Page B,並且显示出來。

通過path傳參

通過url傳參一般有兩種方式,一種是直接把參數組合在path里,比如“/page/b/小明”這樣。

修改Page A:

@page "/page/a"

 <h2>
     PAGE A
 </h2>
<p>
    <a href="/page/b/@userName">Page B</a>
</p>

@code {
    private string userName = "小明";
}

通過把userName組合到path上傳遞給Page B。

修改Page B:

@page "/page/b/{userName}"

 <h2>
     PAGE B
 </h2>
<p>
    userName: @userName
</p>

@code {
    [Parameter]
    public string userName { get; set; }
}

Page B 使用一個“/page/b/{userName}” pattern來匹配userName,並且userName需要標記[Parameter]並且設置為public。

通過QueryString傳參

除了把參數直接拼接在path里,我們還習慣通過QueryString方式傳遞,比如“/page/b?username=小明”。

修改Page A:

@page "/page/a"

<h2>
    PAGE A
</h2>
<p>
    <a href="/page/b?username=@userName">Page B</a>
</p>

@code {
    private string userName = "小明";
}

首先安裝一個工具庫:

Install-Package Microsoft.AspNetCore.WebUtilities -Version 2.2.0

修改Page B:

@page "/page/b"

<h2>
    PAGE B
</h2>
<p>
    userName: @UserName
</p>

@using Microsoft.AspNetCore.WebUtilities;

@inject NavigationManager NavigationManager;

@code {
    [Parameter]
    public string UserName { get; set; }


    protected override void OnInitialized()
    {
        var uri = NavigationManager.ToAbsoluteUri(NavigationManager.Uri);
        QueryHelpers.ParseQuery(uri.Query).TryGetValue("username", out Microsoft.Extensions.Primitives.StringValues userName);
        Console.WriteLine(NavigationManager.Uri);
        UserName = userName.ToString();
        Console.WriteLine(UserName);

        base.OnInitialized();
    }
}

頁面獲取QueryString的傳參比較麻煩,Blazor並沒有進行封裝。所以我們需要通過QueryHelpers.ParseQuery方法手工把QueryString格式化成字典形式,然後獲取對應的參數。QueryHelpers類存在Microsoft.AspNetCore.WebUtilities這個庫里,需要通過nuget安裝。

NavLink

NavLink是個導航組件,它其實就是封裝了a標籤。當選中的時候,也就是當前的url跟它的href一致的時候,會自動在class上加上active類,所以可以用來控制選中的樣式。默認的3個導航菜單就是用的NavLink。

比如導航到counter的NavLink:

   <NavLink class="nav-link" href="counter">
                <span class="oi oi-plus" aria-hidden="true"></span> Counter
    </NavLink>

最後翻譯成html:

<a href="counter" class="nav-link active">
                <span class="oi oi-plus" aria-hidden="true"></span> Counter
</a>

NavigationManager

有的時候我們可能需要在代碼里進行導航,如果是JavaScript我們會用window.location來切換頁面,Blazor為我們提供了相應的封裝:NavigationManager。使用NavigationManager可以通過代碼直接進行頁面間的跳轉。我們在Page A頁面放個按鈕然後通過按鈕的點擊事件進行跳轉:

@page "/page/a"

<h2>
    PAGE A
</h2>
<p>
   <button @onclick="GoToB">
       go to B
   </button>
</p>

@inject NavigationManager NavigationManager
@code {

    private void GoToB()
    {
        NavigationManager.NavigateTo("/page/b?username=小貓");
    }

}

修改Page A的代碼,注入NavigationManager對象,通過NavigationManager.NavigateTo方法進行跳轉。

擴展Back方法

Blazor封裝的NavigationManager咋一看以為跟WPF的NavigationService一樣,我想當然的覺得裏面肯定有個Back方法可以進行後退。但是查了一番發現還真的沒有,這就比較尷尬了,沒辦法只能使用JavaScript來實現了。

為了方便我們給NavigationManager直接寫個擴展方法吧。
首先修改Program把IServiceCollection暴露出來:

    public class Program
    {
        public static IServiceCollection Services;

        public static async Task Main(string[] args)
        {
            var builder = WebAssemblyHostBuilder.CreateDefault(args);
            builder.RootComponents.Add<App>("app");

            builder.Services.AddTransient(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });
            Services = builder.Services;

            await builder.Build().RunAsync();
        }
    }

擴展類:

  public static class Ext
    {
        public static void Back(this NavigationManager navigation)
        {
            var jsruntime = Program.Services.BuildServiceProvider().GetService<IJSRuntime>();
            jsruntime.InvokeVoidAsync("history.back");
        }
    }

這個擴展方法很簡單,從DI容器里獲取IJSRuntime的實例對象,通過它去調用JavaScript的history.back方法。

修改Page B:

@page "/page/b"

<h2>
    PAGE B
</h2>
<p>
    userName: @UserName
</p>
<p>
    <button @onclick="GoBack">
        Go back
    </button>
</p>

@using Microsoft.AspNetCore.WebUtilities;

@inject NavigationManager NavigationManager;

@code {
    [Parameter]
    public string UserName { get; set; }


    protected override void OnInitialized()
    {
        var uri = NavigationManager.ToAbsoluteUri(NavigationManager.Uri);
        QueryHelpers.ParseQuery(uri.Query).TryGetValue("username", out Microsoft.Extensions.Primitives.StringValues userName);
        Console.WriteLine(NavigationManager.Uri);
        UserName = userName.ToString();
        Console.WriteLine(UserName);

        base.OnInitialized();
    }

    private void GoBack()
    {
        NavigationManager.Back();
    }
}

在Page B頁面上添加一個按鈕,點擊調用NavigationManager.Back方法就能回到上一頁。

總結

到此Blazor路由的內容學習的差不多了,整體上沒有什麼特別的,就是NavigationManager只有前進方法沒有後退是比較讓我震驚的。

相關內容:

ASP.NET Core Blazor Webassembly 之 數據綁定
ASP.NET Core Blazor Webassembly 之 組件
ASP.NET Core Blazor 初探之 Blazor WebAssembly
ASP.NET Core Blazor 初探之 Blazor Server

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!

※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※教你寫出一流的銷售文案?

※別再煩惱如何寫文案,掌握八大原則!

世界上最著名的操作系統是用什麼語言編寫的?

5{icon} {views}

Unix 與 C 語言的關係

在服務器領域,最著名的系統莫過於Unix了,即便Linux也是類Unix的操作系統。Unix 是用 C 語言編寫的,而且是世界上第一個用 C 語言編寫的操作系統。但是 Unix 是怎麼產生的?C 語言又是怎麼產生的?Unix 為什麼要用 C 語言來編寫?相信看完這篇文章你很快就會有了答案。

 

Multics 和 Unix

1964年,在 Unix 誕生之前,美國貝爾實驗室、通用電氣、和麻省理工學院聯合開發了一個項目,叫做 Multics操作系統。Multics 在當時取得了巨大的成功,因為它給了人們一個真正可用並且很穩定的操作系統。當時從學校到政府機關,到處都在安裝 Multics。

 

但是時間到了 1969年,因為種種原因,貝爾實驗室的 Ken Thompson 和 Dennis Ritchie 決定放棄Multics,於是貝爾實驗室退出了這個項目。Ken Thompson 和 Dennis Ritchie 決定開發一個更為簡單並且高效的操作系統,並把它命名為 Unix,於是他們倆就成為了 Unix 之父。

 

和 Unix 相比,Multics 有兩個比較致命的缺點,一是需要安裝在非常昂貴的機器上,普通的計算機沒有辦法安裝。二是設計非常複雜,這也是貝爾實驗室的工程師退出的主要原因。不過 Ken Thompson 和 Dennis Ritchie 還是從 Multics 上得到很多啟發,可以說 Unix 是 Multics 的簡化以及更新。

 

說到這裏,C 語言還沒有出場,因為它在那個時候還沒有被發明出來。Unix 操作系統的第一個版本是純粹用彙編語言編寫出來的。一直到了 1974年,第四個版本才改用 C 語言進行開發。在講 C 語言之前,我們還不得不先說一下 BCPL 和 B 語言。

 

BCPL 與 B 語言

Ken Thompson 和 Dennis Ritchie 最初用彙編語言來開發 Unix,因為在那個時候,所有的操作系統都是用彙編語言來開發的。不過當時 Multics 是一個例外,Multics 項目組使用了 PL/1 來進行開發。它的價值就在於向世人展示了用一門高級語言也可以開發出一套操作系統。Ken Thompson 和 Dennis Ritchie 也受到了鼓舞,他們決定用彙編之外的語言重新開發 Unix。他們最初的選擇是 BCPL。BCPL 最早是由 Martin Richards 發明用來開發編譯器的語言。但是 Ken Thompson 和 Dennis Ritchie很快發現,如果他們想在小型計算機 DEC PDP-7 上使用 BCPL,就需要對這個語言本身進行一些修改。於是就產生了後來的 B 語言。

 

 B 語言作為系統開發語言,也存在很多的缺點,於是後來它又被改進為 NB 語言 (New B)。可是 NB 還是有很多的問題,於是 Dennis Ritchie 就又發明了 C 語言,最終在 1974年,Ken Thompson 和 Dennis Ritchie 一起用 C 語言重新編寫了第四版的 Unix 系統。現在,C 語言已經成為了操作系統開發最常用的編程語言。

 

通往 C 語言與 Unix 之路

Dennis Ritchie 曾經解釋過自己為什麼要發明 C 語言,以及使用 B 語言過程中遇到的一些困難:

  • 只能處理計算機字:B語言所有的操作都是通過計算機字來處理的,在那個時候,能夠處理字節的編程語言對工程師們來說是一個夢。

  • 沒有類型:準確的說,B語言只有一種類型,計算機字。如果你有一個字符串,可能你需要把它分成多個變量來保存,比如一個21個字符的字符串,就需要 6 個變量。

  • 不支持浮點類型運算:在那個時候,大部分硬件已經都可以開始支持浮點運算了,但是 B 語言還不支持這種操作。 

 

B 語言的這些問題,開發低效,在機器上運行緩慢等等,都迫使 Dennis Ritchie 發明一種新的編程語言。最開始被稱為 New B,後來逐漸演化成了 C 語言。

 

C 語言解決了 B 語言的很多缺陷,並很快成為了開發操作系統最流行的一種編程語言。新版本的 Unix 以及今天很多類 Unix 的操作系統都是用 C 語言開發出來的。

 

好了,講到這裏,我想大家都清楚了 Unix 和 C 語言是怎麼來的了,以及為什麼要用 C 語言來編寫 Unix。現在有很多非常流行的語言比如 Java 和 Python,它們是一種更高級的編程語言,是在 C 語言這一層之上的。但是如果大家想做設備驅動或者系統內核模塊的修改,還是離不開 C 語言這把利器。

 

 

推薦閱讀:

《一篇文章帶你快速弄清楚什麼是終端》

《一篇文章看清楚 Linux 的職業發展方向》

《2020年你最需要掌握的11種編程語言》

《微軟:懸賞10萬美金破解 Linux 系統》

《安卓到底是不是Linux》

 

  

 

獲取知識乾貨、增加面試經驗、了解程序人生

歡迎關注微信公眾號

回復【面試】,獲取技術大廠面試寶典

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

台北網頁設計公司這麼多該如何選擇?

※智慧手機時代的來臨,RWD網頁設計為架站首選

※評比南投搬家公司費用收費行情懶人包大公開

※回頭車貨運收費標準

網頁設計最專業,超強功能平台可客製化

※別再煩惱如何寫文案,掌握八大原則!

想不到7.5萬起車型開起來比14萬的車還更爽!

5{icon} {views}

38-11。28萬本田飛度有着“知乎神車”的稱號,原因10萬以內沒能找到一輛這樣低油耗、加速快以及高保值率的合資車。它使用的是1。5L地球夢發動機,最大功率96千瓦,配合5MT手動變速箱,可以實現9s以內的百公里加速時間,另外還有CVT變速箱可以選擇。

前言

“才六七萬錢的車,能開就行了,還要什麼操控樂趣?”,相信這句話是不少人都聽到過的,認為低價位的汽車都是比較無聊的,但是有沒有想過有些六七萬起售的汽車能給到你超越價格的樂趣,甚至要比貴了一倍價錢的車型還要好玩?

小型車,其實是一個被忽略的市場,在國產緊湊型轎車以及小型SUV的轟炸下,合資小型車的市場份額被逐漸蠶食。以前那種合資小型車百花齊放的景象已經看不到了,前些年年輕人都追求的是這種有着絕佳的操控樂趣小車。

它們都有着小巧的車身,在車流中可以非常靈活地穿梭;有着精準的操控,坐在車內有着一種人車合一的感覺;有着極低的重心,即使在山道也能有着較佳的車身姿態。有着類似卡丁車的操控樂趣,而且還有着較高的改裝潛力。

上汽大眾-pOLO

官方指導價:7.59-14.69萬

作為德系的代表,大眾pOLO有着極高的造詣,小巧的車身配合精準的操控,這輛小型車有着超高的駕駛樂趣,較高速度過彎都能有着一個極佳的姿態。所以在不少車隊甚至是大眾官方都是將其作為賽車車型的首選,價格低操控好而且改裝潛力大。

不過對於家庭用戶來說,後排空間就相對局促。動力方面有着1.4L以及1.6L自然吸氣發動機可以選擇,變速箱則是5MT以及6AT變速箱可以選擇,不過更推薦的是5MT,傳動效率高動力佳,而且檔位清晰,離合容易控制,上手難度低。

廣汽本田-飛度

官方指導價:7.38-11.28萬

本田飛度有着“知乎神車”的稱號,原因10萬以內沒能找到一輛這樣低油耗、加速快以及高保值率的合資車。它使用的是1.5L地球夢發動機,最大功率96千瓦,配合5MT手動變速箱,可以實現9s以內的百公里加速時間,另外還有CVT變速箱可以選擇。

它還有着極其優秀的車廂空間,完全不亞於某些合資緊湊型轎車,加上低油耗的特點非常適合家庭使用。動力強以及手感極好的手動變速箱,讓它有着超高的加速性能,不過過彎的時候側傾稍微有點大,但幸好可以通過改裝改善。

長安鈴木-雨燕

官方指導價:5.98-8.28萬

鈴木雨燕是之前小型車大熱時的產物,到如今那麼多年都僅僅是對外觀進行小小的修改,所以有着當初那種最佳的駕駛樂趣,不過也是因為這麼多年都沒有進行性能上的改進而為人所詬病。發動機方面有着1.3L以及1.5L兩種排量可以選擇,1.5L自然吸氣發動機最大功率76千瓦,相對弱勢。

但配合5MT手動變速箱操控極佳,加上優秀的底盤表現以及改裝潛力使得它是第三代飛度之前最熱的改裝車,如今在不少賽車場都可以看到它的蹤影。並且對於某些改裝發燒友來說,可以無損改裝進口速翼特的M16A發動機也是重大的優勢,動力輸出更加,高轉有着極其優秀的表現和魅力。

編輯總結:

以上三款汽車都可以說是這個價位中操控最好的代表,甚至比起12萬左右的合資緊湊型轎車還要優秀。價格基本可以在不到7萬可以買到,尤其是大眾pOLO,終端起售價甚至可以在6.5萬左右,非常適合追求駕駛樂趣的年輕人。本站聲明:網站內容來源於http://www.auto6s.com/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!

※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※教你寫出一流的銷售文案?

※別再煩惱如何寫文案,掌握八大原則!

這些車15萬預算就給你30萬般高顏值上檔次的內飾!

3{icon} {views}

99-15。99萬英朗外觀造型非常的有神韻。英朗的懸浮式的中控台造型上讓車廂內更具簡潔、時尚的氣質,懸浮式的中控台設計層次分明,按鍵數量精簡,簡約設計更讓視覺效果更顯檔次,英朗的內飾做工用料出色,銀色飾板的點綴到位,給人厚重紮實的感覺,全彩的3。

一台車,我們待的時間最多就是在車廂里,而外觀只有在上車時或者下車時,多看兩眼,正所謂,一步三回頭,欣賞它的美。所以內飾對我我們來說也是非常重要,好看的內飾,決定了你的品位,好看的內飾,還能調動你內心的情緒。

我們都知道

概念車的內飾

可實際上靠譜的內飾應該是這樣

東風本田-傑德

指導價:14.98-18.38萬

傑德的外觀可是顏值爆表,尤其是側面,非常符合年輕人的審美。傑德的內飾也是它的亮點之一,傑德的內飾整體給人一種很居家的感覺,沒有任何誇張的元素,簡約實用的設計風格。傑德的內飾雖然沒有讓人過目不忘的視覺衝擊,但是整體感覺非常舒適溫馨,中控台的設計也比較簡單,區域的劃分也很明顯,按鍵的布局排列也十分整齊。內種大面積的採用了木紋裝飾板,這種裝飾板摸上去手感還是不錯的,整體效果看上去更更居家,傑德採用了液晶屏式的儀錶盤,相對比傳統樣式的儀錶盤,信息的显示會更加豐富。時尚運動的外表之下,也可以有一顆居家的心,這就是傑德內飾給我的感覺。

上汽通用別克-英朗

指導價:10.99-15.99萬

英朗外觀造型非常的有神韻。英朗的懸浮式的中控台造型上讓車廂內更具簡潔、時尚的氣質,懸浮式的中控台設計層次分明,按鍵數量精簡,簡約設計更讓視覺效果更顯檔次,英朗的內飾做工用料出色,銀色飾板的點綴到位,給人厚重紮實的感覺,全彩的3.5英寸液晶儀錶清晰明了,錶盤刻度設計非常精緻,行車電腦显示信息豐富。英朗的內飾做工用料非常出色,坐在車內,你能感受到沉穩、從容的感覺。

長安標緻雪鐵龍-DS 5LS

指導價:14.98-24.68萬

法系車的外觀設計一直都是天馬行空,現在這種誇張的元素也慢慢收斂了許多,慢慢趨向大眾化,但它的外觀設計依然是特別有味道,DS 5LS外形依然顯豪華的質感,非常搶眼!5LS的內飾設計非常精緻和豪華感,中控的布局也是比較分明,功能區按鍵手感細膩,空間區按鍵和旋鈕搭配的布局合理,直觀,使用便捷,非常精緻,細節之處凸顯文化底蘊。DS 5LS的儀錶盤造型也很獨特、很有科技感,行車電腦显示的信息也比較豐富。DS 5LS的內飾設計更加豪華、上檔次。本站聲明:網站內容來源於http://www.auto6s.com/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

台北網頁設計公司這麼多該如何選擇?

※智慧手機時代的來臨,RWD網頁設計為架站首選

※評比南投搬家公司費用收費行情懶人包大公開

※回頭車貨運收費標準

網頁設計最專業,超強功能平台可客製化

※別再煩惱如何寫文案,掌握八大原則!

「持續集成實踐系列 」Jenkins 2.x 構建CI自動化流水線常見技巧

7{icon} {views}

在上一篇文章中,我們介紹了Jenkins 2.x實現流水線的兩種語法,以及在實際工作中該如何選擇腳本式語法或聲明式語法。原文可查閱:「持續集成實踐系列」Jenkins 2.x 搭建CI需要掌握的硬核要點(一)

在使用傳統的Jenkins Web界面和項目時,比如自由風格類型的任務,我們對處理流程的控制能力是有限的。所採用的典型形式是任務鏈:任務完成后觸發其他的任務。或者我們可能會包括構建后處理,不管任務成功完成與否,總是去做一些類似發送通知的事情。

除了這些基本的功能外,還可以添加條件性構建步驟插件,通過基於單個或者多個條件的構建步驟來定義更加複雜的流程。但即便如此,相比於我們編寫程序時可以直接控制執行流程的方法,條件性構建步驟插件對流程的控制能力依然有限。

在本篇中,我們將聊一下,關於Jenkins流水線DSL語言所提供的用於控制流水線執行流程基本結構和一些常見技巧。

1. Pipeline流水線指令常見結構

正如在系列第一篇文章中介紹到的,Jenkins DSL採用的是Groovy腳本語言。這也意味着如果當你掌握了Groovy語言,可以按照需求在流水線中使用Groovy語言的結構和習慣用法,針對這一類使用者,通常會更傾向於用腳本式語法來實現流水線。但不管採用的是哪種語法,從流水線組成的角度來講,都是由一些不同指令+步驟構建結構化代碼塊。

對於腳本式流水線,基本結構如下:

node('worker'){
    stage('階段'){
        // DSL
    }
}

構建腳本式流水線常用的結構或者說代碼塊節點主要由nodestage兩個組成。

而,聲明式流水線基本結構構成環節相對要多一些,整理了一張圖如下:

需要劃一個重點:可以簡單理解node是用於腳本式流水線,而agent則是用於聲明式流水線。

Jenkins Pipeline支持的指令(常見):

指令名 說明 作用域
agent 指定流水線或特定階段在哪裡運行。 stage 或pipeline
environment 設置環境變量 stage或pipeline
tools 自動下載並安裝指定的工具,並將其加入到PATH變量中 stage或pipeline
input 暫停pipeline,提示輸入內容 stage
options 用來指定一些預定義選項 stage 或 pipeline
parallel 并行執行多個step stage
parameters 允許執行pipeline前傳入一些參數 pipeline
triggers 定義執行pipeline的觸發器 pipeline
when 定義階段執行的條件 stage
build 觸發其他的job steps

options Jenkins Pipeline常見配置參數:

參數名 說明 例子
buildDiscarder 保留最近歷史構建記錄的數量 buildDiscarder(logRotator(numToKeepStr: ’10’)
timestamps 添加時間戳到控制台輸出 timestamps()
disableConcurrentBuilds 阻止Jenkins併發執行同一個流水線 disableConcurrentBuilds()
retry pipeline發生失敗后重試次數 retry(4)
timeout pipeline運行超時時間 timeout(time:1, unit: ‘HOURS’)

示例:

pipeline{
    agent any
    options{
        buildDiscarder(logRotator(numToKeepStr: '10')
        timestamps()
        retry(3)
        timeout(time:1, unit: 'HOURS')
    }
    stages{
        stage('demo'){
            steps{
                sh 'echo hello'
            }
        }
    }
}

更多pipeline指令,可參見官方介紹:

https://www.jenkins.io/doc/book/pipeline/syntax/#

下述僅挑幾個常用的,用於流水線流程控制選項的指令項,介紹一些常用技巧。

2. 超時(Timeout)

這個timeout步驟允許限制等待某個行為發生時腳本所花費的時間。其語法相當簡單。示例如下:

timeout(time:60,unit:'SECONDS'){
    //該代碼塊中的過程被設置為超時
}

默認的時間單位是min。如果發生超時,該步驟就會拋出一個異常。如果異常沒有被處理,將導致整個流水線過程被中止。

通常推薦的做法是,在使用timeout對任何造成流水線暫停的步驟(如一個input步驟)進行封裝,這樣做的結果是,即使出現差錯導致在限定的時間內沒有得到期望的輸入,流水線也會繼續執行。

示例如下:

node{
    def response
    stage('input'){
        timeout(time:10,unit:'SECONDS'){
            response = input message :'Please Input User'
            parameters:[string(defaultValue:'mikezhou',description:'Enter UserId:',name:'userid')]
        }
        echo "Username = " + response
    }
}

在這種情況下,Jenkins將會給用戶10s做出反應,如果時間到了,Jenkins會拋出一個異常來中止流水線。

如果實際在設計流水線時,當超時發生時,並不想中止流水線向下執行,可以引入try...catch代碼塊來封裝timeout。

如下代碼塊所示:

node{
    def response
    stage('input')
{
      try {
        timeout(time:10,unit:'SECONDS'){
            response = input message :'Please Input User'
            parameters:[string(defaultValue:'mikezhou',description:'Enter UserId:',name:'userid')]
         }
       }
       catch(err){
            response = 'user1'
      }
    }
}

需要注意的是,在處理異常的時候,可以在捕獲異常處設置為期望的默認值。

3. 重試(retry)

這個retry閉包將代碼封底裝為一個步驟,當代碼中有異常發生時,該步驟可以重試n次。其語法如下:

retry(n){
  //代碼過程
}

如果達到重試的限制並且發生了一個異常,那麼整個過程將會被中止(除非異常被處理,如使用try...catch代碼塊)

retry(2){
    try {
       def result=build job: "test_job"
       echo result
      }
    catch(err){
        if(!err.getMessage().contains("UNSTABLE"))
        throw err
    }
}

4. 等待直到(waitUntil)

引入waitUntil步驟,會導致整個過程一直等待某件事發生,通常這裏的“某件事”指的是可以返回true的閉包。

如果代碼過程永不返回true的話,這個步驟將會無期限地等待下去而不會結束。所以一般常見的做法,會結合timeout步驟來封裝waitUntil步驟。

例如,使用waitUntil代碼塊來等待一個標記文件出現:

timeout(time:15,unit:'SECONDS'){
    waitUntil{
        def ret = sh returnStatus:true,script:'test -e /home/jenkins2/marker.txt'
        return (ret==0)
    }
}

再舉一個例子,假如我們要等待一個Docker容器運行起來,以便我們可以在流水線中通過REST API調用獲取一些數據。在這種情況下,如果這個URL還不可用,就會得到一個異常。為了保證異常被拋出的時候進程不會立即退出,我們可以使用try...catch代碼塊來捕獲異常並且返回false。

timeout(time:150,unit:'SECONDS'){
    waitUntil{
        try{
            sh "docker exec ${containerid} curl --silent http://127.0.0.1:8080/api/v1/registry >/test/output/url.txt"
            return true
        }
        catch(err)
            return false
    }
}

5.Stash暫存:實現跨節點文件共享

在Jenkins的DSL中,stashunstash函數允許在流水線的節點間和階段間保存或獲取文件。

基本用法格式:

stash name:"<name>" [includes:"<pattern>" excludes:"<pattern>"]
unstash "<name>"

我們通過名稱或模式來指定一個被包括或被排除的文件的集合。給這些文件的暫存處命名,以便後面通過這個名稱使用這些文件。

提到stash,很多讀者可能會把Jenkins stashGit stash功能弄混,需要說明一下,Jenkins stashGit stash功能是不同的。Git stash函數是為了暫存一個工作目錄的內容,緩存那些還沒有提交到本地代碼倉庫的代碼。而Jenkins stash函數是為了暫存文件,以便在節點間共享。

例如,master節點和node節點,實現跨主機共享文件:

pipeline{
    agent none
    stages{
        stage('stash'){
            agent { label "master" }
            steps{
                writeFile file: "test.txt", text: "$BUILD_NUMBER"
                stash name: "test", includes: "test.txt"
            }
        }
        stage('unstash'){
            agent { label "node" }
            steps{
                script{
                    unstash("test")
                    def content = readFile("test.txt")
                    echo "${content}"
                }
            }
        }
    }
}

如果你覺得文章還不錯,請大家點贊分享下。你的肯定是我最大的鼓勵和支持。

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!

※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※教你寫出一流的銷售文案?

※別再煩惱如何寫文案,掌握八大原則!

重學 Java 設計模式:實戰橋接模式(多支付渠道「微信、支付寶」與多支付模式「刷臉、指紋」場景)

7{icon} {views}

作者:小傅哥
博客:https://bugstack.cn – 編寫系列原創專題文章

沉澱、分享、成長,讓自己和他人都能有所收穫!

一、前言

為什麼你的代碼那麼多ifelse

同類的業務、同樣的功能,怎麼就你能寫出來那麼多ifelse。很多時候一些剛剛從校園進入企業的萌新,或者一部分從小公司跳槽到大企業的程序員,初次承接業務需求的時候,往往編碼還不成熟,經常一桿到底的寫需求。初次實現確實很快,但是後期維護和擴展就十分痛苦。因為一段代碼的可讀性閱讀他後期的維護成本也就越高。

設計模式是可以幫助你改善代碼

很多時候你寫出來的ifelse都是沒有考慮使用設計模式優化,就像;同類服務的不同接口適配包裝、同類物料不同組合的建造、多種獎品組合的營銷工廠等等。它們都可以讓你代碼中原本使用if判斷的地方,變成一組組類和面向對象的實現過程。

怎麼把設計模式和實際開發結合起來

多從實際場景思考,只找到代碼優化的最佳點,不要可以想着設計模式的使用。就像你最開始看設計模式適合,因為沒有真實的場景模擬案例,都是一些畫圓形、方形,對新人或者理解能力還不到的夥伴來說很不友好。所以即使學了半天 ,但實際使用還是摸不着頭腦。

二、開發環境

  1. JDK 1.8
  2. Idea + Maven
  3. 涉及工程三個,可以通過關注公眾號bugstack蟲洞棧,回復源碼下載獲取(打開獲取的鏈接,找到序號18)
工程 描述
itstack-demo-design-7-01 使用一坨代碼實現業務需求
itstack-demo-design-7-02 通過設計模式優化改造代碼,產生對比性從而學習

三、橋接模式介紹

橋接模式的主要作用就是通過將抽象部分與實現部分分離,把多種可匹配的使用進行組合。說白了核心實現也就是在A類中含有B類接口,通過構造函數傳遞B類的實現,這個B類就是設計的

那麼這樣的橋接模式,在我們平常的開發中有哪些場景

JDBC多種驅動程序的實現、同品牌類型的台式機和筆記本平板、業務實現中的多類接口同組過濾服務等。這些場景都比較適合使用橋接模式進行實現,因為在一些組合中如果有如果每一個類都實現不同的服務可能會出現笛卡爾積,而使用橋接模式就可以非常簡單。

四、案例場景模擬

隨着市場的競爭在支付服務行業出現了微信和支付寶還包括一些其他支付服務,但是對於商家來說並不希望改變用戶習慣。就像如果我的地攤只能使用微信或者只能使用支付寶付款,那麼就會讓我顧客傷心,雞蛋灌餅也賣不動了。

在這個時候就出現了第三方平台,把市面上綜合佔據市場90%以上的支付服務都集中到自己平台中,再把這樣的平台提供給店鋪、超市、地攤使用,同時支持人臉、掃描、密碼多種方式。

我們這個案例就模擬一個這樣的第三方平台來承接各個支付能力,同時使用自家的人臉讓用戶支付起來更加容易。那麼這裏就出現了多支付多模式的融合使用,如果給每一個支付都實現一次不同的模式,即使是繼承類也需要開發好多。而且隨着後面接入了更多的支付服務或者支付方式,就會呈爆炸似的擴展。

所以你現在可以思考一下這樣的場景該如何實現?

五、用一坨坨代碼實現

產品經理說老闆要的需求,要儘快上,kpi你看着弄!

既然你逼我那就別怪我無情,還沒有我一個類寫不完的需求!反正寫完就完事了,拿完績效也要走了天天逼着寫需求,代碼越來越亂心疼後面的兄弟3秒。

1. 工程結構

itstack-demo-design-7-01
└── src
    └── main
        └── java
            └── org.itstack.demo.design
                └── PayController.java
  • 只有一個類裏面都是ifelse,這個類實現了支付和模式的全部功能。

2. 代碼實現

public class PayController {

    private Logger logger = LoggerFactory.getLogger(PayController.class);

    public boolean doPay(String uId, String tradeId, BigDecimal amount, int channelType, int modeType) {
        // 微信支付
        if (1 == channelType) {
            logger.info("模擬微信渠道支付划賬開始。uId:{} tradeId:{} amount:{}", uId, tradeId, amount);
            if (1 == modeType) {
                logger.info("密碼支付,風控校驗環境安全");
            } else if (2 == modeType) {
                logger.info("人臉支付,風控校驗臉部識別");
            } else if (3 == modeType) {
                logger.info("指紋支付,風控校驗指紋信息");
            }
        }
        // 支付寶支付
        else if (2 == channelType) {
            logger.info("模擬支付寶渠道支付划賬開始。uId:{} tradeId:{} amount:{}", uId, tradeId, amount);
            if (1 == modeType) {
                logger.info("密碼支付,風控校驗環境安全");
            } else if (2 == modeType) {
                logger.info("人臉支付,風控校驗臉部識別");
            } else if (3 == modeType) {
                logger.info("指紋支付,風控校驗指紋信息");
            }
        }
        return true;
    }

}
  • 上面的類提供了一個支付服務功能,通過提供的必要字段;用戶ID交易ID金額渠道模式,來控制支付方式。
  • 以上的ifelse應該是最差的一種寫法,即使寫ifelse也是可以優化的方式去寫的。

3. 測試驗證

3.1 編寫測試類

@Test
public void test_pay() {
    PayController pay = new PayController();
    System.out.println("\r\n模擬測試場景;微信支付、人臉方式。");
    pay.doPay("weixin_1092033111", "100000109893", new BigDecimal(100), 1, 2);
    
    System.out.println("\r\n模擬測試場景;支付寶支付、指紋方式。");
    pay.doPay("jlu19dlxo111","100000109894",new BigDecimal(100), 2, 3);
}
  • 以上分別測試了兩種不同的支付類型和支付模式;微信人臉支付、支付寶指紋支付

3.2 測試結果

模擬測試場景;微信支付、人臉方式。
23:05:59.152 [main] INFO  o.i.demo.design.pay.channel.Pay - 模擬微信渠道支付划賬開始。uId:weixin_1092033111 tradeId:100000109893 amount:100
23:05:59.155 [main] INFO  o.i.demo.design.pay.mode.PayCypher - 人臉支付,風控校驗臉部識別
23:05:59.155 [main] INFO  o.i.demo.design.pay.channel.Pay - 模擬微信渠道支付風控校驗。uId:weixin_1092033111 tradeId:100000109893 security:true
23:05:59.155 [main] INFO  o.i.demo.design.pay.channel.Pay - 模擬微信渠道支付划賬成功。uId:weixin_1092033111 tradeId:100000109893 amount:100

模擬測試場景;支付寶支付、指紋方式。
23:05:59.156 [main] INFO  o.i.demo.design.pay.channel.Pay - 模擬支付寶渠道支付划賬開始。uId:jlu19dlxo111 tradeId:100000109894 amount:100
23:05:59.156 [main] INFO  o.i.demo.design.pay.mode.PayCypher - 指紋支付,風控校驗指紋信息
23:05:59.156 [main] INFO  o.i.demo.design.pay.channel.Pay - 模擬支付寶渠道支付風控校驗。uId:jlu19dlxo111 tradeId:100000109894 security:true
23:05:59.156 [main] INFO  o.i.demo.design.pay.channel.Pay - 模擬支付寶渠道支付划賬成功。uId:jlu19dlxo111 tradeId:100000109894 amount:100

Process finished with exit code 0
  • 從測試結果看已經滿足了我們的不同支付類型和支付模式的組合,但是這樣的代碼在後面的維護以及擴展都會變得非常複雜。

六、橋接模式重構代碼

接下來使用橋接模式來進行代碼優化,也算是一次很小的重構。

從上面的ifelse方式實現來看,這是兩種不同類型的相互組合。那麼就可以把支付方式支付模式進行分離通過抽象類依賴實現類的方式進行橋接,通過這樣的拆分后支付與模式其實是可以單獨使用的,當需要組合時候只需要把模式傳遞給支付即可。

橋接模式的關鍵是選擇的橋接點拆分,是否可以找到這樣類似的相互組合,如果沒有就不必要非得使用橋接模式。

1. 工程結構

itstack-demo-design-7-02
└── src
    ├── main
    │   └── java
    │       └── org.itstack.demo.design.pay
    │           ├── channel
    │           │   ├── Pay.java
    │           │   ├── WxPay.java
    │           │   └── ZfbPay.java
    │           └── mode
    │               ├── IPayMode.java
    │               ├── PayCypher.java
    │               ├── PayFaceMode.java
    │               └── PayFingerprintMode.java
    └── test
         └── java
             └── org.itstack.demo.design.test
                 └── ApiTest.java

橋接模式模型結構

  • 左側Pay是一個抽象類,往下是它的兩個支付類型實現;微信支付、支付寶支付。
  • 右側IPayMode是一個接口,往下是它的兩個支付模型;刷臉支付、指紋支付。
  • 那麼,支付類型 × 支付模型 = 就可以得到相應的組合。

2. 代碼實現

2.1 支付類型橋接抽象類

public abstract class Pay {

    protected Logger logger = LoggerFactory.getLogger(Pay.class);

    protected IPayMode payMode;

    public Pay(IPayMode payMode) {
        this.payMode = payMode;
    }

    public abstract String transfer(String uId, String tradeId, BigDecimal amount);

}
  • 在這個類中定義了支付方式的需要實現的划賬接口:transfer,以及橋接接口;IPayMode,並在構造函數中用戶方自行選擇支付方式。
  • 如果沒有接觸過此類實現,可以重點關注 IPayMode payMode,這部分是橋接的核心。

2.2 兩個支付類型的實現

微信支付

public class WxPay extends Pay {

    public WxPay(IPayMode payMode) {
        super(payMode);
    }

    public String transfer(String uId, String tradeId, BigDecimal amount) {
        logger.info("模擬微信渠道支付划賬開始。uId:{} tradeId:{} amount:{}", uId, tradeId, amount);
        boolean security = payMode.security(uId);
        logger.info("模擬微信渠道支付風控校驗。uId:{} tradeId:{} security:{}", uId, tradeId, security);
        if (!security) {
            logger.info("模擬微信渠道支付划賬攔截。uId:{} tradeId:{} amount:{}", uId, tradeId, amount);
            return "0001";
        }
        logger.info("模擬微信渠道支付划賬成功。uId:{} tradeId:{} amount:{}", uId, tradeId, amount);
        return "0000";
    }

}

支付寶支付

public class ZfbPay extends Pay {

    public ZfbPay(IPayMode payMode) {
        super(payMode);
    }

    public String transfer(String uId, String tradeId, BigDecimal amount) {
        logger.info("模擬支付寶渠道支付划賬開始。uId:{} tradeId:{} amount:{}", uId, tradeId, amount);
        boolean security = payMode.security(uId);
        logger.info("模擬支付寶渠道支付風控校驗。uId:{} tradeId:{} security:{}", uId, tradeId, security);
        if (!security) {
            logger.info("模擬支付寶渠道支付划賬攔截。uId:{} tradeId:{} amount:{}", uId, tradeId, amount);
            return "0001";
        }
        logger.info("模擬支付寶渠道支付划賬成功。uId:{} tradeId:{} amount:{}", uId, tradeId, amount);
        return "0000";
    }

}
  • 這裏分別模擬了調用第三方的兩個支付渠道;微信、支付寶,當然作為支付綜合平台可能不只是接了這兩個渠道,還會有其很跟多渠道。
  • 另外可以看到在支付的時候分別都調用了風控的接口進行驗證,也就是不同模式的支付(刷臉指紋),都需要過指定的風控,才能保證支付安全。

2.3 定義支付模式接口

public interface IPayMode {

    boolean security(String uId);

}
  • 任何一個支付模式;刷臉、指紋、密碼,都會過不同程度的安全風控,這裏定義一個安全校驗接口。

2.4 三種支付模式風控(刷臉、指紋、密碼)

刷臉

public class PayFaceMode implements IPayMode{

    protected Logger logger = LoggerFactory.getLogger(PayCypher.class);

    public boolean security(String uId) {
        logger.info("人臉支付,風控校驗臉部識別");
        return true;
    }

}

指紋

public class PayFingerprintMode implements IPayMode{

    protected Logger logger = LoggerFactory.getLogger(PayCypher.class);

    public boolean security(String uId) {
        logger.info("指紋支付,風控校驗指紋信息");
        return true;
    }

}

密碼

public class PayCypher implements IPayMode{

    protected Logger logger = LoggerFactory.getLogger(PayCypher.class);

    public boolean security(String uId) {
        logger.info("密碼支付,風控校驗環境安全");
        return true;
    }

}
  • 在這裏實現了三種支付模式(刷臉、指紋、密碼)的風控校驗,在用戶選擇不同支付類型的時候,則會進行相應的風控攔截以此保障支付安全。

3. 測試驗證

3.1 編寫測試類

@Test
public void test_pay() {
    System.out.println("\r\n模擬測試場景;微信支付、人臉方式。");
    Pay wxPay = new WxPay(new PayFaceMode());
    wxPay.transfer("weixin_1092033111", "100000109893", new BigDecimal(100));

    System.out.println("\r\n模擬測試場景;支付寶支付、指紋方式。");
    Pay zfbPay = new ZfbPay(new PayFingerprintMode());
    zfbPay.transfer("jlu19dlxo111","100000109894",new BigDecimal(100));
}
  • 與上面的ifelse實現方式相比,這裏的調用方式變得整潔、乾淨、易使用;new WxPay(new PayFaceMode())new ZfbPay(new PayFingerprintMode())
  • 外部的使用接口的用戶不需要關心具體的實現,只按需選擇使用即可。

3.2 測試結果

模擬測試場景;微信支付、人臉方式。
23:14:40.911 [main] INFO  o.i.demo.design.pay.channel.Pay - 模擬微信渠道支付划賬開始。uId:weixin_1092033111 tradeId:100000109893 amount:100
23:14:40.914 [main] INFO  o.i.demo.design.pay.mode.PayCypher - 人臉支付,風控校驗臉部識別
23:14:40.914 [main] INFO  o.i.demo.design.pay.channel.Pay - 模擬微信渠道支付風控校驗。uId:weixin_1092033111 tradeId:100000109893 security:true
23:14:40.915 [main] INFO  o.i.demo.design.pay.channel.Pay - 模擬微信渠道支付划賬成功。uId:weixin_1092033111 tradeId:100000109893 amount:100

模擬測試場景;支付寶支付、指紋方式。
23:14:40.915 [main] INFO  o.i.demo.design.pay.channel.Pay - 模擬支付寶渠道支付划賬開始。uId:jlu19dlxo111 tradeId:100000109894 amount:100
23:14:40.915 [main] INFO  o.i.demo.design.pay.mode.PayCypher - 指紋支付,風控校驗指紋信息
23:14:40.915 [main] INFO  o.i.demo.design.pay.channel.Pay - 模擬支付寶渠道支付風控校驗。uId:jlu19dlxo111 tradeId:100000109894 security:true
23:14:40.915 [main] INFO  o.i.demo.design.pay.channel.Pay - 模擬支付寶渠道支付划賬成功。uId:jlu19dlxo111 tradeId:100000109894 amount:100

Process finished with exit code 0
  • 從測試結果看內容是一樣的,但是整體的實現方式有了很大的變化。所以有時候不能只看結果,也要看看過程

七、總結

  • 通過模擬微信與支付寶兩個支付渠道在不同的支付模式下,刷臉指紋密碼,的組合從而體現了橋接模式的在這類場景中的合理運用。簡化了代碼的開發,給後續的需求迭代增加了很好的擴展性。
  • 從橋接模式的實現形式來看滿足了單一職責和開閉原則,讓每一部分內容都很清晰易於維護和拓展,但如果我們是實現的高內聚的代碼,那麼就會很複雜。所以在選擇重構代碼的時候,需要考慮好整體的設計,否則選不到合理的設計模式,將會讓代碼變得難以開發。
  • 任何一種設計模式的選擇和使用都應該遵頊符合場景為主,不要刻意使用。而且統一場景因為業務的複雜從而可能需要使用到多種設計模式的組合,才能將代碼設計的更加合理。但這種經驗需要從實際的項目中學習經驗,並提不斷的運用。

八、推薦閱讀

  • 1. 重學 Java 設計模式:實戰工廠方法模式(多種類型商品發獎場景)
  • 2. 重學 Java 設計模式:實戰抽象工廠模式(替換Redis雙集群升級場景)
  • 3. 重學 Java 設計模式:實戰建造者模式(裝修物料組合套餐選配場景)
  • 4. 重學 Java 設計模式:實戰原型模式(多套試每人題目和答案亂序場景)
  • 5. 重學 Java 設計模式:實戰單例模式(Effective Java 作者推薦枚舉單例模式)

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

台北網頁設計公司這麼多該如何選擇?

※智慧手機時代的來臨,RWD網頁設計為架站首選

※評比南投搬家公司費用收費行情懶人包大公開

※回頭車貨運收費標準

網頁設計最專業,超強功能平台可客製化

※別再煩惱如何寫文案,掌握八大原則!

這有點猛!疑似 M1X 晶片的規格、效能跑分現身國外網站,12 核心 CPU + 16 核心 GPU

6{icon} {views}

搭載 M1X 晶片 MacBook 可說是今年很多蘋果用戶最期待的產品之一,從 M1 來看,雖然已經知道這顆效能絕對不會差到哪去,但究竟有多強悍,相信不少人都想提前知道。而最近國外跑分網站就出現疑似 M1X 晶片的規格表,不僅非常猛,下方甚至還附上跑分比較表,如果是真的,那這顆實在有點誇張。

(圖片來源)

疑似 M1X 晶片的規格、效能跑分現身國外網站

近日國外 CPU Monkey 跑分網站上,出現一筆 Apple M1X 的跑分與規格資料,從下圖可以看到,這顆晶片採 5nm 製程技術,時脈雖然維持在 3.20GHz,但核心數提升到 12 顆,8 顆效能核心 + 4 顆節能核心。GPU 更誇張,核心數直接多一倍,變成 16 核心(M1 為 8 核心)。也有註明推出時間,預計在 2021 年的 Q2:

核心數跟去年底 LeasApplePro 爆料的 12 顆一樣,也增添這表格的可信度:

Next Mac March 12 cores

— LeaksApplePro (@LeaksApplePro) December 31, 2020

下方還有跑分數據圖,多核心相當猛,不過真實性還不知道,所以大家就參考即可,不用太認真看待。

首先是 Cinebench R23 單核心,時脈沒變,也因此分數當然跟 M1 差不多,獲得 1514 的同分表現:

Cinebench R23 多核心就超級猛,比 Ryzen 5700G 和 i9-10900X 還要高,獲得 14450 的分數:

Geekbench 5 64 位元單核心測試,也跟 M1 一樣,獲得 1744 的分數:

iGPU F32 效能測試,跟 M1 相比幾乎快提升一倍,拿下 5200 的超高分數:

如果到時 Apple 端出的 M1X 晶片真是這樣,那今年的新 Mac 看來也必入手不可阿,實在是讓人非常期待。

稍早也有消息指出,3/16 蘋果有可能舉辦春季新品發表會,不過預測新品表似乎沒有 Mac。

資料來源:CPU Monkey

針對 Apple M1 惡意軟體出現,安全自保守好三不

您也許會喜歡:

【推爆】終身$0月租 打電話只要1元/分

立達合法徵信社-讓您安心的選擇

【其他文章推薦】

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!

※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※教你寫出一流的銷售文案?

※別再煩惱如何寫文案,掌握八大原則!

國外 YouTuber 實測 M1 MacBook Air 貼上導熱矽膠片後,效能有感提升(更接近 MacBook Pro)

6{icon} {views}

MacBook Air 與 MacBook Pro 雖然都是搭載 M1 晶片,但 MacBook Air 的 GPU 部分少一顆,也沒有散熱風扇,因此正常來說重度工作的處理效能,MacBook Air 表現會差一些,不過最近一位國外 YouTuber 找到一個解決方案,只需要花個 30 美金購入導熱矽膠片並貼在 MacBook Air 上,就能立刻提升效能表現,甚至有些測試還超過 MacBook Pro,讓人眼睛為之一亮。

M1 MacBook Air 貼上導熱矽膠片效能有感提升

近日 Max Tech 頻道上傳一部 M1 MacBook Air 加裝導熱矽膠貼片的實測影片,這貼片是從 Amazon 網站上購買的,僅 30 美金(買兩片)。不過黏貼時需要把 MacBook Air 背蓋拆掉,因此有可能會喪失保固,有興趣的人這點要注意。

導熱矽膠片黏貼在左上角的位置,他也有拍攝一部黏貼教學影片,有興趣了解的人文末會附上:

下圖為這次的測試比較內容,從 Geekbench、Cinebench、影片輸出、圖片剪輯、一直到電池續航力比較都有:

Geekbench 5 成績跟 MacBook Pro 幾乎一樣,多核心還多出 21 分:

GPU 因為少一顆,因此即便 M1 MacBook Air 加上導熱矽膠貼片也無法追上 MacBook Pro:

Cinebench R23 跑分就跟 M1 MacBook Pro 差不多,差距僅 40 分不到:

而跟未黏貼的 M1 MacBook Air 相比,黏貼後整整高出 1,000 多分,這相當驚人:

Xcode 測試也相當接近,黏貼後的 M1 MacBook Air 僅慢個 1 秒:

BruceX Benchmark 測試也非常亮眼,比 M1 MacBook Pro 還快,23.91 秒就完成:

5 分鐘 4K H.264 格式影片輸出速度,黏貼後的 M1 MacBook Air 也比 M1 MacBook Pro 快,約 3 分 2 秒就完成:

8 位元 HEVC 穩定性測試就一樣,皆為 10 秒鐘完成:

10 位元 HEVC 輸出也相同時間完成,都是 1 分鐘 12 秒,Max Tech 也提到,這項測試過去 MacBook Air 都比 MacBook Pro 還慢,因此非常讓人驚艷:

4.5K Red Raw 影片輸出則是 M1 MacBook Pro 快一些,2 分 36 秒完成,不過黏貼後的 M1 MacBook Air 也僅慢 11 秒:

8K Red Raw 影片輸出差距就稍微大一點,M1 MacBook Pro 約 20 分 20 秒就完成,黏貼後的 M1 MacBook Air 為 23 分 39 秒:

Lightroom Classic 50x 42MP 輸出測試部分,黏貼後的 M1 MacBook Air 就比較快,2 分 37 秒完成,M1 MacBook Pro 慢了 17 秒:

而最後的電池續航力測試,一開始這兩台都是 100% 充飽電,過程都進行一樣的操作測試,跑到最後一項 M1 MacBook Pro 還有 67% 電量,黏貼後的 M1 MacBook Air 剩下 52% 電量,因此對於注重續航力的人,M1 MacBook Pro 還是比較好。

不得不說,花點小錢貼上幾片導熱矽膠片,就能讓 M1 MacBook Air 效能有感提升,感覺真的挺不錯的,但必須承擔可能喪失保固的風險,已過保的人就蠻值得試試。

完整測試影片:

 

這部則是黏貼教學影片,後半部有跟未黏貼的 M1 MacBook Air 測試比較:

這有點猛!疑似 M1X 晶片的規格、效能跑分現身國外網站,12 核心 CPU + 16 核心 GPU

您也許會喜歡:

【推爆】終身$0月租 打電話只要1元/分

立達合法徵信社-讓您安心的選擇

【其他文章推薦】

台北網頁設計公司這麼多該如何選擇?

※智慧手機時代的來臨,RWD網頁設計為架站首選

※評比南投搬家公司費用收費行情懶人包大公開

※回頭車貨運收費標準

網頁設計最專業,超強功能平台可客製化

※別再煩惱如何寫文案,掌握八大原則!