You are on page 1of 36

Pola Desain GoF

Sasaran
z Memperkenalkan dan menerapkan beberapa
pola desain GoF
z Menunjukkan prinsip-prinsip GRASP sebagai
generalisasi dari pola-pola desain lainnya

1
Adapter (GoF)
z Nama: Adapter
z Problem:
z Bagaimana menyatukan antarmuka-antarmuka
yang tidak compatible?
z Bagaimana menyediakan antarmuka yang stabil
pada komponen-komponen yang serupa dengan
antarmuka yang berbeda-beda?
z Solusi (Saran): Ubah antarmuka awal sebuah
komponen menjadi antarmuka lainnya
melalui objek adapter penengah

z Sistem NextGen POS perlu mendukung beberapa


jenis layanan third-party ekternal, meliputi
penghitung pajak, layanan otorisasi kartu kredit,
sistem inventori, sistem akuntansi, dan lain-lain.
z Masing-masing memiliki API yang berbeda dan tidak
dapat diubah.
z Solusi: menambahkan sebuah level indirection
dengan objek yang mengadaptasikan berbagai
interface eksternal ke sebuah interface yang
konsisten dalam aplikasi.

2
Penerapan Pola Adapter pada NextGen POS
«interface» Adapters use interfaces and
ITaxCalculatorAdapter polymorphism to add a level of
indirection to varying APIs in other
getTaxes( Sale ) : List of TaxLineItems components.

TaxMasterAdapter GoodAsGoldTaxPro
Adapter

getTaxes( Sale ) : List of TaxLineItems


getTaxes( Sale ) : List of TaxLineItems

«interface» «interface»
IAccountingAdapter ICreditAuthorizationService
Adapter
postReceivable( CreditPayment )
postSale( Sale ) requestApproval(CreditPayment,TerminalID, MerchantID)
... ...

«interface»
IInventoryAdapter
SAPAccountingAdapter GreatNorthernAccountingAdapter
...

postReceivable( CreditPayment ) postReceivable( CreditPayment )


postSale( Sale ) postSale( Sale )
... ...

Penggunaan Adapter

:Register : SAPAccountingAdapter

makePayment
...
SOAP over
HTTP

postSale( sale )
xxx «actor»
: SAPSystem

the Adapter adapts to


interfaces in other components

3
Prinsip GRASP sebagai Generalisasi
dari Pola-Pola Desain Lainnya

z Penggunaan pola Adapter dapat dianggap


sebagai spesialisasi dari beberapa prinsip
GRASP:
Adapter mendukung Protected Variations
berkaitan dengan pengubahan antarmuka-
antarmuka eksternal atau paket-paket third-
party melalui penggunaan objek Indirection
yang menerapkan interface dan
Polymorphism

Pattern Overload!

z Pattern Almanac 2000 mendaftarkan sekitar


500 pola desain dan masih terus bertambah
sampai saat ini.
z Bagaimana mempelajari/mengingat semuanya?
z Solusi: Lihat prinsip-prinsip yang mendasarinya.
z Banyak pola desain dapat dilihat sebagai
spesialisasi dari beberapa pinsip dasar GRASP.

4
Contoh: Adapter dan GRASP
Low coupling is a way to achieve protection at a Protected Variation GRASP
variation point. Mechanism Principles

Polymorphism is a way to achieve protection at a


variation point, and a way to achieve low coupling.

An indirection is a way to achieve low coupling. Low Coupling High Cohesion


Mechanism Mechanism
The Adapter design pattern is a kind of Indirection
and a Pure Fabrication, that uses Polymorphism.

Polymorphism Indirection Pure


Example Mechanism Fabrication

GoF Design
Adapter Patterns

Penemuan “Analisis” selama


Desain: Model Domain
z Dalam desain Adapter pada contoh NextGen
POS, operasi getTaxes mengembalikan
daftar TaxLineItems.
z Berdasarkan analisis bagaimana pajak
ditangani dan bagaimana kalkulator pajak
bekerja, disadari bahwa daftar item baris
pajak (tax line item) berhubungan dengan
penjualan. Contoh: (di US) state tax, federal
tax, dll.

5
Model Domain parsial yang
Telah Diperbaharui
... Sale
1
... dateTime

