欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java管理對(duì)象方法總結(jié)

 更新時(shí)間:2019年05月05日 08:31:39   投稿:laozhang  
在本篇文章中小編給大家分享了關(guān)于Java管理對(duì)象方法以及相關(guān)代碼知識(shí)點(diǎn),需要的朋友們跟著學(xué)習(xí)下。

有一天晚上我腦海中突然冒出來一個(gè)問題:“怎樣管理我們代碼中的對(duì)象”。

小弈是剛工作時(shí)的我,他說:通過 new 來創(chuàng)建一個(gè)對(duì)象然后直接使用就好了啊。

public class HelloWorld {

public void hello() {

System.out.println("hello world!");

}

}

HelloWorld helloWorld = new HelloWorld();

helloWorld.hello();

你們看,我有一個(gè) HelloWorld 類,我用 new 就能直接創(chuàng)建一個(gè)對(duì)象,然后就能使用這個(gè)對(duì)象中所有的方法了,多簡(jiǎn)單啊。

二弈是工作兩年的我,他一臉鄙視的對(duì)小弈說,你別整天 HelloWorld 好不好,還有啊,除了 new 你就不會(huì)其他的了,能不能有點(diǎn)追求啊?

小弈對(duì)二弈說那你說除了 new 還有什么辦法啊?

二弈說可以通過 Class 的 newInstance 或者 Constructor 的 newInstance 來創(chuàng)建對(duì)象實(shí)例啊。

不過你得記住,Class 的 newInstance 只能對(duì)那些擁有可見的(Accessible)無(wú)參構(gòu)造函數(shù)的類,才能進(jìn)行對(duì)象的實(shí)例化,而 Constructor 就沒有這些限制。

大弈是工作三年的我,他說,雖然你們的方法都可以用來創(chuàng)建對(duì)象,但都還是手動(dòng)創(chuàng)建的,太原始了,生產(chǎn)力太低。

工欲善其事,必先利其器,我們也得找個(gè)高效的生產(chǎn)力工具。IOC 容器你們了解吧?

以前我們?cè)谝粋€(gè)對(duì)象中如果要調(diào)用另外一個(gè)對(duì)象的方法時(shí),都是通過 new 或者反射來手動(dòng)創(chuàng)建該對(duì)象,但是每次都這樣做太累了,并且類之間的耦合也很高。

通過 IOC 容器,我們可以把所有的對(duì)象交給容器來管理,在使用之前只需要定義一下對(duì)象,然后再使用到該對(duì)象時(shí),IOC 容器就會(huì)幫我們把該對(duì)象初始化好,這樣是不是更方便呢?

大弈說完,舉了一個(gè)例子:

@Bean

public class RegisterService {

public void register() {

// do register

}

}

@Bean

public class LoginService {

public void login() {

// do login

}

}

@Bean

public class HelloWorld {

@Autowired

private RegisterService registerService;

@Autowired

private LoginService loginService;

public void hello() {

// 注冊(cè)

registerService.register();

// ...

// 登錄

loginService.login();

}

}

IOC 容器通過一種叫 Bean 的注解,在系統(tǒng)啟動(dòng)時(shí)掃描所有通過 Bean 標(biāo)注的類,對(duì)這些類進(jìn)行實(shí)例化,然后將所有的對(duì)象都保存在容器中。再掃描所有通過 Autowired 標(biāo)注的屬性或者方法,從容器中找到與之匹配(通過名稱或者類型等)的對(duì)象將具體的對(duì)象賦值給這些屬性。這樣我們就可以直接將這些對(duì)象拿來使用了,作為一個(gè)伸手黨是不是很幸福啊。

老弈是工作五年的我,他聽了大弈的話后,提出了一個(gè)問題,對(duì)于新的項(xiàng)目可以使用這種 IOC 的容器,可是對(duì)于那些遺留的老項(xiàng)目來說,要使用 IOC 來改造是不太符合實(shí)情的。

我舉個(gè)例子,在一個(gè)遺留的老項(xiàng)目中,有一個(gè)核心的接口 Handler:

public interface Handler<REQ, RES> {

 RES handle(REQ request);

}

Handler 接口有很多的實(shí)現(xiàn)類,我們需要對(duì)不同的請(qǐng)求來調(diào)用不同的 Handler 實(shí)現(xiàn)類進(jìn)行處理,如果用 IOC 容器來管理這些實(shí)現(xiàn)類,顯然不太合適,因?yàn)槲覀兲幚碇笆遣恢涝撚媚膫€(gè) Handler 實(shí)現(xiàn)類的。

