日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

使用实例工厂方法实例化_一些工厂实例

發(fā)布時間:2023/12/3 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 使用实例工厂方法实例化_一些工厂实例 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

使用實例工廠方法實例化

我時不時地發(fā)現(xiàn)自己摸索了一些舊代碼,找到了“我在哪里做過類似工廠的事情”的示例。

上周再次發(fā)生這種情況時,我決定只查找所有示例,并創(chuàng)建一個示例項目和有關(guān)該示例的博客文章。

所以在這篇文章中,我:

  • 從簡單的“原始” Java SE工廠示例開始
  • 然后使用Java SE SPI
  • Java SE上的CDI
  • Java EE上的 CDI
  • Java EE上的EJB
  • Java SE上的動態(tài)SPI
  • 最后是Java EE上的SPI

這個例子

這個示例應用程序是一個非常簡單的“ Hello World”,您可以輸入名稱,并且有多種表達問候的方法。

Greeting Service獲取Greeting Factory的實例。 然后,它可以按名稱要求工廠提供Greeting (接口),然后工廠將返回正確的實現(xiàn)。

有3種具體的實現(xiàn)方式:

  • English將打招呼“ Good day name” 。
  • Afrikaans將打招呼“ Goeie dag name” 。 (請參閱https://www.youtube.com/watch?v=CtxB4sbV0pA )
  • Bugs Bunny會打招呼“ Eeee, 叫什么名字 ?” (請參閱https://www.youtube.com/watch?v=UeVtZjGII-I )

Github中提供了此博客的所有源代碼 :

git clone https://github.com/phillip-kruger/factories-example

問候界面:

public interface Greeting {public String getName();public String sayHello(String to);}

香草

這個基本的Java SE應用程序有一個主要方法,可讓您傳遞名稱和想要的問候方式。

工廠是獲得正確實現(xiàn)的基本if-statement :

public Greeting getGreeting(String name){if(name.equalsIgnoreCase("BugsBunny")){return new BugsBunny();}else if(name.equalsIgnoreCase("Afrikaans")){return new Afrikaans();}else {return new English();}}

一個具體的實現(xiàn)示例, 英語 :

public class English implements Greeting {@Overridepublic String sayHello(String to) {return "Good day " + to + ".";}@Overridepublic String getName() {return "English";}}

運行示例:

vanilla文件夾中:

mvn clean install

這將構(gòu)建項目并運行該應用程序。 日志將輸出:

SEVERE: Good day Phillip.Goeie dag Phillip.Eeee, what's up Phillip ?

您也可以在Maven之外運行此命令:

java -jar target/vanilla-1.0.0-SNAPSHOT.jar World BugsBunnySEVERE: Eeee, what's up World ?

另見

  • https://alvinalexander.com/java/java-factory-pattern-example

服務提供商接口(SPI)

上面的示例意味著我可以非常輕松地添加另一個實現(xiàn),并在詢問時更新if statement以返回該實現(xiàn)。

但是,我們要改進的是if-statement 。 我們希望可以在不修改現(xiàn)有代碼的情況下添加新的實現(xiàn)。 我要做的就是添加新的實現(xiàn)。

SPI是Java SE的一部分,是允許您構(gòu)建可插入擴展的API。

將應用程序分解為模塊。

我們要做的第一件事是將應用程序分解為模塊 :

  • API –這將包含Greeting接口(我們的合同)
  • 引擎–其中將包含服務和工廠(以及默認的英語實現(xiàn))
  • 其他實現(xiàn)–所有其他實現(xiàn)都變成了自己的模塊(因此,一種用于南非荷蘭語,另一種用于Bugs Bunny等)

這已經(jīng)意味著我可以通過創(chuàng)建一個新模塊來添加新的實現(xiàn),而不必觸摸代碼,只需更新依賴項即可:

<dependencies><dependency><groupId>${project.groupId}</groupId><artifactId>spi-api</artifactId><version>${project.version}</version></dependency><dependency><groupId>${project.groupId}</groupId><artifactId>spi-impl-afrikaans</artifactId><version>${project.version}</version></dependency><dependency><groupId>${project.groupId}</groupId><artifactId>spi-impl-bugsbunny</artifactId><version>${project.version}</version></dependency></dependencies>

映射文件

具體的實現(xiàn)需要通過在/src/main/resources/META-INF/services/添加一個名為com.github.phillipkruger.factory.api.Greeting的文件來將其Greeting類注冊為實現(xiàn)(接口的完全限定名稱) )

文件的內(nèi)容是實現(xiàn)的名稱,例如Bugs Bunny :

com.github.phillipkruger.factory.impl.BugsBunny

該工廠

工廠現(xiàn)在需要獲取所有Greetings實例:

ServiceLoader<Greeting> loader = ServiceLoader.load(Greeting.class);Iterator<Greeting> greetingIterator = loader.iterator();while (greetingIterator.hasNext()) {Greeting greeting = greetingIterator.next();loadedGreetings.put(greeting.getName(), greeting);}

現(xiàn)在我們擺脫了工廠中的if-statement 。

運行示例:

spi文件夾中:

mvn clean install

這將構(gòu)建項目并運行該應用程序。 日志將輸出:

SEVERE: Good day Phillip.Goeie dag Phillip.Eeee, what's up Phillip ?

您也可以在Maven之外運行此命令:

java -jar spi-engine/target/spi-engine-1.0.0-SNAPSHOT-jar-with-dependencies.jar Johny AfrikaansSEVERE: Goeie dag Johny.

另見

  • https://docs.oracle.com/javase/tutorial/sound/SPI-intro.html

上下文和依賴注入(CDI)

最新版本的CDI允許您在Java SE中使用CDI。 為了創(chuàng)建工廠,我們將創(chuàng)建自己的注釋作為稱為GreetingProvider的API的一部分:

@Qualifier@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.TYPE)public @interface GreetingProvider {String value();}