... Contains
1
Contains
...
1..* 1..*
...
Sales Tax
LineItem LineItem

quantity description
percentage
amount

Factory
z Disebut juga Simple Factory atau Concrete Factory
z Bukan merupakan pola desain GoF, namun banyak
digunakan.
z Merupakan penyederhanaan pola GoF Abstract
Factory.
z Pola ini menjawab permasalahan berikut:
z Pada solusi pola Adapter sebelumnya, siapa yang
membuat adapter-adapter tersebut?
z Bagaimana menentukan kelas adapter yang akan dibuat
(seperti TaxMasterAdapter atau
GoodAsGoldTaxProAdapter)?

6
z Jika beberapa objek domain membuat objek
adapter tersebut, tanggung jawab objek domain
tersebut menjadi keluar dari logika aplikasi murni
dan masuk ke dalam hal-hal yang berkaitan dengan
hubungan ke komponen-komponen software
eksternal.
z Pola desain dasar lainnya yang digarisbawahi ini
pada kasus ini adalah:
Desain untuk mempertahankan pemisahan
perhatian/tugas (separation of concerns).
Æ memodularkan perhatian yang berbeda dalam
area-area yang berbeda, sehingga masing-masing
memiliki fungsi yang kohesif

z Secara mendasar, prinsip tersebut


merupakan penerapan dari prinsip GRASP
High Cohesion.
z Memilih sebuah objek domain (seperti
Register) untuk membuat adapter-adapter
tidak mendukung sasaran pemisahan
concern dan memperkecil kohesinya.
z Solusi umum pada kasus ini adalah
menerapkan pola Factory, yang merupakan
objek Pure Fabrication “factory” untuk
membuat objek-objek

7
z Objek Factory memiliki beberapa
keuntungan:
z Memisahkan tanggung jawab pembuatan objek-
objek yang kompleks pada objek pembantu yang
kohesif
z Menyembunyikan logika pembuatan objek yang
mungkin kompleks
z Memperkenankan penerapan strategi manajemen
memori yang meningkatkan kinerja, seperti object
caching atau object recyling

z Nama: Factory
z Problem: Siapa yang harus bertanggung jawab
membuat objek-objek ketika ada beberapa
pertimbangan khusus, seperti logika pembuatan
objek yang kompleks, keinginan memisahkan
tanggung jawab pembuatan objek agar mencapai
kohesi yang lebih baik, dll?
z Solusi (Saran): Buat sebuah objek Pure Fabrication
yang disebut Factory yang menangani pembuat
objek-objek tersebut.

8
Pola Factory
ServicesFactory note that the factory methods
return objects typed to an
accountingAdapter : IAccountingAdapter interface rather than a class, so
inventoryAdapter : IInventoryAdapter that the factory can return any
taxCalculatorAdapter : ITaxCalculatorAdapter implementation of the interface

getAccountingAdapter() : IAccountingAdapter
getInventoryAdapter() : IInventoryAdapter
getTaxCalculatorAdapter() : ITaxCalculatorAdapter
...

if ( taxCalculatorAdapter == null )
{
// a reflective or data-driven approach to finding the right class: read it from an
// external property

String className = System.getProperty( "taxcalculator.class.name" );


taxCalculatorAdapter = (ITaxCalculatorAdapter) Class.forName( className ).newInstance();

}
return taxCalculatorAdapter;

z Pada ServicesFactory, logika untuk


memutuskan kelas mana yang akan dibuat
dicapai dengan membaca nama kelas dari
sumber luar (contoh: melalui properti sistem
pada Java) dan kemudian secara dinamis
me-load kelas tersebut.
Æ contoh Data-Driven Design

9
Singleton (GoF)
z ServicesFactory memunculkan masalah baru
dalam desain: Siapa yang membuat factory itu
sendiri, dan bagaimana mengaksesnya?
z Beberapa hal yang perlu diperhatikan:
1. Hanya ada satu instance factory yang dibutuhkan dalam
proses.
2. Metoda-metoda factory ini mungkin perlu dipanggil dari
berbagai tempat dalam kode sehingga membutuhkan
akses ke adapter-adapter untuk meminta layanan
eksternalnyaÆ masalah visibility: bagaimana
mendapatkan visibility pada sebuah instance tunggal
ServiceFactory?

