国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

一文理清21種設(shè)計模式:用實例分析和對比

PrototypeZ / 798人閱讀

摘要:設(shè)計模式無論是對于最底層的的編碼實現(xiàn)還是較高層的架構(gòu)設(shè)計都有著重要的指導(dǎo)作用。所謂光說不練假把式,今天我就把項目中常見的應(yīng)用場景涉及到的主要設(shè)計模式及其相關(guān)設(shè)計模式總結(jié)一下,用實例分析和對比的方式在一片文章中就把最常見的種設(shè)計模式梳理清楚。

設(shè)計模式無論是對于最底層的的編碼實現(xiàn)還是較高層的架構(gòu)設(shè)計都有著重要的指導(dǎo)作用。所謂光說不練假把式,今天我就把項目中常見的應(yīng)用場景涉及到的主要設(shè)計模式及其相關(guān)設(shè)計模式總結(jié)一下,用實例分析和對比的方式在一片文章中就把最常見的21種設(shè)計模式梳理清楚。

Redis發(fā)布訂閱

在項目中常常使用redis的發(fā)布/訂閱功能,用來實現(xiàn)進程間通信甚至IM等業(yè)務(wù)。
使用 jedis 實現(xiàn)頻道訂閱的模式一般如下:

try( Jedis jedis =  RedisClient.getJedis() ) {
    JedisPubSub listener = new MySubListener();
    // 訂閱
    jedis.subscribe(listener, "channel");
}

其中 MySubListener

class MySubListener extends JedisPubSub {
    // 取得訂閱的消息后的處理
    public void onMessage(String channel, String message) {
        logger.info("頻道:{},收到消息:{}",channel,message);
    }
    // 初始化訂閱時候的處理
    public void onSubscribe(String channel, int subscribedChannels) {
        logger.info("訂閱:{},總數(shù):{}",channel,subscribedChannels);
    }
    // 取消訂閱時候的處理
    public void onUnsubscribe(String channel, int subscribedChannels) {
        logger.info("取消訂閱:{},總數(shù):{}",channel,subscribedChannels);
    }
}

這里使用了策略模式對算法的封裝,把使用算法的責任和算法本身分隔開,委派給不同的對象管理。策略模式通常把一系列的算法包裝到一系列的策略類里面,作為抽象策略類的子類)。
圖:

本例中,JedisPubSub抽象策略類,定義不同事件發(fā)生時的響應(yīng)模式亦即所支持的算法的公共接口;MySubListener是一個具體策略類定義了一種具體的事件響應(yīng)方式(簡單的打印);jedis是就是Context,負責維護調(diào)用者與策略之間的聯(lián)系。這樣不同的調(diào)用者只需要傳入不同的事件響應(yīng)具體算法如MySubListener1、2、3等即可(而不是去修改已有算法),實現(xiàn)了對擴展開放,對修改關(guān)閉的開閉原則
jedis 發(fā)布事件的代碼如下:

try {
    jedis.publish("channel","message to be published");
}

說到這就不得不說說狀態(tài)模式當一個對象內(nèi)在狀態(tài)改變時允許其改變行為, 這個對象看起來像改變了其類
圖:

Context定義客戶端需要的接口, 并且負責具體狀態(tài)的切換
State接口或抽象類,負責對象狀態(tài)定義,并且封裝Context以實現(xiàn)狀態(tài)切換;
ConcreteState每一個具體狀態(tài)必須完成兩個職責:就是本狀態(tài)下要做的事情,以及本狀態(tài)如何過渡到其他狀態(tài)
狀態(tài)模式和策略模式都是為具有多種可能情形設(shè)計的模式,把不同的處理情形抽象為一個相同的接口,符合開閉原則。但是狀態(tài)模式將各個狀態(tài)對應(yīng)的操作分離開來,即不同的狀態(tài)由不同的子類實現(xiàn)具體操作,狀態(tài)切換由子類實現(xiàn),當發(fā)現(xiàn)傳入?yún)?shù)不是自己這個狀態(tài)所對應(yīng)的參數(shù),則自己給Context類切換狀態(tài),也就是說客戶端并不知曉狀態(tài);而策略模式是直接依賴注入到Context類的參數(shù)進行選擇策略,不存在切換狀態(tài)的操作,也就是說狀態(tài)和策略是由客戶端自己定的

