9. [TD]: [ui] katmanının bir konsol programı ile uygulaması
Anahtar kelimeler: çok katmanlı mimari, Spring, bağımlılık enjeksiyonu.
![]() |
9.1. Support
![]() |
[1]'te, [support / chap-09] klasörü, konsol uygulamasının [UI] katmanına ait Eclipse projesini içerir.
9.2. Maven Yapılandırması
[elections-ui-metier-dao-jdbc] Eclipse projesi, aşağıdaki [pom.xml] Maven dosyası ile yapılandırılmıştır:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>istia.st.elections</groupId>
<artifactId>elections-ui-metier-dao-jdbc</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>elections-ui-metier-dao-jdbc</name>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.2.7.RELEASE</version>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<!-- iş süreci -->
<dependency>
<groupId>istia.st.elections</groupId>
<artifactId>elections-metier-dao-jdbc</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<!-- Spring Boot -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot</artifactId>
<scope>test</scope>
</dependency>
<!-- Spring Boot Testi -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<!-- eklentiler -->
<build>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<archive>
<manifest>
<mainClass>config.AppConfig</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</plugin>
<!-- proje artefaktının yerel Maven deposuna kurulması için -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.18.1</version>
</plugin>
</plugins>
</build>
</project>
- 22-26. satırlar: [métier] katmanının arşivi ve buna bağlı olarak [DAO] katmanının arşivi içe aktarılır;
9.3. Spring Yapılandırması
![]() |
[UiConfig] sınıfı, Spring uygulamasını yapılandırır:
package elections.ui.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Import;
import elections.metier.config.MetierConfig;
@Import(MetierConfig.class)
@ComponentScan(basePackages = { "elections.ui.service" })
public class UiConfig {
}
- 8. satır: [métier] katmanında tanımlanan bean'ler içe aktarılır. Bu katman, [DAO] katmanında tanımlanan bean'leri zaten içe aktarmıştı. Dolayısıyla burada üç katmanın bean'lerine erişim sağlanır;
- 9. satır: [elections.ui.service] paketi başka bean'ler içerir;
9.4. [UI] katmanının arayüzü
![]() |
[UI] katmanının Java arayüzünün ne olabileceğini anlamak için, bu arayüzü kimin kullanacağını bilmemiz gerekir. Bu, yukarıdaki şemadaki kullanıcı değil, uygulamayı bir bütün olarak başlatacak programdır.
![]() |
[IElectionsUI] arayüzü, uygulamayı başlatacak olan ana program [main]'e sunulur. [main], [ui] katmanından ne isteyebilir? Seçimde eksik olan verileri girecek olan kullanıcıyla iletişime geçmesini isteyebilir. Aşağıdaki minimum arayüzü kullanacağız:
package istia.st.elections.ui;
public interface IElectionsUI {
/**
* lance le dialogue avec l'utilisateur
*/
public void run();
}
- 7. satır: Arayüzün tek bir yöntemi vardır: run. Bu yöntemi çağırarak, [ui] katmanından kullanıcıyla etkileşime başlaması istenir.
9.5. Uygulamanın başlatma sınıfı
![]() |
Uygulamanın başlatma sınıfı, [main] adlı statik bir yönteme sahip bir Java sınıfıdır. Bu yöntem, [ui, metier, demo] katmanlarının örneklerini oluşturmalı ve [ui] katmanından kullanıcıyla etkileşime geçmesini istemelidir. Bu sınıf, aşağıdaki [AbstractBootElections] sınıfı olabilir:
package elections.ui.boot;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import elections.dao.entities.ElectionsException;
import elections.ui.config.UiConfig;
import elections.ui.service.IElectionsUI;
public abstract class AbstractBootElections {
// Spring bağlamının alınması
protected AnnotationConfigApplicationContext ctx;
public void run() {
// [ui] katmanının örneklenmesi
IElectionsUI electionsUI = null;
try {
// Spring bağlamının alınması
ctx = new AnnotationConfigApplicationContext(UiConfig.class);
// [ui] katmanının alınması
electionsUI = getUI();
} catch (RuntimeException ex) {
// hata bildiriliyor
afficheExceptions("Les erreurs suivantes se sont produites :", ex);
// uygulama durduruluyor
System.exit(1);
}
// [ui] katmanının yürütülmesi
try {
electionsUI.run();
} catch (ElectionsException ex2) {
// hata bildiriliyor
afficheExceptions("Les erreurs suivantes se sont produites :", ex2);
// uygulama durduruluyor
System.exit(3);
} catch (RuntimeException ex1) {
// hata bildiriliyor
afficheExceptions("Les erreurs suivantes se sont produites :", ex1);
// uygulama durduruluyor
System.exit(2);
}
}
protected abstract IElectionsUI getUI();
private void afficheExceptions(String message, ElectionsException ex) {
// mesaj görüntüleniyor
System.out.println(String.format("%s -------------", message));
System.out.println(String.format("Code erreur : %d", ex.getCode()));
// hatalar görüntülenir
for (String erreur : ex.getErreurs()) {
System.out.println(String.format("-- %s", erreur));
}
}
public void afficheExceptions(String message, Exception ex) {
// mesaj görüntülenir
System.out.println(String.format("%s -------------", message));
// istisna yığını görüntülenir
Throwable cause = ex;
while (cause != null) {
System.out.println(String.format("-- %s", cause.getMessage()));
cause = cause.getCause();
}
}
}
- 19. satır: Spring bağlamı örneklenir: çeşitli yapılandırma dosyalarında tanımlanan tüm bean'ler oluşturulacaktır;
- 21. satır: [IElectionsUI] arayüzünü uygulayan bean'e bir referans alınır. [IElectionsUI] arayüzünü iki bean ile uygulayacağız:
- konsol uygulaması için [ElectionsConsole];
- Swing uygulaması için [ElectionsSwing];
[getUI] yöntemi soyuttur (44. satır). Nitekim, [AbstractBootElections] sınıfı iki sınıfın üst sınıfı olacaktır:
- [BootElectionsConsole], üst sınıfına [ElectionsConsole] bean'ini sağlayacak;
- [BootElectionsSwing], üst sınıfına [ElectionsSwing] bean'ini sağlayacaktır;
- 30. satır: arayüzün [run] yöntemi yürütülür;
İstisnalar çeşitli yerlerde yönetilir:
- 22-27. satırlar: Spring bağlamının örneklendirilmesi sırasında bir istisna meydana gelebilir;
- satır 31-41: [UI] katmanının yürütülmesi sırasında bir istisna meydana gelebilir. İki tür istisna ayırt edilir:
- [DAO] katmanının tetiklediği [ElectionsException] sınıfı;
- çalıştırma sırasında ortaya çıkabilecek diğer istisnalar için [RuntimeException] sınıfı;
[BootElectionsConsole] sınıfı, konsol uygulamasını başlatan sınıftır. Kod şöyledir:
package elections.ui.boot;
import elections.ui.service.IElectionsUI;
public class BootElectionsConsole extends AbstractBootElections{
public static void main(String[] arguments) {
new BootElectionsConsole().run();
}
@Override
protected IElectionsUI getUI() {
return ctx.getBean("electionsConsole",IElectionsUI.class);
}
}
- 5. satırda, [BootElectionsConsole] sınıfı, [AbstractBootElections] sınıfını genişletir. Bu nedenle, üst sınıfı tarafından soyut olarak bildirilen [getUI] yöntemini uygulamalıdır;
- 10-13. satırlar: [getUI] yönteminin uygulanması;
- 12. satır: [electionsConsole] adlı bean'in [IElectionsUI] arayüzünü uyguladığı belirtilir. [ctx], üst sınıfta şu bildirimle tanımlanan Spring bağlamıdır:
// Spring bağlamını al
protected AnnotationConfigApplicationContext ctx;
Alan, [protected] özniteliğine sahip olduğu için alt sınıflarda görülebilir.
- satırdaki bean şu şekilde tanımlanacaktır:
@Component
public class ElectionsConsole implements IElectionsUI {
Bu bean'in varsayılan adı, sınıf adının ilk harfi küçük harfle yazılmış halidir. Aşağıdaki gibi açıkça yazarak bu varsayılan addan kurtulabilirsiniz:
Swing uygulamasını çalıştıracak [BootElectionsSwing] sınıfı şu şekilde olabilir:
package elections.ui.boot;
import elections.ui.service.IElectionsUI;
public class BootElectionsSwing extends AbstractBootElections {
public static void main(String[] arguments) {
new BootElectionsSwing().run();
}
@Override
protected IElectionsUI getUI() {
return ctx.getBean("electionsSwing", IElectionsUI.class);
}
}
Sınıfların ortak davranışlarını bir üst sınıfta birleştirip, alt sınıfların kendilerine özgü ayrıntıları uygulamalarına izin verilen bu tasarım modeline Strategy tasarım modeli denir. Bu tasarım modeli, tüm alt sınıflara ortak bir davranış dayatır.
9.6. [ElectionsConsole] uygulama sınıfı
![]() |
[ui] katmanının ilk uygulama sınıfımız, kullanıcıyla iletişim kurmak için konsolu kullanan bir sınıf olacaktır. İşte Eclipse konsolunda elde edilen bir diyalog örneği:
Il y a 7 listes en compétition. Veuillez indiquer le nombre de voix de chacune d'elles :
Nombre de voix de la liste [A] : 2500
Nombre de voix de la liste [B] : 4500
Nombre de voix de la liste [C] : x
Nombre de voix incorrect. Veuillez recommencer
Nombre de voix de la liste [C] : 8000
Nombre de voix de la liste [D] : 12000
Nombre de voix de la liste [E] : 16000
Nombre de voix de la liste [F] : 25000
Nombre de voix de la liste [G] : 32000
Résultats de l'élection
[G,32000,2,false]
[F,25000,2,false]
[E,16000,1,false]
[D,12000,1,false]
[C,8000,0,false]
[B,4500,0,true]
[A,2500,0,true]
[ElectionsConsole] sınıfının iskeleti şu şekilde olabilir:
package elections.ui.service;
import java.util.Comparator;
import java.util.Scanner;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import elections.dao.entities.ListeElectorale;
import elections.metier.service.IElectionsMetier;
@Component
public class ElectionsConsole implements IElectionsUI {
@Autowired
private IElectionsMetier electionsMetier;
@Override
public void run() {
// verilerin girilmesi
try (Scanner clavier = new Scanner(System.in)) {
// [metier] katmanından rekabet halindeki listeler isteniyor
// oyların girilmesi
}
// koltuk hesaplaması yapılıyor
// sonuçlar kaydediliyor
// listeler oy sayısına göre azalan sırada sıralanıyor
// listeler görüntüleniyor
}
// seçim listelerinin karşılaştırma sınıfı
class CompareListesElectorales implements Comparator<ListeElectorale> {
// oy sayısına göre iki aday listesinin karşılaştırılması
@Override
public int compare(ListeElectorale listeElectorale1, ListeElectorale listeElectorale2) {
// bu iki listenin oyları karşılaştırılır
int nbVoix1 = listeElectorale1.getVoix();
int nbVoix2 = listeElectorale2.getVoix();
if (nbVoix1 < nbVoix2) {
return +1;
} else {
if (nbVoix1 > nbVoix2)
return -1;
else
return 0;
}
}
}
}
- 12. satır: [ElectionsConsole] sınıfı bir Spring bileşenidir;
- 13. satır: sınıf, [IElectionsUI] arayüzünü uygular
- 15-16. satırlar: Spring tarafından [metier] katmanına bir referans enjeksiyonu;
- satır 18-34: [IelectionsUI] arayüzünün [run] yöntemi;
21-28. satırlardaki try, try-with-resources olarak adlandırılır ve sözdizimi şöyledir:
- satırdaki kaynak, [java.lang.AutoCloseable] arayüzünü uygulamalıdır. Kaynak, 1. satırda açılır ve 3. satırdan sonra, bu iki satır arasında yürütülen kodda istisna olsun ya da olmasın, otomatik olarak kapatılır. Bu sözdizimi, ne olursa olsun açık bir kaynağın mutlaka kapatılmasını sağlar.
Yapılması gereken iş: [run] yönteminin kodunu yazın. Yorumlardan yararlanabilirsiniz.