z Beberapa solusi yang mungkin:


z melewatkan instance ServicesFactory sebagai
parameter ke manapun visibility dibutuhkan, atau
z menginisialisasi objek-objek yang membutuhkan
visitility ke instance tersebut dengan sebuah
referensi permanen
z Solusi alternatif: pola Singleton

10
Singleton
z Nama: Singleton
z Problem: Tepatnya hanya satu instance dari
sebuah kelas yang diperkenankan, yaitu
singleton. Objek-objek membutuhkan sebuah
titik akses global dan tunggal
z Solusi: Definisikan sebuah metoda static
pada kelas yang mengembalikan singleton

Pola Singleton dalam Kelas ServicesFactory


UML notation: this '1' can optionally be used to
indicate that only one instance will be created (a
singleton)

1
ServicesFactory

UML notation: in a instance : ServicesFactory singleton static


class box, an attribute
underlined attribute or accountingAdapter : IAccountingAdapter
method indicates a inventoryAdapter : IInventoryAdapter
static (class level) taxCalculatorAdapter : ITaxCalculatorAdapter
member, rather than singleton
an instance member getInstance() : ServicesFactory static
method
getAccountingAdapter() : IAccountingAdapter
getInventoryAdapter() : IInventoryAdapter
getTaxCalculatorAdapter() : ITaxCalculatorAdapter
...

// static method
public static synchronized ServicesFactory getInstance()
{
if ( instance == null )
instance = new ServicesFactory()
return instance
}

11
z Contoh:
public class Register {
public void initialize() {
… melakukan beberapa pekerjaan …

// mengakses singleton Factory via pemanggilan getInstance


accountingAdapter =
ServicesFactory.getInstance().getAccountingAdapter();

… melakukan beberapa pekerjaan …


}
// metoda-metoda lain...
}

Implementasi Dan Isu Desain

z Metoda Singleton getInstance sering digunakan.


z Pada aplikasi multithreading, tahap pembuatan dengan
logika lazy initialization merupakan bagian yang kritis,
membutuhkan kontrol thread concurrency.
z Jika instance kelas tersebut diinisialisasi belakangan
(lazy initialization), umumnya metoda dibungkus dengan
kontrol concurrency:
public static synchronized ServicesFactory getInstance() {
if ( instance == null ) {
// bagian yang kritis dalam aplikasi multithreading
instance = new ServicesFactory();
}
return instance;
}

12
z Eager initialization
public class ServicesFactory {

// eager initialization
private static ServicesFactory instance =
new ServicesFactory();

public static ServicesFactory getInstance() {


return instance;
}
// other methods...
}

Lazy vs Earger Initialization


z Pendekatan lazy initialization biasanya lebih
disukai karena:
z Pembuatan objek (khususnya yang
membutuhkan sumber daya yang mahal) dapat
dihindari jika objek tersebut tidak benar-benar
dibutuhkan
z Metoda getInstance pada strategi lazy
initialization terkadang mengandung logika
pembuatan objek yang kondisional dan kompleks

13
Pesan implisit getInstance dengan Pola
Singleton dinyatakan dalam UML dengan
Tanda ‘1’

1
:Register
:ServicesFactory

initialize
aa = getAccountingAdapter

the ‘1’ indicates that visibility


to this instance was achieved
...
via the Singleton pattern

Penerapan Pola Adapter, Factory,


dan Singleton pada Desain
1
:Store
:ServicesFactory

create
create :Register

accountingAdapter =
getAccountingAdapter
create : SAPAccounting
Adapter

accountingAdapter:
:Register
SAPAccountingAdapter

makePayment
create(cashTendered) : Payment SOAP over
HTTP

postSale( sale )
xxx «actor»
: SAPSystem

14
Strategy (GoF)
z Masalah desain berikutnya yang akan
dipecahkan adalah menyediakan logika
penetapan harga (pricing) yang lebih
kompleks, seperti diskon dari toko selama
satu hari, diskon untuk senior citizen, dll.
z Stategi pricing (disebut juga aturan,
kebijakan, atau algoritma) untuk satu
transaksi penjualan dapat bervariasi.
z Bagaimana merancang algoritma pricing
yang bervariasi ini?