大弈想了想,如果 Handler 接口只有幾個(gè)固定的實(shí)現(xiàn)類,并且在使用時(shí)只會(huì)使用一個(gè)來進(jìn)行處理,那么倒是可以在啟動(dòng)前通過配置的方式來確定具體使用哪種 Handler ,比如可以通過 @Conditional 根據(jù)某些條件來確定加載具體的對(duì)象,但是這種要在使用時(shí)才能確定 Handler 對(duì)象的類型確實(shí)比較棘手。

老弈看大家都不說話了,就繼續(xù)說了下去。

為了要在調(diào)用方法時(shí)使用不同的 Handler 來處理不同的而請(qǐng)求,需要確定兩種類,一種是請(qǐng)求類,一種是處理類,并且要讓請(qǐng)求類和處理類一一對(duì)應(yīng)起來。

假設(shè)我們的請(qǐng)求類是一個(gè) Packet 類,每一個(gè)具體的請(qǐng)求類都繼承自這個(gè)基類。

那么想要確定每一個(gè)具體的 Packet 是什么類型的,可以有很多種方法,可以為每個(gè) Packet 取一個(gè)唯一的名字,例如:

public abstract class Packet {

  public abstract String name();

}

也可以為每一個(gè) Packet 指定一個(gè)標(biāo)志,例如:

public abstract class Packet {

  public abstract int symbol();

}

但是不管哪種方式,每一個(gè) Packet 的實(shí)現(xiàn)類都需要實(shí)現(xiàn)抽象類中的方法,來“標(biāo)志”自己是哪種 Packet。

我們以第二種方式舉例,假設(shè)我們有兩個(gè)具體的 Packet:

public class RegisterPacket extends Packet {

// 注冊(cè)所需要的其他參數(shù)

int symbol() {

return 1;

}

}

public class LoginPacket extends Packet {

// 登錄所需要的其他參數(shù)

int symbol() {

return 2;

}

}

這樣當(dāng)我們接收到 request 對(duì)象時(shí),通過調(diào)用 request.symbol() 就知道這個(gè) request 是哪種類型的 Packet 了,這時(shí)只要找到具體的 Handler 實(shí)現(xiàn)類來處理就可以了。

那請(qǐng)求類已經(jīng)可以確定了,怎樣確定 Handler 處理類呢?我們是否也可以在 Handler 接口中定義一個(gè) symbol 方法呢,像這樣:

public interface Handler<REQ, RES> {

  int symbol();

  RES handle(REQ request);

}

這樣的話,只要在所有的實(shí)現(xiàn)類中實(shí)現(xiàn) symbol 方法來標(biāo)注該 Handler 是用來處理何種 request 的即可。

public RegisterHandler implements Handler<RegisterPacket, RES> {

  int symbol(){

  return 1;

  }

  RES handle(RegisterPacket request){

  // 具體的處理方法

  }

}

public LoginHandler implements Handler<LoginPacket, RES> {

  int symbol(){

  return 2;

  }

  RES handle(LoginPacket request){

  // 具體的處理方法

  }

}

最后把所有的 Handler 實(shí)現(xiàn)類都實(shí)例化后保存在一個(gè) HandlerProvider 中,要使用時(shí)再到 HandlerProvider 中來獲取即可:

public interface HandlerProvider {

  Handler getHandler(int symbol);

}

那怎樣獲取到所有的 Handler 的實(shí)現(xiàn)類呢,有兩種方法。

一種是通過 ServiceLoader.load(Handler.class) 的方式來獲取,不過這種通過 spi 的方式需要在項(xiàng)目的 resources/META-INF/services/ 目錄下創(chuàng)建一個(gè) xxx.Handler 的文件,并在文件中將所有 Handler 的實(shí)現(xiàn)類的完全類限定符列出來。

另一種比較簡(jiǎn)單的方式是通過掃描的方式,獲取到所有 Handler 的實(shí)現(xiàn)類。

到現(xiàn)在為止,我們的實(shí)現(xiàn)還算可以,但是有一個(gè)問題,那就是在 Handler 接口中我們?cè)黾恿艘粋€(gè)方法,這樣做就對(duì)原來的代碼進(jìn)行了侵入。

為了讓原來的代碼保持不變,我們可以定義一個(gè)注解來標(biāo)注在所有的 Handler 實(shí)現(xiàn)類上,比如這樣:

@Symbol(1)