回到本例,發(fā)布/訂閱本身就是觀察者模式定義對象間一種一對多的依賴關(guān)系,使得每當一個對象改變狀態(tài),則所有依賴于它的對象都會得到通知并被自動更新)的運用。
圖:

可以結(jié)合Redis設(shè)計與實現(xiàn)查看redis實現(xiàn)發(fā)布訂閱的原理。本例中,JedisPubSub抽象觀察者MySubListener具體觀察者抽象主題沒有顯式定義,但是我們知道它的標準就是能夠添加、刪除、通知觀察者(如調(diào)用onMessage方法),具體主題就是redis里面包含"channel"這個模式的頻道。這就把消息生產(chǎn)者和消費者解耦了,消費者不用管生產(chǎn)者如何產(chǎn)生消息,生產(chǎn)者不用管消費者如何處理消息,兩者直接是松耦合的,也就是說兩者僅依賴于通知機制進行交互而不知道對方的實現(xiàn)細節(jié),這樣只要保持通知機制,雙方都可以隨意擴展。

請注意上面代碼的Jedis jedis = RedisClient.getJedis()是一個靜態(tài)工廠方法模式或者說簡單工廠模式通過專門定義一個類使用靜態(tài)方法來負責創(chuàng)建其他類的實例,被創(chuàng)建的實例通常都具有共同的父類或者父接口)的使用。
圖:

RedisClient主要代碼如下:

public final class RedisClient {
    
    private static JedisPool jedisPool;

    public static void construct(Properties p){
        try {
            JedisPoolConfig config = new JedisPoolConfig();
            config.setMaxTotal(Integer.parseInt(p.getProperty("jedis.pool.maxTotal")));
            jedisPool = new JedisPool(config,p.getProperty("redis.host"), Integer.parseInt(p.getProperty("redis.port")),
                    Integer.parseInt(p.getProperty("redis.timeOut")),p.getProperty("redis.auth"), Integer.parseInt(p.getProperty("redis.db")));
        }
    }
    public static Jedis getJedis(){
        return jedisPool.getResource();
    }
    public static void destruct(){
        jedisPool.close();
    }
}

本例中類RedisClient就是Creator,返回的redis客戶端Jedis就是ConcreateProduct,由于目前只用了 jedis 這一種 java redis client 所以沒有設(shè)置抽象的Product,如果有多種client那么就要設(shè)置抽象的Product(這些Product都要有set、hset等redis通用操作),然后再在getJedis函數(shù)中去根據(jù)需要產(chǎn)生不同的client(if else 或者 switch case)。
靜態(tài)工廠方法的好處在于:增加新的Product類(比如新的java redis client)的時候老的類不需要改變,調(diào)用者由于只依賴于接口(抽象的Product)也不用改變,亦即把變化封裝到工廠內(nèi)部了;可讀性更強(比如getJedis你就知道他要干啥,而不是使用不知所以的構(gòu)造函數(shù));緩存增強性能(比如上面的jedisPool就一直存在著,避免每次獲取連接時新創(chuàng)建連接池);代碼簡潔等等。

靜態(tài)工廠方法模式的缺點就是新加入一個Product類的時候,其工廠方法本身需要改變(比如多一個判斷的case分支),解決辦法就是采用每種具體Product對應(yīng)一個具體工廠的工廠模式定義一個用于創(chuàng)建對象的接口, 讓子類決定實例化哪一個類。 工廠方法使一個類的實例化延遲到其子類
圖:

工廠模式把每一種 product 類的實例化過程都封裝到了一個對應(yīng)的工廠類中,新加入product的時候不需要改任何的舊代碼,只需要同時添加對應(yīng)的具體工廠類即可。高層模塊只需要知道產(chǎn)品的抽象類,其他的具體實現(xiàn)類都不需要關(guān)心,符合迪米特法則,依賴倒置原則,里氏替換原則

然后就不得不說說抽象層次更高、更具一般性的抽象工廠模式為創(chuàng)建一組相關(guān)或相互依賴的對象提供一個接口, 而且無須指定它們的具體類)了
圖:

抽象工廠與工廠方法的區(qū)別就是可能有多個抽象Product,也就是說每一個具體工廠能夠生產(chǎn)一個產(chǎn)品族而不只是一個產(chǎn)品,可以把抽象工廠簡單理解為工廠方法+簡單工廠,每一個具體工廠都是一個簡單工廠。