z Nama: Strategy
z Problem:
z Bagaimana mendesain algoritma atau kebijakan
yang bervariasi namun berhubungan?
z Bagaimana mendesain kemampuan perubahan
algoritma atau kebijakan ini?
z Solusi (Saran): Definisikan setiap
algoritma/kebijakan/strategi dalam satu kelas
terpisah, dengan interface yang sama.

15
Kelas-Kelas Pricing Strategy
«interface»
ISalePricingStrategy

getTotal( Sale ) : Money

PercentDiscount AbsoluteDiscount ???


PricingStrategy OverThreshold PricingStrategy
PricingStrategy
percentage : float ...
discount : Money
getTotal( s:Sale ) : threshold : Money ...
Money
getTotal( s:Sale ) :
Money

{ {
return s.getPreDiscountTotal() * percentage pdt := s.getPreDiscountTotal()
} if ( pdt < threshold )
return pdt
else
return pdt - discount
}

z Objek strategy dilekatkan pada sebuah objek


konteks (context object), yaitu objek yang
menerapkan algoritma tersebut.
z Contoh: Pada NextGen POS, objek
konteksnya adalah sebuah Sale.
Ketika pesan getTotal dikirimkan ke Sale, ia
mendelegasikan beberapa tugasnya pada
objek strateginya.

16
Strategi dalam Kolaborasi
lineItems[ i ] : :PercentDiscount
s : Sale
SalesLineItem PricingStrategy

t = getTotal
{ t = pdt * percentage }
loop st = getSubtotal

t = getTotal( s )

pdt = getPreDiscountTotal note that the Sale s is


passed to the Strategy so
that it has parameter
visibility to it for further
collaboration

Objek konteks umumnya melewatkan sebuah referensi


dirinya (this) pada objek strategi tersebut sehingga objek
strategi memiliki visibility pada objek konteks untuk
kolaborasi berikutnya.

Objek Konteks Memerlukan Visibility


Atribut ke Objek Strateginya
Sale needs attribute
visibility to its Strategy

Sale
«interface»
date 1 ISalePricingStrategy
...
pricingStrategy getTotal( Sale ) : Money
getTotal()
...

getTotal()
PercentDiscount AbsoluteDiscount
{
PricingStrategy OverThreshold
...
PricingStrategy
return pricingStrategy.getTotal( this ) percentage : float
discount : Money
} getTotal( Sale ) : Money threshold : Money

getTotal( Sale ) : Money

17
Membuat Objek Strategi
dengan Factory
z Ada beberapa algoritma atau strategi pricing
yang berbeda dan selalu berubah sepanjang
waktu.
z Masalah: Siapa yang membuat objek strategi
tersebut?
z Solusi: Gunakan pola Factory
ÆPricingStrategyFactory bertanggung jawab
membuat semua objek strategi yang
dibutuhkan aplikasi.

Factory untuk Objek-Objek


Strategi
1
PricingStrategyFactory

instance : PricingStrategyFactory

getInstance() : PricingStrategyFactory

getSalePricingStrategy() : ISalePricingStrategy
getSeniorPricingStrategy() : ISalePricingStrategy
...

{
String classN am e = System .getProperty( "salepricingstrategy.class.nam e" );
strategy = (ISalePricingStrategy) C lass.forNam e( classNam e ).new Instance();
return strategy;
}

18
Membuat Objek Strategi

1
:Register
:PricingStrategyFactory

makeNewSale
create :Sale

ps =
getSalePricingStrategy
create(percent) ps : PercentDiscount
PricingStrategy

Composite (GoF) dan Prinsip


Desain Lainnya
z Masalah menarik lainnya: Bagaimana kita
menangani kasus beberapa kebijakan pricing yang
konflik?
z Contoh: sebuah toko memiliki kebijakan berikut ini
yang berlaku efektif hari ini (Senin):
z Diskon 20% untuk senior
z Diskon 15% untuk pembelian di atas $400 bagi pelanggan
yang punya kartu anggota
z Pada hari senin, ada potongan $50 untuk pembelian di
atas $500
z Beli 1 kotak teh Sosro, mendapat diskon 15%
z Misalkan seorang senior yang juga memiliki kartu
anggota membeli satu kotak teh Sosro, dan $600
veggieburger.
Kebijakan pricing mana yang diterapkan?