public RegisterHandler implements Handler<RegisterPacket, RES> {

  RES handle(RegisterPacket request){

  // 具體的處理方法

  }

}

@Symbol(2)

public LoginHandler implements Handler<LoginPacket, RES> {

  RES handle(LoginPacket request){

  // 具體的處理方法

  }

}

這樣就將 Handler 的實(shí)現(xiàn)和標(biāo)注進(jìn)行了解耦了,也可以通過掃描 @Symbol 注解來獲取到所有的 Handler 實(shí)現(xiàn)類,不過這樣做的缺點(diǎn)就是假如我忘記對(duì)某個(gè) Handler 實(shí)現(xiàn)類添加 @Symbol 注解,到時(shí)候就獲取不到該 Handler 了。

大家聽完老弈的話之后,都陷入了沉思,我靠,還可以這么玩,真有趣。

這時(shí)候現(xiàn)在的我,也就是逅弈,說了一句,如果我有一個(gè)接口,他只有幾個(gè)固定的實(shí)現(xiàn)類,我不想搞那一套那么重的實(shí)現(xiàn)方式,但是我也需要?jiǎng)討B(tài)的獲取實(shí)現(xiàn)類來對(duì)請(qǐng)求進(jìn)行處理,那我該怎么辦呢?

比如我有一個(gè)序列化的接口,如下所示:

public interface Serializer {

  byte[] serialize(Packet packet);

}

然后只有五種具體的序列化的實(shí)現(xiàn)類,如下所示:

public class JdkSerializer implements Serializer {

@Override

  public byte[] serialize(Packet packet) {

  // 具體的序列化操作

  }

}

public class FastJsonSerializer implements Serializer {

@Override

  public byte[] serialize(Packet packet) {

  // 具體的序列化操作

  }

}

public class HessianSerializer implements Serializer {

@Override

  public byte[] serialize(Packet packet) {

  // 具體的序列化操作

  }

}

public class KryoSerializer implements Serializer {

@Override

  public byte[] serialize(Packet packet) {

  // 具體的序列化操作

  }

}

public class ProtoStuffSerializer implements Serializer {

@Override

  public byte[] serialize(Packet packet) {

  // 具體的序列化操作

  }

}

那么我們?cè)撛趺创_定使用哪種序列化方式對(duì)參數(shù) packet 進(jìn)行序列化呢?

使用老弈剛剛說的那一套也確實(shí)能夠?qū)崿F(xiàn),不過太麻煩了,又得對(duì) Packet 定義 symbol,又得對(duì) Hander 實(shí)現(xiàn)類進(jìn)行標(biāo)注,還得掃描所有的實(shí)現(xiàn)類。

我只有五個(gè)實(shí)現(xiàn)類,不需要搞那么麻煩的。

其實(shí)很簡(jiǎn)單,只需要定義一個(gè)枚舉類,表示序列化的算法,然后對(duì) Packet 增加一個(gè) algorithm 方法用來表示,使用何種序列化算法,如下所示:

public enum SerializeAlgorithm {

  JDK((byte) 1),

  FAST_JSON((byte) 2),

  HESSIAN((byte) 3),

  KRYO((byte) 4),

  PROTO_STUFF((byte) 5);

  private byte type;

  SerializeAlgorithm(byte type) {

    this.type = type;

  }

}

public abstract class Packet implements Serializable {

public abstract byte algorithm();

}

然后定義一個(gè) SerializerChooser 根據(jù)不同的算法選擇不同的 Serializer 實(shí)現(xiàn)類即可:

public interface SerializerChooser {

  Serializer choose(byte algorithm);

}

因?yàn)楦鶕?jù)算法是可以知道對(duì)應(yīng)的序列化接口的,所以就沒有必要去掃描了,直接把幾種序列化的實(shí)現(xiàn)類枚舉出來即可,對(duì)象的實(shí)例可以使用單例模式,如下所示:

public class DefaultSerializerChooser implements SerializerChooser {

  private DefaultSerializerChooser() {

  }

  public static SerializerChooser getInstance() {

    return Singleton.get(DefaultSerializerChooser.class);

  }

  @Override

  public Serializer choose(byte algorithm) {

    SerializeAlgorithm serializeAlgorithm = SerializeAlgorithm.getEnum(algorithm);

    switch (serializeAlgorithm) {

      case JDK: {

        return Singleton.get(JdkSerializer.class);

      }

      case FAST_JSON: {

        return Singleton.get(FastJsonSerializer.class);

      }

      case HESSIAN: {

        return Singleton.get(HessianSerializer.class);

      }

      case KRYO: {

        return Singleton.get(KryoSerializer.class);

      }

      case PROTO_STUFF: {

        return Singleton.get(ProtoStuffSerializer.class);

      }

      default: {

        return null;

      }

    }

  }

}