說到工廠模式就不得不說原型模式用原型實例指定創(chuàng)建對象的種類, 并且通過拷貝這些原型創(chuàng)建新的對象
圖:

原型模式的核心是Override Object 類的 clone 方法,通過該方法進行對象的拷貝,由于是內(nèi)存二進制流的拷貝,所以比直接new性能好很多,特別是要在一個循環(huán)體內(nèi)產(chǎn)生大量的對象時,原型模式可以更好地體現(xiàn)其優(yōu)點。在實際項目中,原型模式很少多帶帶出現(xiàn),一般是和工廠方法模式一起出現(xiàn),通過clone的方法創(chuàng)建一個對象, 然后由工廠方法提供給調(diào)用者。

繼續(xù)觀察上面的RedisClient類,我們知道,連接池jedisPool在整個應(yīng)用中是只需要一個實例的,也就是說我們要使用單例模式確保某一個類只有一個實例, 而且自行實例化并向整個系統(tǒng)提供這個實例
圖:

所以我們的代碼要修改一下:

public final class RedisClient {
    
    private static volatile JedisPool jedisPool;

    public static void construct(Properties p){
        try {
            JedisPoolConfig config = new JedisPoolConfig();
            config.setMaxTotal(Integer.parseInt(p.getProperty("jedis.pool.maxTotal")));
            if(jedisPool==null){
                synchronized (RedisClient.class){
                    if (jedisPool==null){
                        jedisPool = new JedisPool(config,p.getProperty("redis.host"), Integer.parseInt(p.getProperty("redis.port")),
                            Integer.parseInt(p.getProperty("redis.timeOut")),p.getProperty("redis.auth"), Integer.parseInt(p.getProperty("redis.db")));
                    }
                }
            }
        }
    }     
}

這里用volatile+雙重檢查來實現(xiàn)單例模式,和標準的單例模式區(qū)別是,本例并不需要返回jedisPool實例,而是返回了一個jedis連接。

上面的JedisPool用到了享元模式使用共享對象來有效地支持大量的細粒度的對象
圖:

JedisPool就是FlyweightFactoryjedis 就是 ConcreteFlyweight抽象的Flyweight在本例沒有設(shè)置,但是我們知道它肯定是封裝了常見的redis操作接口的,UNsharedConcreteFactory也沒有對應(yīng)設(shè)置,因為jedis對客戶端都是一樣的,所以所有部分都不是不可分享的。通過池操作,使得固定數(shù)量N(甚至更少)的jedis對象可以服務(wù)于遠超N個的客戶端對象,達到共享和復(fù)用的目的。

Netty的應(yīng)用

我們啟動Netty服務(wù)器的時候,服務(wù)端使用ServerBootstrap,一般而言代碼如下:

NioEventLoopGroup group = new NioEventLoopGroup();
ServerBootstrap b = new ServerBootstrap();
b.group(group) 
    .channel(NioServerSocketChannel.class) 
    .localAddress(new InetSocketAddress(port)) 
    .childHandler(new ChannelInitializer() { 
        @Override
        public void initChannel(SocketChannel ch)
            throws Exception {
            ch.pipeline().addLast(
                new EchoServerHandler());
        }
});
ChannelFuture f = b.bind().sync();

這里使用了建造者模式將一個復(fù)雜對象的構(gòu)建與它的表示分離, 使得同樣的構(gòu)建過程可以創(chuàng)建不同的表示
圖:

本例中ServerBootstrap具體建造者,其繼承的AbstractBootstrap抽象建造者,返回的ProductChannelFuture,我們的調(diào)用代碼是Director。通過建造者模式,我們在構(gòu)建復(fù)雜對象的時候不必一次性確定全部參數(shù)(碩大的構(gòu)造函數(shù)),而是根據(jù)需要一步一步構(gòu)建一個完整的對象(也比一個一個調(diào)用setter的方式節(jié)省代碼而且美觀),所以每一個構(gòu)造過程函數(shù)都要返回一個完整的對象this。說到這就不得不說一說裝飾器模式動態(tài)地給一個對象添加一些額外的職責。就增加功能來說, 裝飾模式相比生成子類更為靈活
圖:

裝飾器模式的ConcreateDecorator可以在不改變ConcreateComponent給其添加一些新功能或者新特性,就像建造者模式,每一步建造過程都在給自身添加新功能或者新特性,也就是說如果看做裝飾器模式,那么ConcreateDecoratorConcreateComponent都是Builder自身,而且添加過程和得到的結(jié)果都相對穩(wěn)定,所以建造者模式是一種特殊的裝飾器模式。裝飾器模式在java的IO類中應(yīng)用廣泛。
與裝飾器模式非常相似的模式有適配器模式將一個類的接口變換成客戶端所期待的另一種接口, 從而使原本因接口不匹配而無法在一起工作的兩個類能夠在一起工作
圖:

代理模式為其他對象提供一種代理以控制對這個對象的訪問
圖:

外觀模式要求一個子系統(tǒng)的外部與其內(nèi)部的通信必須通過一個統(tǒng)一的對象進行外觀模式提供一個高層次的接口,使得子系統(tǒng)更易于使用
圖:

這4個模式都是將原本的對象進行包裝轉(zhuǎn)換實現(xiàn)另一些功能,不同的是:

裝飾器模式關(guān)注于在一個對象上動態(tài)的添加方法,增加新的行為,實現(xiàn)新功能

適配器模式關(guān)注于將一個類的接口轉(zhuǎn)換成客戶希望的另外一個不同的接口,使得原本接口不兼容而不能一起工作的那些類可以兼容

代理模式關(guān)注于為其他對象提供一種代理以實現(xiàn)對這個對象的訪問控制,代理與被代理對象實現(xiàn)相同的接口

外觀模式關(guān)注于為子系統(tǒng)中的一組接口提供一個一致的界面,此模式簡化接口,使得子系統(tǒng)更加容易使用

netty處理與客戶端之間的消息往來使用的ChannelPipelineChannelHandler模型是一個典型的命令模式將一個請求封裝成一個對象,從而讓你使用不同的請求把客戶端參數(shù)化,對請求、排隊或者記錄請求日志,還提供命令的撤銷和恢復(fù)功能)的使用
圖:

在java中,常常將ConcreteCommandReceiver合并為一個對象,這樣每個命令都完成一個職責,而不是根據(jù)接收者的不同完成不同的職責,client調(diào)用時就不用考慮接收者是誰。模式如下:

//非儉省模式定義 接收者 和 命令
Receiver receiver = new ConcreteReciver1(); Command command = new ConcreteCommand1(receiver);
//儉省模式 只定義一個發(fā)送給接收者的具體命令
Command command = new ConcreteCommand1();
//首先聲明調(diào)用者Invoker
Invoker invoker = new Invoker();
//把命令交給調(diào)用者
invoker.setCommand(command);
//執(zhí)行
invoker.action();

java Runable就是一個絕佳的示例:

//定義一個具體的命令賦值給抽象的命令引用,里面的run可以理解為receiver
Runnable runnable = new Runnable() {
    @Override
    public void run() {
        System.out.println(2);
    }
};
//聲明調(diào)用者Invoker并把命令交給調(diào)用者
Thread thread = new Thread(runnable);
//執(zhí)行
thread.start();    