19
z Untuk lebih jelasnya, strategi pricing yang dikenakan
pada penjualan berdasarkan tiga faktor:
z Perioda waktu (senin)
z Jenis pelanggan (senior)
z Produk barang tertentu yang dibeli (teh Sosro)
z Solusi masalah ini membutuhkan strategi
penyelesaian konflik.
z Biasanya toko menerapkan strategi penyelesaian
konflik “terbaik bagi pelanggan (harga terendah)”.
z Namun ini dapat saja berubah, misalkan pada
masa-masa kesulitan keuangan, toko dapat
menerapkan strategi penyelesaian konflik “harga
tertinggi”

z Nama: Composite
z Problem: Bagaimana memperlakukan
sekelompok struktur komposisi objek-objek
menggunakan cara yang sama (dengan
polimorfik) seperti objek non-komposit
(atomik)?
z Solusi: Definisikan kelas-kelas untuk objek-
objek komposit dan atomik sehingga
semuanya mengimplementasikan interface
yang sama

20
Pola Composite
{ All composites maintain a list of
... contained strategies. Therefore,
return pricingStrategy.getTotal( this ) define a common superclass
} CompositePricingStrategy that
defines this list (named strategies).

Sale
«interface» 1..*
date 1 ISalePricingStrategy
...
pricingStrategy getTotal( Sale ) : Money strategies
getTotal()
...

PercentageDiscount AbsoluteDiscount Composite


PricingStrategy OverThreshold PricingStrategy
PricingStrategy
percentage : float
discount : Money
getTotal( Sale ) : Money threshold : Money add( ISalePricingStrategy )
getTotal( Sale ) : Money
getTotal( Sale ) : Money

{ CompositeBestForCustomer CompositeBestForStore
return sale.getPreDiscountTotal() * PricingStrategy PricingStrategy
percentage
}

getTotal( Sale ) : Money getTotal( Sale ) : Money

{
lowestTotal = INTEGER.MAX
for each ISalePricingStrategy strat in pricingStrategies
{
total := strat.getTotal( sale )
lowestTotal = min( total, lowestTotal )
}
return lowestTotal
}

Kolaborasi dengan sebuah


Composite UML: ISalePricingStrategy is an interface, not a class;
this is the way in UML 2 to indicate an object of an
unknown class, but that implements this interface

lineItems[ i ] : :CompositeBestForCustomer strategies[ j ] :


s : Sale
SalesLineItem PricingStrategy : ISalePricingStrategy

t = getTotal

loop st = getSubtotal

t = getTotal( s )

{ t = min(set of all x) } loop x = getTotal( s )

the Sale object treats a Composite Strategy that contains


other strategies just like any other ISalePricingStrategy

Implementasi CompositePricingStrategy dan sub-subkelasnya dalam Java

21
Superkelas Abstrak, Metoda Abstrak,
dan Pewarisan dalam UML
UML notation: An abstract class is
shown with an italicized name Composite
PricingStrategy
abstract methods are also shown with
italics
add( ISalePricingStrategy )
getTotal( Sale ) : Money

CompositeBestForCustomer CompositeBestForStore
PricingStrategy PricingStrategy

getTotal( Sale ) : Money getTotal( Sale ) : Money

Membuat Banyak SalePricingStratey

z Dengan pola Composite, sekelompok strategi


pricing nampak dari objek Sale seperti
sebuah strategi pricing tunggal.
z Objek Composite tersebut yang mengandung
kelompok tersebut juga
mengimplementasikan interface
ISalePricingStrategy.
z Masalah desain berikutnya: Kapan kita
membuat strategi-strategi ini?