我說完后,大家又一次陷入了沉思,我知道大家都在思考,他們會(huì)在每一次思考中獲得進(jìn)步和成長(zhǎng),正如我在思考后得到成長(zhǎng)一樣。

相關(guān)文章

  • Springboot?多租戶SaaS搭建方案

    Springboot?多租戶SaaS搭建方案

    這篇文章主要介紹了Springboot?多租戶SaaS方案,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-06-06
  • jpa多數(shù)據(jù)源時(shí)Hibernate配置自動(dòng)生成表不生效的解決

    jpa多數(shù)據(jù)源時(shí)Hibernate配置自動(dòng)生成表不生效的解決

    這篇文章主要介紹了jpa多數(shù)據(jù)源時(shí)Hibernate配置自動(dòng)生成表不生效的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-02-02
  • Java動(dòng)態(tài)規(guī)劃篇之線性DP的示例詳解

    Java動(dòng)態(tài)規(guī)劃篇之線性DP的示例詳解

    這篇文章主要通過幾個(gè)例題為大家詳細(xì)介紹一些Java動(dòng)態(tài)規(guī)劃中的線性DP,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)Java有一定的幫助,需要的可以參考一下
    2022-11-11
  • java 實(shí)現(xiàn)最小二叉樹堆排序的實(shí)例

    java 實(shí)現(xiàn)最小二叉樹堆排序的實(shí)例

    這篇文章主要介紹了java 實(shí)現(xiàn)最小二叉樹堆排序的實(shí)例的相關(guān)資料,希望通過本文能幫助到大家,需要的朋友可以參考下
    2017-09-09
  • Java實(shí)戰(zhàn)項(xiàng)目 醫(yī)院預(yù)約掛號(hào)系統(tǒng)

    Java實(shí)戰(zhàn)項(xiàng)目 醫(yī)院預(yù)約掛號(hào)系統(tǒng)

    本文是一個(gè)Java語(yǔ)言編寫的實(shí)戰(zhàn)項(xiàng)目,是一個(gè)醫(yī)院預(yù)約掛號(hào)系統(tǒng),主要用到了jdbc+jsp+mysql+ajax等技術(shù),技術(shù)含量比較高,感興趣的童鞋跟著小編往下看吧
    2021-09-09
  • MyBatis-Plus通用枚舉自動(dòng)關(guān)聯(lián)注入的實(shí)現(xiàn)

    MyBatis-Plus通用枚舉自動(dòng)關(guān)聯(lián)注入的實(shí)現(xiàn)

    本文主要介紹了MyBatis-Plus通用枚舉自動(dòng)關(guān)聯(lián)注入的實(shí)現(xiàn),解決了繁瑣的配置,讓 mybatis 優(yōu)雅的使用枚舉屬性,感興趣的可以一起來了解一下
    2021-06-06
  • 解決idea中javaweb的mysql8.0.15配置問題

    解決idea中javaweb的mysql8.0.15配置問題

    這篇文章主要介紹了idea中javaweb的mysql8.0.15配置問題 ,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2019-05-05
  • 基于ThreadPoolTaskExecutor的使用說明

    基于ThreadPoolTaskExecutor的使用說明

    這篇文章主要介紹了基于ThreadPoolTaskExecutor的使用說明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-11-11
  • Jmeter?BlazeMeter實(shí)現(xiàn)web錄制過程

    Jmeter?BlazeMeter實(shí)現(xiàn)web錄制過程

    BlazeMeter是一款與Apache JMeter兼容的chrome插件,采用BlazeMeter可以方便的進(jìn)行流量錄制和腳本生成,作為接口測(cè)試腳本編寫的一個(gè)基礎(chǔ),這篇文章主要介紹了Jmeter?BlazeMeter實(shí)現(xiàn)web錄制,需要的朋友可以參考下
    2021-12-12
  • MyBatis SqlMapConfig.xml配置

    MyBatis SqlMapConfig.xml配置

    MyBatis 的核心配置文件SqlMapConfig.xml,接下來通過本文給大家介紹MyBatis SqlMapConfig.xml配置,非常不錯(cuò),感興趣的朋友一起學(xué)習(xí)吧
    2016-08-08

最新評(píng)論