value是實現(xiàn)的名稱。

以上的文字實現(xiàn) :

@AllArgsConstructorpublic class GreetingProviderLiteral extends AnnotationLiteral<GreetingProvider> implements GreetingProvider {private final String name;@Overridepublic String value() {return this.name;}}

這將允許我們使用@GreetingProvider注釋任何具體的實現(xiàn)(現(xiàn)在是RequestScoped CDI Bean),例如英語:

@GreetingProvider("English")@RequestScopedpublic class English implements Greeting {@Overridepublic String sayHello(String to) {return "Good day " + to + ".";}@Overridepublic String getName() {return "English";}}

工廠更改以查找所有@GreetingProvider類:

public class GreetingFactory {@Inject @Anyprivate Instance<Greeting> greetings;public Greeting getGreeting(String name) {Instance<Greeting> instance = greetings.select(new GreetingProviderLiteral(name));if(!instance.isUnsatisfied()){Greeting provider = instance.get();return provider;}else{return new English();}}}

因此,現(xiàn)在我們不再需要SPI映射文件,工廠中沒有if-statement ,但是我們?nèi)匀槐仨毟乱蕾図椧园璧乃袑崿F(xiàn)。

運行示例:

cdi文件夾中:

mvn clean install

這將構(gòu)建項目并運行該應用程序。 日志將輸出:

SEVERE: Good day Phillip.Goeie dag Phillip.Eeee, what's up Phillip ?

您也可以在Maven之外運行此命令:

java -jar cdi-engine/target/cdi-engine-1.0.0-SNAPSHOT-jar-with-dependencies.jar Charmaine BugsBunnySEVERE: Eeee, what's up Charmaine ?

另見

  • http://www.mastertheboss.com/jboss-frameworks/cdi/building-a-cdi-2-standalone-java-application
  • http://www.adam-bien.com/roller/abien/entry/injecting_classes_in_java_se

Java EE上的CDI

我們還可以使用CDI在Application Server上創(chuàng)建解決方案。 現(xiàn)在,我們將入口點設(shè)為REST服務(而不是主要方法),因此我們需要創(chuàng)建并添加ApplicationConfig來啟用JAX-RS:

@ApplicationPath("/api")public class ApplicationConfig extends Application {}

GreetingService現(xiàn)在成為REST資源,允許您執(zhí)行GET ,將名稱作為PathParam傳遞,以及可選的方式作為QueryParam進行問候:

@Path("/")@Produces(MediaType.APPLICATION_JSON)public class GreetingService {@Injectprivate GreetingFactory factory;@GET@Path("{to}")public String sayHello(@PathParam("to") String to, @QueryParam("way") List<String> way){//....}}

工廠和帶注釋的RequestScoped CDI Bean實現(xiàn)與Java SE示例上的CDI完全相同。

運行示例:

該示例可以在3個不同的應用程序服務器上運行(為誠實起見)

  • 野蜂群
  • 開放自由
  • Payara Micro

(您不必下載,安裝或配置任何東西,Maven構(gòu)建會做到這一點)

javaee-cdi文件夾中:

mvn clean install -P wildfly

要么

mvn clean install -P liberty

要么

mvn clean install -P payara

在所有3種情況下,maven都會:

  • 在部署了應用程序的情況下啟動應用程序服務器
  • 擊中2個REST網(wǎng)址:
    • http:// localhost:8080 / javaee-cdi-engine / api (此列表所有實現(xiàn))
  • 關(guān)閉應用程序服務器(Payara除外)

因此,在日志中,您將看到(類似):

=============================================== ["BugsBunny","Afrikaans","English"] ============================================================================================== ["Eeee, what's up Phillip ?","Goeie dag Phillip.","Good day Phillip."] ===============================================

如果運行Payara,則服務器不會關(guān)閉,因此您也可以手動測試工廠:

wget -qO- http://localhost:8080/javaee-cdi-engine/api/Donald?way=BugsBunny["Eeee, what's up Donald ?"]

Java EE上的EJB

只是為了完成示例,這是在Java EE上使用EJB的方法(因此沒有CDI,因此也沒有自定義注釋)

我們僅使用JNDI查找命名的EJB。

GreetingService與Java EE CDI示例相同,因此我們?nèi)匀挥幸粋€REST入口點。 現(xiàn)在,具體的實現(xiàn)變?yōu)镋JB,例如英語:

@Stateless@EJB(beanInterface = Greeting.class, beanName = "English", name = "English")public class English implements Greeting {@Overridepublic String sayHello(String to) {return "Good day " + to + ".";}@Overridepublic String getName() {return "English";}}

現(xiàn)在, 工廠基于Bean名稱進行JNDI查找:

@Log@Statelesspublic class GreetingFactory {@EJB(lookup = "java:module/English")private Greeting english; // defaultpublic Greeting getGreeting(String name) {Greeting g = lookup("java:module/" + name);if(g==null)return english;return g;}public List<Greeting> getAll(){List<Greeting> greetings = new ArrayList<>();try {InitialContext context = new InitialContext();NamingEnumeration<Binding> list = (NamingEnumeration<Binding>)context.listBindings("java:global/javaee-ejb-engine"); while (list.hasMore()) {Binding next = list.next();if(next.getName().endsWith(Greeting.class.getName())){Greeting g = lookup("java:global/javaee-ejb-engine/" + next.getName());if(g!=null && !greetings.contains(g))greetings.add(g);}}} catch (NamingException e) {throw new RuntimeException(e);} return greetings;}private Greeting lookup(String jndi){try {InitialContext context = new InitialContext();Object o = context.lookup(jndi);return (Greeting)o;} catch (NamingException e) {log.log(Level.SEVERE, "Could not lookup [{0}]", jndi);return null;} }}

運行示例:

與Java EE CDI示例類似,它在Wildfly Swarm , Open Liberty和Payara Micro上運行

javaee-ejb文件夾中:

mvn clean install -P wildfly

(或-P自由或-P payara)

在所有3種情況下,maven都會:

  • 在部署了應用程序的情況下啟動應用程序服務器
  • 擊中2個REST網(wǎng)址:
    • http:// localhost:8080 / javaee-ejb-engine / api (此列表列出了所有實現(xiàn))
  • 關(guān)閉應用程序服務器(Payara除外)

因此,在日志中,您將看到(類似):

=============================================== ["BugsBunny","Afrikaans","English"] ============================================================================================== ["Eeee, what's up Phillip ?","Goeie dag Phillip.","Good day Phillip."] ===============================================

如果運行Payara,則服務器不會關(guān)閉,因此您也可以手動測試工廠:

wget -qO- http://localhost:8080/javaee-ejb-engine/api/Barney?way=Afrikaans["Goeie dag Barney."]

動態(tài)SPI

到目前為止,添加新實現(xiàn)時,我們唯一要做的就是創(chuàng)建包含Greeting實現(xiàn)的模塊,并更新pom.xml以包含新的依賴項。

接下來,讓我們看看如何動態(tài)加載新的實現(xiàn)(因此無需更新依賴項)。

實現(xiàn)完全類似于Java SE SPI示例,包括映射文件,但是現(xiàn)在我們可以刪除模塊作為pom.xml依賴項:

<dependencies><dependency><groupId>${project.groupId}</groupId><artifactId>dynamic-spi-api</artifactId><version>${project.version}</version></dependency><!-- This will be loaded dynamically<dependency><groupId>${project.groupId}</groupId><artifactId>dynamic-spi-impl-afrikaans</artifactId><version>${project.version}</version></dependency><dependency><groupId>${project.groupId}</groupId><artifactId>dynamic-spi-impl-bugsbunny</artifactId><version>${project.version}</version></dependency>--></dependencies>

工廠看起來像這樣:

public class GreetingFactory {private final Map<String,Greeting> loadedGreetings = new HashMap<>();public GreetingFactory(){URLClassLoader classloader = getURLClassLoader();ServiceLoader<Greeting> loader = ServiceLoader.load(Greeting.class, classloader);Iterator<Greeting> greetingIterator = loader.iterator();while (greetingIterator.hasNext()) {Greeting greeting = greetingIterator.next();loadedGreetings.put(greeting.getName(), greeting);}}public Greeting getGreeting(String name){if(loadedGreetings.containsKey(name)){return loadedGreetings.get(name);}else {return new English();}}private URLClassLoader getURLClassLoader(){File[] pluginFiles = getPluginFiles();ArrayList<URL> urls = new ArrayList<>();for(File plugin:pluginFiles){try{URL pluginURL = plugin.toURI().toURL();urls.add(pluginURL);}catch(MalformedURLException m){log.log(Level.SEVERE, "Could not load [{0}], ignoring", plugin.getName());}}return new URLClassLoader(urls.toArray(new URL[]{}),GreetingFactory.class.getClassLoader());}private File[] getPluginFiles(){File loc = new File("plugins");File[] pluginFiles = loc.listFiles((File file) -> file.getPath().toLowerCase().endsWith(".jar"));return pluginFiles;}}

基本上,工廠仍將使用SPI的ServiceLoader加載可用的問候語,但我們傳入自定義的ClassLoader。我們在plugins文件夾中查找任何jar文件,并使用URLClassloader加載。

這意味著我現(xiàn)在可以只創(chuàng)建一個新的實現(xiàn)模塊并將文件放在plugins文件夾中。 美觀且可插拔。

運行示例:

dynamic-spi文件夾中:

mvn clean install

這將構(gòu)建項目并運行該應用程序。 日志將輸出:

SEVERE: Good day Phillip.Goeie dag Phillip.Eeee, what's up Phillip ?

您也可以在Maven之外運行此命令:

java -jar dynamic-spi-engine/target/dynamic-spi-engine-1.0.0-SNAPSHOT-jar-with-dependencies.jar Madonna BugsBunnySEVERE: Eeee, what's up Madonna ?

Java EE上的動態(tài)SPI

現(xiàn)在,這是否是一個好主意,將進行另外的討論,只是為了表明它是可能的,我們現(xiàn)在將使用動態(tài)SPI在應用程序服務器上加載實現(xiàn)。 這意味著我可以向正在運行的服務器添加新的實現(xiàn)。 因此,我不僅可以在不接觸代碼或依賴項的情況下添加新的實現(xiàn),而且還可以啟用該新實現(xiàn)而無需重新啟動應用程序。

這些實現(xiàn)完全類似于Java SE SPI示例, pom.xml不包含任何實現(xiàn)模塊,并且我們現(xiàn)在有了一個新類,可以將模塊加載到plugins文件夾中:

這是一個ApplicationScoped CDI Bean,可在啟動時加載模塊。 也可以使用REST重新加載模塊:

@Path("/pluginloader")@ApplicationScoped@Logpublic class PluginLoader {@Produces @Named("Greetings")private final Map<String,Greeting> loadedGreetings = new HashMap<>();public void init(@Observes @Initialized(ApplicationScoped.class) ServletContext context) {loadPlugins();}@GET@Path("/reload")public Response loadPlugins(){ClassLoader classloader = getClassLoader();ServiceLoader<Greeting> loader = ServiceLoader.load(Greeting.class, classloader);Iterator<Greeting> greetingIterator = loader.iterator();while (greetingIterator.hasNext()) {Greeting greeting = greetingIterator.next();log.log(Level.SEVERE, "Adding provider [{0}]", greeting.getName());if(!loadedGreetings.containsKey(greeting.getName())){loadedGreetings.put(greeting.getName(), greeting);}}return Response.ok("ok").build();}private ClassLoader getClassLoader(){File[] pluginFiles = getPluginFiles();if(pluginFiles!=null){ ArrayList<URL> urls = new ArrayList<>();for(File plugin:pluginFiles){try{URL pluginURL = plugin.toURI().toURL();urls.add(pluginURL);}catch(MalformedURLException m){log.log(Level.SEVERE, "Could not load [{0}], ignoring", plugin.getName());}}return new URLClassLoader(urls.toArray(new URL[]{}),this.getClass().getClassLoader());}return this.getClass().getClassLoader();}private File[] getPluginFiles(){File loc = getPluginDirectory();if(loc==null)return null;File[] pluginFiles = loc.listFiles((File file) -> file.getPath().toLowerCase().endsWith(".jar"));return pluginFiles;}private File getPluginDirectory(){File plugins = new File("plugins");if(plugins.exists())return plugins; return null;}}

所有已加載的Greetings在Map<String,Greeting>中都可用,可以將其注入工廠 :

@RequestScoped@Logpublic class GreetingFactory {@Inject @Named("Greetings")private Map<String,Greeting> greetings;// ...}

運行示例:

與Java EE CDI和EJB示例類似,它在Wildfly Swarm , Open Liberty和Payara Micro上運行

javaee-spi文件夾中:

mvn clean install -P wildfly

(或-P自由或-P payara)

在所有3種情況下,maven都會:

  • 在部署了應用程序的情況下啟動應用程序服務器
  • 擊中2個REST網(wǎng)址:
    • http:// localhost:8080 / javaee-spi-engine / api (此列表列出了所有實現(xiàn))
  • 關(guān)閉應用程序服務器(Payara除外)

因此,在日志中,您將看到(類似):

=============================================== ["BugsBunny","Afrikaans","English"] ============================================================================================== ["Eeee, what's up Phillip ?","Goeie dag Phillip.","Good day Phillip."] ===============================================

如果運行Payara,則服務器不會關(guān)閉,因此您也可以手動測試工廠:

wget -qO- http://localhost:8080/javaee-spi-engine/api/Frans?way=Afrikaans["Goeie dag Frans."]

當前,在plugins文件夾中,您將看到2個已知的實現(xiàn)(南非荷蘭語和Bugs Bunny):

ls javaee-spi-engine/plugins/javaee-spi-impl-afrikaans-1.0.0-SNAPSHOT.jar javaee-spi-impl-bugsbunny-1.0.0-SNAPSHOT.jar

當我們構(gòu)建這些實現(xiàn)時,將其復制到那里。

現(xiàn)在,讓服務器保持運行狀態(tài),并添加一種新的問候方式,稱為AliG。 (請參閱https://www.youtube.com/watch?v=b00lc92lExw )

cd javaee-spi-impl-aligmvn clean install -P plugin

這會將Ali G實現(xiàn)復制到plugins文件夾。

現(xiàn)在,讓我們再次問候Frans:

wget -qO- http://localhost:8080/javaee-spi-engine/api/Frans?way=AliG["Booyakasha Frans !"]

因此,我們可以向正在運行的服務器添加新的具體實現(xiàn)。

結(jié)束

就是這樣(現(xiàn)在)。 歡迎任何評論和您自己的示例!

翻譯自: https://www.javacodegeeks.com/2017/12/some-factory-examples.html

使用實例工廠方法實例化

創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎勵來咯,堅持創(chuàng)作打卡瓜分現(xiàn)金大獎

總結(jié)

以上是生活随笔為你收集整理的使用实例工厂方法实例化_一些工厂实例的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。