22
z Desain yang diinginkan dimulai dengan membuat
objek Composite yang mengandung kebijakan
diskon toko saat ini, seperti:
PercentageDiscountPricingStrategy.
z Jika pada tahap selanjutnya, strategi pricing
lainnya diterapkan, tambahkan strategi tersebut
pada composite.
z Tiga titik dalam skenario di mana strategi pricing
dapat ditambahkan pada composite:
1. Diskon yang ditetapkan toko saat ini ditambahkan ketika
objek sale dibuat
2. Diskon berdasarkan jenis pelanggan ditambahkan ketika
jenis pelanggan dikomunikasikan pada POS
3. Diskon tipe produk ditambahkan ketika produk
dimasukkan dalam objek sale

Membuat Strategi Composite


1
:R egister :PricingStrategyFactory

m ake
N ew Sale
create :Sale

ps =
getSale
PricingStrategy
create
ps :C om positeBestForC ustom er
PricingStrategy

create( percent ) s : PercentageD iscount


PricingStrategy
add( s )

23
z Kasus kedua (diskon berdasarkan jenis
pelanggan) didasarkan pada use case berikut:

Use Case UC1: Process Sale

Extensions (or Alternative Flows):


5b. Customer says they are eligible for a discount
(e.g., employee, preferred customer)
1. Cashier signals discount request
2. Cashier enters Customer identification
3. System presents discount total, based on discount
rules.

z Ada indikasi operasi sistem yang baru Æ


enterCustomerForDiscount.
Dapat terjadi setelah operasi endSale.
z Pelanggan perlu diidentifikasi Æ customerID
dibaca melalui card reader atau via keyboard

24
Membuat strategi pricing untuk
diskon berdasar pelanggan (1)

by Expert and by Expert


by Controller IDs to Objects

:Register :Store s :Sale

enterCustomerForDiscount( custID )
c = getCustomer( custID )

enterCustomerForDiscount( c : Customer )
ref Enter Customer
For Discount

Membuat strategi pricing untuk


diskon berdasar pelanggan (2)
sd Enter Customer For Discount

by Factory and
by Expert
High Cohesion

1
:PricingStrategy ps :CompositeBestForCustomer
s :Sale
Factory PricingStrategy
enterCustomer
ForDiscount( c : Customer )
addCustomer Pass
PricingStrategy( s ) Aggregate
Object as
Parameter
c = getCustomer
by High Cohesion
ps = getPricing
by Expert
Strategy
pct =
getCustomer
Percentage( c )

create( pct ) s : PercentageDiscount


PricingStrategy
add( s )

by Factory and Composite

25
Façade (GoF)
z Kebutuhan lain yang dipilih pada iterasi ini
adalah aturan bisnis yang pluggable.
z Pada titik-titik yang dapat diprediksi dalam
skenario seperti ketika makeNewSale atau
enterItem terjadi pada use case Process
Sale, atau ketika kasir mulai menarik
bayaran, perilaku NextGen POS harus dapat
dikustomisasi.

z Misalkan aturan yang diinginkan adalah yang


dapat membuat suatu aksi tidak valid/berlaku,
contoh:
z Ketika suatu transaksi penjualan dibuat, sangat
mungkin transaksi tersebut dibayar dengan gift
certificate. Toko memiliki aturan memperkenankan
hanya satu item yang dapat dibeli jika menggunakan
gift certificate.
Konsekuensinya, operasi enterItem berikutnya
setelah yang pertama harus dibatalkan.

26
z Jika transaksi penjualan dibayar dengan gift
certificate, batalkan semua jenis pembayaran
uang kembalian kecuali untuk gift certificate
lainnya.
z Saat transaksi penjualan baru dibuat,
dimungkinkan penjualan itu untuk sumbangan.
Toko dapat memiliki aturan hanya
memperkenankan entri barang dengan harga
masing-masing kurang dari $250, dan hanya
memperkenankan entri item jika yang login
adalah “manager”

Pola Facade
z Nama: Facade
z Problem: Dibutuhkan sebuah antarmuka bersama
yang disatukan bagi sekumpulan implementasi atau
interface berbeda (seperti dalam suatu subsistem).
Ada coupling yang tidak diinginkan pada banyak hal
dalam subsistem tersebut, atau implementasi
subsistem tersebut dapat berubah. Apa yang harus
dilakukan?
z Solusi/saran: Definisikan titik kontak tunggal pada
subsistem tersebut, yaitu sebuah objek facade yang
membungkus subsistem itu.
Objek facade ini menyatakan sebuah interface yang
disatukan dan bertanggung jawab untuk
berkolaborasi dengan komponen-komponen
subsistem tersebut.