netty中一個ChannelInboundHandler收到消息后調(diào)用ChannelHandlerContext(繼承了ChannelInboundInvoker)的fireChannelRead去調(diào)用下一個ChannelInboundHandlerchannelRead方法。
實際做法中,ChannelInboundInvoker是抽象的Invoker,而AbstractChannelHandlerContext才是真正的具體Invoker,其 static void invokeChannelRead(final AbstractChannelHandlerContext next, Object msg) 方法(也就是執(zhí)行方法)調(diào)用了下一個(next)ChannelInboundHandler(也就是receiver)的channelRead方法(也就是具體命令

ChannelPipelineChannelHandler模型也是一個標準的責任鏈模式使多個對象都有機會處理請求,從而避免了請求的發(fā)送者和接受者之間的耦合關(guān)系。將這些對象連成一條鏈,并沿著這條鏈傳遞該請求,直到有對象處理它為止
圖:

Handler就是netty中的ChannelHandler接口,消息處理的每一個ConcreteHandler(一般由我們自己實現(xiàn))都會去調(diào)用下一個ConcreteHandler。

ChannelPipelineChannelHandler模型實際上還是一個非典型的模板方法模式定義一個操作中的算法的框架, 而將一些步驟延遲到子類中,使得子類可以不改變一個算法的結(jié)構(gòu)即可重定義該算法的某些特定步驟
圖:

也就是說,netty規(guī)定了處理客戶端的連接的算法是先用一些列抽象的ChannelInboundHandler處理(比如解碼、解密),然后再由一系列抽象的ChannelOutboundHandler處理(比如編碼、加密),但是具體的Handler實現(xiàn)是我們自己加入的,如上面代碼改一下:

ch.pipeline().addLast(new DecodeHandler());
ch.pipeline().addLast(new EncodeHandler());
ch.pipeline().addLast(new BusinessHandler());

說他非典型主要是模板方法模式的算法的框架是確定的(比如確定了要解碼、存儲、編碼三個步驟),不確定的只是細節(jié),但是在netty中不僅細節(jié),算法框架本身我們都可以自己修改(可以加入很多的Handler)。

其他

橋接模式抽象和實現(xiàn)解耦,使得兩者可以獨立地變化
圖:

Abstraction的主要職責是定義出該角色的行為,同時保存一個對Implementor的引用,該角色一般是抽象類;
Implementor是接口或者抽象類,定義角色必需的行為和屬性;
RefinedAbstraction引用Implementor對Abstraction進行修正;
ConcreteImplementor實現(xiàn)接口或抽象類定義的方法和屬性。
所謂將抽象和實現(xiàn)解耦就是說抽象與實現(xiàn)不是直接通過繼承來強耦合,而是通過對象組合構(gòu)成的一座橋來實現(xiàn)弱耦合。
最經(jīng)典的橋接模式就是JDBC,JDBC為所有的數(shù)據(jù)庫提供通用的接口(Abstraction), 一個應(yīng)用程序可以根據(jù)需要選擇的驅(qū)動程序(Implementor), 通過具體的驅(qū)動程序(ConcreteImplementor)向的數(shù)據(jù)庫發(fā)起請求. 這個過程就是Abstraction把行為委托給Implementor的過程,這樣一來應(yīng)用程序和具體的驅(qū)動程序都可以獨立變化

中介模式用一個中介對象封裝一系列的對象交互,中介者使各對象不需要顯示地相互作用,從而使其耦合松散,而且可以獨立地改變它們之間的交互
圖:

Mediator 定義統(tǒng)一的接口,用于各Colleague之間的通信;
ConcreteMediator 通過協(xié)調(diào)各Colleague實現(xiàn)協(xié)作行為,因此它必須依賴于各個Colleague;
Colleague 都知道Mediator,而且與其他的Colleague的時候,都通過Mediator協(xié)作。
中介者模式的優(yōu)點就是減少類間的依賴,把原有的一對多的依賴變成了一對一的依賴,Colleague只依賴Mediator,降低了類間的耦合。
最經(jīng)典的中介模式是MVC框架的運用,其中的C就是一個中介者,把M和V隔離開,協(xié)調(diào)M和V協(xié)同工作,把M運行的結(jié)果和V代表的視圖融合成一個前端可以展示的頁面,減少M和V的依賴關(guān)系

備忘錄模式在不破壞封裝性的前提下,捕獲一個對象的內(nèi)部狀態(tài),并在該對象之外保存這個狀態(tài),這樣以后就可將該對象恢復(fù)到原先保存的態(tài)
圖:

Originator 記錄當前時刻的內(nèi)部狀態(tài),負責定義哪些屬于備份范圍的狀態(tài),負責創(chuàng)建和恢復(fù)備忘錄數(shù)據(jù);
Memento 負責存儲Originator發(fā)起人對象的內(nèi)部狀態(tài),在需要的時候提供發(fā)起人需要的內(nèi)部狀態(tài);
Caretaker 對備忘錄進行管理、保存和提供備忘錄。
最經(jīng)典的備忘錄模式就是jdbc的事務(wù)功能,因為要提供回滾,所以必然要用備忘錄模式。

訪問者模式封裝一些作用于某種數(shù)據(jù)結(jié)構(gòu)中的各元素的操作, 它可以在不改變數(shù)據(jù)結(jié)構(gòu)的前提下定義作用于這些元素的新的操作
圖:

Visitor 是抽象類或者接口,聲明訪問者可以訪問哪些元素,具體到程序中就是visit方法的參數(shù)定義哪些對象是可以被訪問的;
ConcreteVisitor 影響訪問者訪問到一個類后該怎么干,要做什么事情;
Element 接口或者抽象類,聲明接受哪一類訪問者訪問,程序上是通過accept方法中的參數(shù)來定義的;
ConcreteElement 實現(xiàn)accept方法,通常是visitor.visit(this),基本上都形成了一種模式了;
ObjectStruture Element產(chǎn)生者,一般容納在多個不同類、不同接口的容器,如List、 Set、 Map等,在項目中,一般很少抽象出這個角色。
訪問者模式可以將數(shù)據(jù)的構(gòu)成與使用方法解耦,擴展性很好。

省略的設(shè)計模式

組合模式說白了就是個樹形結(jié)構(gòu);
迭代器模式基本沒有人會自己實現(xiàn)了;
解釋器模式使用的很少;

附錄——六大設(shè)計模式原則

所有的設(shè)計模式無非都是這幾個原則的體現(xiàn)(當然有些會違背),這些原則指導(dǎo)著我們寫出更健壯、穩(wěn)定、易維護的程序。

單一職責原則:應(yīng)該有且僅有一個原因引起類的變更,但是這“一個原因”怎么定義需要我們根據(jù)業(yè)務(wù)自己拿捏

里氏替換原則:所有引用基類的地方必須能透明地使用其子類的對象,記住要確實有is-a的關(guān)系才用繼承,否則就使用依賴、聚集、組合的方式

依賴倒置原則:高層模塊不應(yīng)該依賴低層模塊(原子邏輯), 兩者都應(yīng)該依賴其抽象,抽象(接口)不應(yīng)該依賴細節(jié)(實現(xiàn)類),細節(jié)應(yīng)該依賴抽象,更加精簡的說法就是“面向接口編程”

接口隔離原則:類間的依賴關(guān)系應(yīng)該建立在最小的接口上,也就是說接口盡量細化

迪米特法則:也稱最少知識原則,一個對象應(yīng)該對其他對象有最少的了解,知道的越多耦合就越高就越不容易修改

開閉原則:一個軟件實體如類、模塊和函數(shù)應(yīng)該對擴展開放,對修改關(guān)閉,就是說我們的功能變化要通過擴展來實現(xiàn)而不是通過修改已有代碼實現(xiàn),這樣系統(tǒng)穩(wěn)定性才更高,也更靈活

感謝設(shè)計模式之禪與HeadFirst設(shè)計模式,這兩本書隨便選一本看完都可以。
閱讀原文,作者:MageekChiu

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/68768.html

相關(guān)文章

  • Java相關(guān)

    摘要:本文是作者自己對中線程的狀態(tài)線程間協(xié)作相關(guān)使用的理解與總結(jié),不對之處,望指出,共勉。當中的的數(shù)目而不是已占用的位置數(shù)大于集合番一文通版集合番一文通版垃圾回收機制講得很透徹,深入淺出。 一小時搞明白自定義注解 Annotation(注解)就是 Java 提供了一種元程序中的元素關(guān)聯(lián)任何信息和著任何元數(shù)據(jù)(metadata)的途徑和方法。Annotion(注解) 是一個接口,程序可以通過...

    wangtdgoodluck 評論0 收藏0
  • python能做什么軟件?Python到底能干嘛,一文看懂

    摘要:語料庫是由文本構(gòu)成的數(shù)據(jù)集通過提供現(xiàn)成的文本數(shù)據(jù)來輔助文本處理。那么可以用來做什么呢我自己是一名從事是不錯的入門選項。大數(shù)據(jù)和人工智能是機器學(xué)習和的主要開發(fā)語言。 Python培訓(xùn)有哪些內(nèi)容?很多零基礎(chǔ)學(xué)員不知道Python軟件是干什么用的?Python軟件是Python工程師編寫代碼時所需...

    YorkChen 評論0 收藏0
  • 一文讀懂 YUV 的采樣與格式

    摘要:接下來的不同采樣格式都是在一張圖像所有像素的轉(zhuǎn)換到基礎(chǔ)上進行的。采樣采樣,意味著分量是分量采樣的一半,分量和分量按照的比例采樣。基于采樣的格式基于采樣的格式主要有和兩種類型,每個類型又對應(yīng)其他具體格式。YUV 是一種顏色編碼方法,和它等同的還有 RGB 顏色編碼方法。 RGB 顏色編碼 RGB 三個字母分別代表了 紅(Red)、綠(Green)、藍(Blue),這三種顏色稱為 三原色,將它們...

    tracy 評論0 收藏0

發(fā)表評論

0條評論

PrototypeZ

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<