27
z Sebuah facade adalah objek front-end yang
merupakan titik masuk tunggal pada layanan-
layanan sebuah subsistem.
z Implementasi dan komponen-komponen
lainnya pada subsistem tersebut
disembunyikan dan tidak dapat dilihat oleh
komponen eksternal.
z Facade menyediakan Protected Variations
dari perubahan-perubahan dalam
implementasi sebuah subsistem.

z Kita mendefinisikan sebuah subsistem rule


engine yang implementasi spesifiknya belum
diketahui.
z Subsistem ini bertanggung jawab
mengevaluasi sejumlah aturan terhadap
sebuah operasi dan menyatakan apakah ada
aturan yang membatalkan operasi tersebut.
z Objek facade untuk subsistem ini adalah
POSRuleEngineFacade.

28
public class Sale {
public void makeLineItem( ProductDescription desc, int quantity ) {
SalesLineItem sli = new SalesLineItem( desc, quantity );
// call to the Facade
if ( POSRuleEngineFacade.getInstance().isInvalid( sli, this ) )
return;
lineItems.add( sli );
}
// ...
} // end of class

Diagram Package UML dengan sebuah


Facade
package name may be
shown in the tab
Domain

visibility of the package element (to


+ Sale + Register ... outside the package) can be shown
by preceding the element name with a
visibility symbol

POSRuleEngine

+ POSRuleEngineFacade «interface» ...


* - IRule
instance : RuleEngineFacade
...
getInstance() : RuleEngineFacade

isInvalid( SalesLineItem, Sale )


isInvalid( Payment, Sale )
...
- Rule1 - Rule2

... ...

29
z Facade sering diakses via Singleton.
z Dengan desain ini, kompleksitas dan
implementasi bagaimana aturan akan
direpresentasikan dan dievaluasi
disembunyikan dalam subsistem rule engine
yang diakses melalui facade
POSRuleEngineFacade..

Observer/Publish-
Subscribe/Delegation Event Model
(GoF)
z Kebutuhan lain pada iterasi ini adalah
menambah kemampuan window GUI untuk
me-refresh tampilan total harga penjualan.
Goal: When the total of the sale
changes, refresh the display with
the new value

Sale

total
...

setTotal( newTotal )
...

30
z Prinsip Pemisahan Model-View menyatakan objek
model (objek-objek non-UI seperti Sale) tidak
seharusnya mengetahui objek-objek View atau
presentasi seperti window.
z Prinsip ini mendukung Low Coupling dari layer lain
ke layer presentasi (UI).
z Konsekuensinya: layer view atau presentasi dapat
diganti yang lain tanpa mempengaruhi objek-objek
non-UI.
z Dengan demikian, prinsip ini mendukung Protected
Variation berkaitan dengan UI yang dapat berubah.
z Untuk itu, pola Observer dapat digunakan.

Pola Observer
z Nama: Observer (Pengamat)
z Problem: Beberapa jenis objek pelanggan
(subscriber) yang berbeda berminat pada perubahan
keadaan atau event pada objek penerbit (publisher),
dan mau beraksi dengan cara sendiri yang unik
ketika penerbit membangkitkan event. Lebih lanjut,
penerbit ingin mempertahankan low coupling pada
pelanggan.
z Solusi/saran: definisikan sebuah interface pelanggan
(subscriber) atau pendengar(listener). Penerbit
secara dinamis dapat mendaftarkan pelanggan-
pelanggan yang berminat pada suatu event dan
memberitahukan mereka ketika event tersebut
terjadi.

31
Pola Observer
{ {
for each PropertyListener pl in propertyListeners propertyListeners.add( lis );
pl.onPropertyEvent( this, nam e, value ); }
}

Sale

addPropertyListener( PropertyListener lis )


publishPropertyEvent( nam e, value )

setTotal( M oney new Total )


...
{
total = new Total;
publishPropertyEvent( "sale.total", total );
}

javax.swing.JFram e propertyListeners
*
... «interface»
setTitle() PropertyListener
setVisible()
... onPropertyEvent( source, nam e, value )

{
if ( nam e.equals("sale.total") )
saleTextField.setText( value.toString() );
}
SaleFram e1

onPropertyEvent( source, nam e, value ) {


sale.addPropertyListener( this )
initialize( Sale sale ) ...
... }

z Ide utama dan tahapan pada contoh ini adalah:


1. Sebuah interface didefinisikan Æ PropertyListener
dengan operasi onPropertyEvent
2. Definisikan window yang implementasikan
interface tersebut Æ SaleFrame1
3. Ketika window SaleFrame1 diinisialisasi, lewatkan
instance Sale yang harga totalnya akan
ditampilkan.
4. Window SaleFrame1 mendaftar atau
berlangganan (subscribe) ke instance Sale untuk
pemberitahuan property events melalui pesan
addPropertyListener.

32
5. Catat bahwa Sale tidak mengetahui objek
SaleFrame1, melainkan hanya mengetahui
objek-objek yang mengimplementasikan
interface PropertyListener. Ini memperkecil
coupling Sale ke window Æ coupling hanya ke
interface, bukan ke kelas GUI.
6. Instance Sale merupakan penerbit (publisher)
dari property events. Ketika harga total berubah,
Sale memberitahukan setiap objek
PropertyListener yang terdaftar.

Pengamat SaleFrame1
berlangganan pada penerbit Sale

sf : SaleFrame1 propertyListeners :
s : Sale
List<PropertyListener>

initialize( s : Sale )

addPropertyListener( sf )
add( sf )

33
Sale mempublikasikan sebuah property
event pada semua pelanggannya

s :Sale propertylisteners[ i ] :
PropertyListener

setTotal( total )
publishPropertyEvent
( "sale.total", total )

loop onPropertyEvent( s, "sale.total", total )

Pelanggan SaleFrame1 menerima


pemberitahuan dari event yang dipublikasikan

Since this is a polymorphic operation im plemented by


this class, show a new interaction diagram that starts saleTextField
: SaleFrame1
with this polymorphic version : JTextField

onPropertyEvent( source, name, value )

setText( value.toString() )

UM L notation: Note this little expression within the


parameter. This is legal and consise.

34
Siapa observer, listener,
subscriber, dan publisher?
Sale

addPropertyListener( PropertyListener lis ) publishes events to


publishPropertyEvent( name, value ) observers/listeners/
subscribers
setTotal( Money newTotal ) registers them when
... they ask to subscribe

javax.swing.JFrame propertyListeners
*
... «interface»
setTitle() PropertyListener
setVisible()
... onPropertyEvent( source, name, value )

listens for events


SaleFram e1 observes events
subscribes to notification of events
onPropertyEvent( source, nam e, value )

initialize( Sale sale )


...

Observer yang diterapkan pada event alarm


dengan subscriber yang berbeda-beda
{
for each Alarm Listener al in alarm Listeners
al.onAlarm Event( this, tim e );
} {
alarm Listeners.add( lis );
}
Alarm C lock

addAlarm nListener( Alarm Listener lis )


publishAlarm Event( tim e )

setTim e( new Tim e ) {


... tim e = new Tim e;
if ( tim e == alarm Tim e )
publishAlarm Event( tim e );
}
javax.sw ing.JFram e alarm Listeners
*
... «interface»
setTitle() Alarm Listener
setVisible()
... onAlarm Event( source, tim e )

Alarm W indow Beeper R eliabilityW atchD og

onAlarm Event( source, tim e ) onAlarm Event( source, tim e ) onAlarm Event( source, tim e )
... ... ...

{ {
{
display notification dialog check that all required processes
beep
box are executing norm ally
}
} }

35
Contoh implementasi
class PropertyEvent extends Event {
private Object sourceOfEvent;
private String propertyName;
private Object oldValue;
private Object newValue;
//...
}
//...
class Sale {
private void publishPropertyEvent(
String name, Object old, Object new ) {
PropertyEvent evt = new PropertyEvent(
this, "sale.total", old, new);
for each AlarmListener al in alarmListeners
al.onPropertyEvent( evt );
}
//...
}

36

You might also like