Strategy pattern cung cấp một cơ chế để tách biệt các lớp client từ sự thi công chi
tiết của một thuật toán cụ thể hoặc một chiến lược nào đó. Thường thì tất cả các lớp riêng
rẽ mà thi công strategy đã thi công một interface riêng để cho phép client được tách biệt
ra với các thi công khác.
66 trang |
Chia sẻ: lvcdongnoi | Lượt xem: 2548 | Lượt tải: 0
Bạn đang xem trước 20 trang tài liệu Đồ án Môn học nghiên cứu về aop, để xem tài liệu hoàn chỉnh bạn click vào nút DOWNLOAD ở trên
ính chất của khái niệm aspect tương tự khái niệm class
Aspect có thể chứa các thuộc tính và phương thức
Aspect chứa các thuộc tính truy cập: private, public, protected ..
Aspect có thể khai báo như một aspect trừu tượng:
public abstract aspect AbstractLogging {
public abstract pointcut logPoints();
public abstract Logger getLogger();
before() : logPoints() {
getLogger().log(Level.INFO, "Before: " + thisJoinPoint);
}
}
Aspect có thể thừa kế class, abstract aspect và thi công các interface
public aspect BankLogging extends AbstractLogging {
public pointcut logPoints()
: call(* banking..*(..));
public Logger getLogger() {
return Logger.getLogger("banking");
}
}
Aspect có thể nhúng trong class và interface như một aspect nằm trong
Ngoài các tính chất tương tự class như trên, aspect cũng có một số đặc điểm khác so với
class như sau:
Aspect không thể khởi tạo trực tiếp
Aspect không thể thừa kế từ một aspect khác (không phải trừu tượng)
Aspect có thể được đánh dấu như quyền
3.2.6 Static crosscutting
Trong AOP chúng ta thường xuyên can thiệp vào các quan hệ đan xen động sử
dụng advice, và cũng cần thiết các hành động can thiệp vào các cấu trúc tĩnh. Trong khi
các concern đan xen động sẽ sửa đổi sự thực hiện các thủ tục của chương trình thì sự đan
xen tĩnh sẽ sửa đổi các cấu trúc như class, interface, các aspect khác và các hành vi tại
điểm dịch chương trình.
3.2.6.1 Giới thiệu thành viên
Aspect thường xuyên giới thiệu các thành viên hoặc các phương thức vào trong
một lớp aspect . AspectJ cung cấp một có chế được gọi là introduction để giới thiệu các
thành viên vào trong các class hoặc interface. Đoạn mã dưới đây mô tả cách giới thiệu 2
thành viên là thuộc tính minimumBalance và phương thức getAvailable() vào lớp
Account. Các thành viên được giới thiệu vào một lớp cũng có thể được chỉ ra quyền truy
nhập như khai báo các thành viên của một lớp. Ví dụ từ khoá private chỉ ra thành viên chỉ
được truy cập từ aspect giới thiệu nó.
public aspect MinimumBalanceRuleAspect {
private float Account._minimumBalance;
public float Account.getAvailableBalance() {
return getBalance() - _minimumBalance;
}
after(Account account) :
execution(SavingsAccount.new(..)) && this(account) {
account._minimumBalance = 25;
}
before(Account account, float amount)throws InsufficientBalanceException :
execution(* Account.debit())&& this(account) && args(amount) {
if (account.getAvailableBalance() < amount) {
throw new InsufficientBalanceException(
"Insufficient available balance");
}
}
3.2.6.2 Sửa đổi cấu trúc thừa kế
Khi thực thi các quan hệ đan xen thường xuyên cần tác động đến tập các class
hoặc interface mà chúng có chung một kiểu cơ sở. AspectJ có thể sửa đổi cây thừa kế của
một lớp đã tồn tại để khai báo các lớp cha hoặc các interface của lớp đó miễn là không
ảnh hưởng đến qui luật thừa kế của Java.
Mẫu khai báo như sau:
declare parents : [ChildTypePattern] implements [InterfaceList];
declare parents : [ChildTypePattern] extends [Class or InterfaceList];
Ví dụ : Aspect khai báo tất cả các class và interface trong gói entities thực thi Identifiable
interface.
aspect AccountTrackingAspect {
declare parents : banking..entities.* implements Identifiable;
... tracking advices
}
3.3 Một số ứng dựng cơ bản của AOP
Dưới đây là một số ứng dụng điển hình sử dụng các ưu điểm của AOP trong việc thiết kế
và triển khai
1. Các kỹ thuật điều khiển, giám sát (monitor): Các kỹ thuật điều khiển, giám sát
như logging, tracing, profiling là những kỹ thuật chung để hiểu được các hành vi
xảy ra trong hệ thống. Ví dụ trong hệ thống nhà băng người quản trị muốn theo
dõi thông tin mỗi giao dịch trong hệ thống như tên tài khoản, thời gian giao dịch.
Vì các chức năng này xuyên suốt qua các module của ứng dụng nên khi triển khai
các kỹ thuật này với AOP là một cách tiếp cận tốt nhất có thể
2. Tăng cường chính sách (policy enforcement): Là một cơ chế bảo đảm các thành
phần trong hệ thống phải theo các quy tắc lập trình thực tế, tuân theo một số luật
cụ thể. Ví dụ bạn không thể gọi đến thư viên xử lý giao diện AWT trong mã của
EJB được.
3. Tối ưu hóa (resource pooling và caching): Khái niệm resource pooling và caching
chúng ta thường xuyên phải sử dụng trong các tình huống muốn tối ưu hóa ứng
dụng.
4 Giải quyết bài toán với AOP
Trong phần này chúng ta sẽ xem xét một số bài toán và một số giải pháp thực tiễn
để giúp một ứng dụng triển khai được trên AOP. Việc áp dụng một công nghệ mới để giải
quyết bài toán không bao giờ dễ dàng, đặc biệt khi bạn còn chưa nhìn thấy một hệ thống
nào triển khai thành công với công nghệ mới này. Chúng ta sẽ tìm hiểu cách sử dụng mô
hình hướng aspect như thế nào để giải quyết bài toán và các giải pháp về thiết kế.
Một khi thực sự chắc chắn muốn sử dụng AOP trong hệ thống phần mềm nào đó,
ta cần xác định tính thích hợp cho mỗi vấn đề khác nhau. Cần phải xem xét khả năng tối
thiểu các rủi ro của hệ thống. Chẳng hạn chúng ta có thể áp dụng AOP cho các module
con, sau khi chứng minh được khả năng của AOP, chúng ta sẽ tiếp tục triển khai trên các
module tiếp theo.
Mỗi pha trong quá trình phát triển phần mềm: thiết kế, thi công, test và bảo trì đều nhấn
mạnh tới một số hành động.
4.1 Sử dụng AOP trong bước thiết kế
Nếu sử dụng AOP trong bước thiết kế chúng ta sẽ có được nhiều sự thuận lợi mà
AOP đem lại. Từ quan điểm về kiến trúc, sự thuận lợi chính là giúp chúng ta vượt qua sự
bế tắc của các kiến trúc hiện tại.
Sau đây là một số bước điển hình sử dụng AOP trong pha thiết kế
1. Nhận biết các concern đan xen: Bước này là một phần trong việc ánh xạ các yêu
cầu người dùng tới các module. Một quy tắc là xem xét các concern được mô tả
với các tính tù hoặc trạng từ bắt đầu với từ “mọi”, ví dụ như mọi ngày, mọi
nơi…Nhận biết các concern này ban đầu sẽ giúp chúng ta tránh khỏi việc module
hoá các concern đan xen theo phương pháp truyền thống.
2. Thiết kế các concern lõi trước: Áp dụng các quy tắc và phương pháp truyền thống
để thiết kế các concern lõi. Công việc này càng làm tốt thì việc áp dụng các
concern đan xen sau này càng dễ.
3. Thiết kế các concern đan xen: Xác định các concern đan xen cần thiết, dễ thấy.
Lên một bộ khung cho các concern bạn cần và cũng có thể cả các concern bạn
chưa cần ngay lập tức.
4.2 Sử dụng AOP trong bước thi công
Khi sử dụng AOP trong bước thi công bạn nên nhấn mạnh vào trên một vài thực
tiễn có tính chất chung. Cũng như cần theo một số chỉ dẫn để việc thi công các concern
lõi và concern đan xen dẽ nhất có thể. Cũng có một số phương pháp refactoring theo mô
hình AOP bạn có thể sử dụng
1. Thực thi các concern lõi
a. Viết các concern lõi theo mô hình refactoring tốt nhất.
b. Sử dụng cách đặt tên nhất quán xuyên suốt ứng dụng
c. Tách biệt các concern đan xen từ các module trong bước đầu tiên.
d. Xem xét bất kỳ sự rải rác và chồng chéo mã chương trình
2. Thực thi các concern đan xen
a. Xác định các join point: Bước này cần xác định các vị trí trong mã chương
trình cần cho các quan hệ đan xen. Tiếp theo cần quyết định cách tốt nhất
để thể hiện các pointcut mà chúng sẽ chọn các join point
b. Lựa chọn các kỹ thuật sử dụng ở lớp dưới
c. Thiết kế các aspect
3. Thực hiện refactoring các aspect
4.3 Sử dụng AOP trong bước kiếm tra
AspectJ có thể trợ giúp nhiều nhiệm vụ trong bước kiếm tra, Sau đây là một kịch
bản điển hình mà chúng ta có thể bắt đầu thực hiện với AspectJ
1. Tạo các test case: Do AspectJ có khả năng sửa đổi các hành vi mà không cần sự
thay đổi thực sự nên AspectJ có thể trợ giúp để viết các chương trình kiểm tra.
2. Thực hiện kiểm tra hiệu năng hệ thống: Rất nhiều vấn đề chỉ được phát hiện ra
vào thời điểm triển khai hệ thống.AspectJ có thể bất chế độ theo dõi hiệu năng các
aspect, do đó chúng ta có thể xác định được kết quả gần với các hệ thống thực, và
chúng ta có thể quyết định sử dụng aspect hay không trên hệ thống triển khai để
tránh tràn bộ nhớ.
3. Báo cáo lỗi: Trong quá trình kiểm tra, khi chúng ta phát hiện ra các lỗi thì có thể
sử dụng aspect để chỉ ra các ngữ cảnh trong ứng dụng chứ không phải chỉ là ngăn
xếp của ngoại lệ được ném ra.
4.4 Sử dụng AOP trong giai đoạn bảo trì
Giai đoạn bảo trì hệ thống bao gồm hai thao tác chính sau
Thêm mới tính năng cho các yêu cầu mới
Sửa các lỗi được tìm thấy
AspectJ có thể điều khiển 2 bước sau trong giai đoạn bảo trì
Tạo một bức tường an toàn: Thêm các tính năng mới mà không làm đổ vỡ hệ
thống, Các chế độ tăng cường của aspect bảo đảm rằng các tính năng mới không
ảnh hưởng đến hệ thống cũng như tạo ra các lỗi mới
Thực thi các tính năng mới: AspectJ có thể thêm các quan hệ đan xen mới mà
không thay đổi trực tiếp trên mã nguồn gốc
5 Triển khai một số pattern trên AspectJ
Mẫu thiết kế (design pattern) được sử dụng rất nhiều khi phát triển một phần
mềm, nó giúp người phát triển giải quyết các vấn đề như điều khiển đối tượng, tái sử
dụng mã, tăng hiệu năng chương trình.
“Design Patterns: Elements of Reusable Object-Oriented Software” được biên
soạn bởi Erich Gamma, Richard Helm, Ralph Johnson, và John Vlissides là một cuốn
sách về design pattern đã được công nhận chính thức như một tài liệu thực tiễn cho mô
hình lập trình hướng đối tượng (OOP). Các mẫu thiết kế trong quyển sách này được chia
thành 3 loại, bao gồm: các mẫu thiết kế về cấu trúc đối tượng, hành vi đối tượng, và tạo
lập đối tượng. Các mẫu thiết kế được thực thi dựa trên cơ chế của các ngôn ngữ lập trình
hướng đối tượng đang có. Với mô hình lập trình hướng aspect, các mẫu thiết kế được xây
dựng với một số đặc điểm mới nhằm tận dụng được những ưu điểm của phương pháp
mới này.
5.1 Các mẫu thiết kế cho việc tạo đối tượng
5.1.1 Singleton pattern
5.1.1.1 Giới thiệu
Singleton pattern là một mẫu thiết kế để đảm bảo trong một phiên làm việc của
ứng dụng chỉ có duy nhất một thể hiện ( instance) của đối tượng vào lúc chạy. Mẫu thiết
kế này thường được sử dụng để quản lý thông tin của một phiên làm việc của một ứng
dụng.
Đối tượng không được khởi tạo trực tiếp trong chương trình (các hàm khởi tạo
của đối tượng được khai báo với từ khoá private) mà sẽ truy xuất qua một hàm static để
trả về thể hiện duy nhất của đối tượng.
public abstract aspect SingletonPattern issingleton( )
{
private Hashtable singletons = new Hashtable( );
public interface Singleton
{
}
public interface NonSingleton
{
}
// Pointcut định nghĩa các đối lớp cto define specify an interest in all creations
// of all Classes that extend Singleton
pointcut selectSingletons( ) : call((Singleton +).new (..));
// Pointcut bảo đảm bất kỳ lớp nào trong cây thừa kế được đánh dấu //là Non Singletons thì không
được gộp trong logic của Singleton
pointcut excludeNonSingletons( ) : !call((NonSingleton +).new (..));
Object around() : selectSingletons() && excludeNonSingletons( )
{
Class singleton = thisJoinPoint.getSignature().getDeclaringType( );
synchronized(singletons)
{
if (singletons.get(singleton) == null)
{
singletons.put(singleton, proceed( ));
}
}
return (Object) singletons.get(singleton);
}
}
Aspect trừu tượng Singleton định nghĩa 2 vai trò: Singleton và NonSingleton.
Các vai trò này được thi công bởi interface nên các aspect trừu tượng có thể làm việc với
singleton mà không cần lo lắng về cách thi công chi tiết.
Hình 8: Cấu trúc của aspect trừu tượng với interface và các hàm được định nghĩa để hỗ trợ
Singleton pattern
5.1.1.2 Sử dụng
Sau đây là ví dụ chỉ ra aspect SingletonPattern được sử dụng trong ứng dụng:
Hình 9:Một ứng dụng trước và sau khi được tác động bởi Singleton pattern
public aspect PrinterSingleton extends SingletonPattern
{
declare parents: Printer implements Singleton;
declare parents: SpecializedPrinter implements NonSingleton;
}
Hình sau minh hoạ hoạt động của ứng dụng khi gọi hàm in 2 lần, lần đầu khi
instance của Printer chưa có, nó sẽ được khởi tạo lần đầu. Lần tiếp theo khi instance đã
tồn tại, hàm in sẽ lấy tham chiếu đến instance đã được khởi tạo ở bước đầu tiên.
Hình 10: Các bước thực hiện của mẫu thiết kế Singleton trong ứng dụng
5.1.2 Prototype pattern
5.1.2.1 Giới thiệu
Prototype pattern được sử dụng hỗ trợ sao chép một đối tượng dựa trên đối tượng gốc.
public abstract aspect PrototypePattern
{
protected interface Prototype
{
}
public Object Prototype.clone() throws CloneNotSupportedException
{
return super.clone( );
}
public Object cloneObject(Prototype object)
{
try
{
return object.clone( );
}
catch (CloneNotSupportedException ex)
{
return createCloneFor(object);
}
}
protected Object createCloneFor(Prototype object)
{
return null;
}
}
Aspect PrototypePattern định nghĩa Prototype interface mà nó có thể ứng dụng
cho bất cứ lớp nào trong ứng dụng cụ thể mà nó được là một nguyên mẫu. Những lớp này
sẽ thừa kế với hàm clone() để hỗ trợ việc sao chép đối tượng.
Hình 11: Cấu trúc của PrototypePattern aspect
5.1.2.2 Sử dụng
public aspect GraphicPrototypes extends PrototypePattern
{
declare parents : Graphic implements Prototype;
declare parents : MusicalNote implements Prototype;
declare parents : Staff implements Prototype;
protected Object createCloneFor(Prototype object)
{
if (object instanceof MusicalNote)
{
return new MusicalNote(((MusicalNote) object).getX( ),
((MusicalNote) object).getY( ));
}
else if (object instanceof Staff)
{
return new Staff(((Staff) object).getX(), ((Staff) object).getY( ));
}
else
{
return null;
}
}
}
Hình 12:Một ứng dụng trước và sau khi được tác động bởi Prototype pattern
Hình 13: Sử dụng Prototype pattern trong ứng dụng
5.1.3 Abstract Factory pattern
Mẫu thiết kế này được sử dụng khi thao tác trên nhóm các lớp có quan hệ với
nhau trong khi nó che giấu sự thực thi các lớp này đối với client. Theo mô hình lập trình
OOP thì factory pattern cung cấp các lợi ích sau:
1. Client không cần phải quan tâm đến việc chọn một concrete class để tạo object
mà mình muốn.
2. Client không cần phải liên hệ trực tiếp với lớp thực thi cụ thể (concrete class) mà
thông qua interface hoặc abstract class.
3. Client không cần phải biết quá trình tạo object như thế nào
Mô hình của pattern được mô tả trong hình sau.
Hình 14: Lược đồ UML của AbstractFactory Pattern
Tạo một factory sử dụng aspect không mang ý nghĩa lắm bởi vì factory chứa các
phương thức cụ thể đến các đối tượng có thể được tạo. Ưu điểm duy nhất của AOP đối
với pattern này là khả năng loại bỏ sự nương tựa vào một lớp abstract cơ sở cho các
abstract factory và thay thế chúng với một interface đơn giản. Điều này có nghĩa là các
factory cụ thể có thể thừa kế từ lớp thích hợp khác hơn là sử dụng một quan hệ thừa kế
được phép để hỗ trợ mẫu thiết kế.
Đoạn mã AspectJ sau đây chỉ ra cách thực hiện pattern này.
public interface ComputerFactory
{
public Computer createPentiumProcessorComputer( );
public Computer createComputerWithHardDisk(HardDisk hardDisk);
}
public aspect DefaultComputerFactoryImplementation
{
public Computer ComputerFactory.createPentiumProcessorComputer( )
{
Processor processor = new Processor("Pentium 4 : 9089085043");
Motherboard motherboard = new Motherboard("019283", processor);
HardDisk hardDisk = new HardDisk("738947");
FloppyDisk floppyDisk = new FloppyDisk("93746");
Computer computer = new Computer("12345", motherboard, hardDisk, floppyDisk);
return computer;
}
public Computer ComputerFactory.createComputerWithHardDisk(HardDisk hardDisk)
{
Processor processor = new Processor("Pentium Standard : 123478");
Motherboard motherboard = new Motherboard("434244", processor);
FloppyDisk floppyDisk = new FloppyDisk("432434");
Computer computer = new Computer("56789", motherboard, hardDisk, floppyDisk);
return computer;
}
}
5.1.4 Factory Method pattern
Factory method pattern tương tự abstract factory khi nó cung cấp cơ chế mà sự thi
công cụ thể của các đối tượng được tách riêng từ các client của factory. Một phương thức
trừu tượng (Factory method ) cung cấp một phương thức để khởi tạo các instance khác
nhau của một interface.
Hình 15: Lược đồ UML của factory method pattern
Đoạn mã AspectJ sau mô tả cách thực hiện pattern này:
public interface ComputerCreator
{
public Computer createComputer(String serial);
}
public aspect DefaultComputerCreatorImplementation
{
public void ComputerCreator.createComputerAndPrintInventory(String serial)
{
System.out.println("Inventory of computerparts:");
System.out.println(this.createComputer(serial).toString( ));
}
}
Thường thì ComputerCreator trong pattern này là một lớp trừu tượng (abstract class). Tuy
nhiên các kỹ thuật về static crosscutting cung cấp mềm dẻo hơn khi sử dụng pattern này
bằng cách loại bỏ lớp trừu tượng cơ sở.
5.1.5 Builder pattern
5.1.5.1 Giới thiệu
Builder pattern được sử dụng để tạo một đối tượng cần đến một tập các bước thực
hiện phức tạp. Các bước này được thi công như những phương thức của lớp builder, sau
khi hoàn tất mỗi bước builder có thể được gọi để tạo đối tượng.
Builder pattern có các lợi ích sau:
1. Tách quá trình tạo một object ra bên ngoài bản thân class của object đó.
2. Tạo khả năng mềm dẻo trong việc đưa ra các implementation khác nhau cho qúa
trình tạo object
Để thực hiện Builder pattern trong AspectJ, cần tạo một aspect mà nó thêm vào
lớp cao nhất của lớp builder.
Ví dụ:
public interface TextPhraseBuilder
{
public void buildHeader(String title);
public void buildBody(String content);
public void buildFooter(String closingContent);
public String getResult( );
}
public aspect TextPhraseBuilderDefaultImplementation
{
public StringBuffer TextPhraseBuilder.result = new StringBuffer( );
public String TextPhraseBuilder.getResult( )
{
return result.toString( );
}
/**
* Declares a compiler error that gets reported if other classes
* (except Builders or this aspect) try to access the result variable.
*/
declare error : (
set(public StringBuffer TextPhraseBuilder +.result)
|| get(public StringBuffer TextPhraseBuilder +.result))
&& !(within(TextPhraseBuilder +)
|| within(TextPhraseBuilderDefaultImplementation)) :
"variable result is aspect protected. use getResult( ) to access it";
}
Aspect TextPhraseBuilderDefaultImplementation cung cấp một phương thức thi công
mặc định cho phương thức (). Sự tiện lợi này ..
Phương thức getResult() cung cấp sự truy cập đến trường result mà nó đã được thêm vào
interface và các lớp thực thi để cung cấp một nơi lưu giữ các kết quả của builder. Trường
result có thể nên khai báo quyền truy xuất là protected để nó chỉ được sử dụng trong bản
thân lớp chứa nó và các lớp con của nó.
5.2 Các mẫu thiết kế cho cấu trúc của đối tượng
5.2.1 Composite pattern
Composite pattern cung cấp khả năng nhóm các đối tượng cùng nhau trong một
tập hợp và tương tác với nhóm tương tự như cách thao tác với một đối tượng thành viên
độc lập của nhóm.
Composite pattern aspect định nghĩa giao diện Composite và Leaf để áp dụng vào
các ứng dụng cần sử dụng vai trò của 2 giao diện này. Aspect sử dụng Visitor pattern để
duyệt đệ quy và làm việc với các thành phần của composite.
Hình 16: Cấu trúc của CompositePattern aspect
public abstract aspect CompositePattern
{
public interface Component
{
}
protected interface Composite extends Component
{
}
protected interface Leaf extends Component
{
}
private WeakHashMap perComponentChildren = new WeakHashMap( );
private Vector getChildren(Component s)
{
Vector children = (Vector) perComponentChildren.get(s);
if (children == null)
{
children = new Vector( );
perComponentChildren.put(s, children);
}
return children;
}
public void addChild(Composite composite, Component component)
{
getChildren(composite).add(component);
}
public void removeChild(Composite composite, Component component)
{
getChildren(composite).remove(component);
}
public Enumeration getAllChildren(Component c) {
return getChildren(c).elements( );
}
public interface Visitor {
public void doOperation(Component c);
}
public void recurseOperation(Component c, Visitor v) {
for (Enumeration enum = getAllChildren(c); enum.hasMoreElements( );) {
Component child = (Component) enum.nextElement( );
v.doOperation(child);
}
}
public interface FunctionVisitor
{
public Object doFunction(Component c);
}
public Enumeration recurseFunction(Component c, FunctionVisitor fv)
{
Vector results = new Vector( );
for (Enumeration enum = getAllChildren(c); enum.hasMoreElements( );) {
Component child = (Component) enum.nextElement( );
results.add(fv.doFunction(child));
}
return results.elements( );
}
}
Ví dụ sử dụng:
public aspect GraphicsComposite extends CompositePattern
{
declare parents : Window implements Composite;
declare parents : Line implements Leaf;
declare parents : Rectangle implements Leaf;
public void Component.draw(PrintStream s)
{
s.println("Drawing: " + this);
}
public void Composite.draw(final PrintStream s)
{
s.println("Composite: " + this);
GraphicsComposite.aspectOf( ).recurseOperation(this, new Visitor( )
{
public void doOperation(Component c)
{
c.draw(s);
}
});
}
public void Leaf.draw(PrintStream s)
{
s.println("Drawing Leaf: " + this);
}
}
Hình 17: Mô hình các đối tượng trước khi áp dụng Composite pattern
Hình 18: Mô hình các đối tượng sau khi áp dụng Composite pattern
Hình 19: Hoạt động của composite pattern trong ứng dụng
5.2.2 Flyweight pattern
Mẫu thiết kế này hỗ trợ giảm sự chi tiết của các đối tượng trong hệ thống bằng
cách chia sẻ các đối tượng.
Hình 20: Cấu trúc của FlyweightPattern aspect
public abstract aspect FlyweightPattern
{
private Hashtable flyweightPool = new Hashtable( );
public interface Flyweight
{
};
protected abstract pointcut flyweightCreation(Object key);
Object around(Object key) : flyweightCreation(key) &&
!within(com.oreilly.aspectjcookbook.oopatterns.FlyweightPattern+)
{
return this.checkFlyweight(key);
}
public synchronized Flyweight checkFlyweight(Object key)
{
if (flyweightPool.containsKey(key))
{
return (Flyweight) flyweightPool.get(key);
}
else
{
Flyweight flyweight = createNewFlyweight(key);
flyweightPool.put(key, flyweight);
return flyweight;
}
}
protected abstract Flyweight createNewFlyweight(Object key);
}
Ví dụ sử dụng:
public aspect PrintableCharacterFlyweight extends FlyweightPattern
{
declare parents : PrintableCharacter implements Flyweight;
protected pointcut flyweightCreation(Object key) :
call(public com.oreilly.aspectjcookbook.PrintableCharacter.
new(Character)) && args(key);
protected Flyweight createNewFlyweight(Object key)
{
return new PrintableCharacter((Character) key);
}
}
5.2.3 Bridge Pattern
Mẫu thiết kế này tách riêng một lớp từ các tính chất của một thi công cụ thể mà
các lớp thực thi khác có thể áp dụng mà không cần tác động vào các lớp client.
public class Window
{
public void drawText(String text)
{
}
public void drawRect( )
{
}
}
public aspect XWindowBridge perthis(captureAllBridgedCalls( ))
{
private XWindow imp = new XWindow( );
public pointcut captureDrawText(String text) :
execution(public void Window.drawText(String))
&& args(text);
public pointcut captureDrawRect( ) : execution(public void Window.
drawRect( ));
public pointcut captureAllBridgedCalls( ) :
captureDrawText(String)
|| captureDrawRect( );
void around(String text) : captureDrawText(text)
{
imp.drawText(text);
}
void around( ) : captureDrawRect( )
{
imp.drawLine( );
imp.drawLine( );
imp.drawLine( );
imp.drawLine( );
}
}
Hình 21:Cấu trúc của XWindowBridge aspect
Ví dụ sử dụng:
Hình 22: Sử dụng các hành vi của lớp Window trong ứng dụng
5.2.4 Decorator pattern
Mẫu thiết kế này thừa các hành vi của một lớp trong khi duy trì public interface
mà không cần hiểu về lớp hoặc để tâm đến sự mở rộng.
public abstract aspect DecoratorPattern
{
public interface DecoratedComponent
{
};
private boolean DecoratedComponent.decorated = false;
public void DecoratedComponent.setDecorated(boolean decorated)
{
this.decorated = decorated;
}
public void DecoratedComponent.isDecorated(boolean decorated)
{
return this.decorated ;
}
}
Hình 23: Cấu trúc của DecoratorPattern aspect
Ví dụ sử dụng:
public aspect TextDisplayDecorator extends DecoratorPattern
{
declare parents : TextDisplay implements DecoratedComponent;
public pointcut selectDecorators(Object object) :
call(public void TextDisplay.display(String))
&& target(object);
before(Object object) : selectDecorators(object) &&
if(((DecoratedComponent)object).getDecorated)
{
System.out.print("");
}
after(Object object) : selectDecorators(object) &&
if(((DecoratedComponent)object).getDecorated)
{
System.out.print("");
}
}
Hình 24:Lớp TextDisplay trước và sau khi áp dụng DecoratorPattern
5.2.5 Adapter pattern
Mẫu thiết kế này giúp thay đối một thông điệp được gửi từ một đối tượng thành
một thông điệp được chấp nhận bởi đối tượng đích. Sự thích ứng thông điệp này phải gắn
với hai đối tượng.
public aspect PrinterScreenAdapter
{
declare parents : Screen implements Printer;
public void Screen.print(String s)
{
outputToScreen(s);
}
}
Hình 25: Áp dụng Adapter pattern
5.2.6 Proxy Pattern
Proxy Pattern cho phép người phát triển cung cấp một đối tượng đại diện cho một
đối tượng khác trong trường hợp đối tượng cần được đại diện hoặc được điều khiển.
Hình 26: Cấu trúc của ProxyPattern aspect
public abstract aspect ProxyPattern
{
protected interface Subject
{
}
protected abstract pointcut requestTriggered( );
private pointcut accessByCaller(Object caller) : requestTriggered( )
&& this(caller);
private pointcut accessByUnknown( ) : requestTriggered( )
&& !accessByCaller(Object);
Object around(Object caller, Subject subject) : accessByCaller(caller)
&& target(subject)
{
if (reject(caller, subject, thisJoinPoint))
{
return rejectRequest(caller, subject, thisJoinPoint);
}
else if (delegate(caller, subject, thisJoinPoint))
{
return delegateRequest(caller, subject, thisJoinPoint);
}
return proceed(caller, subject);
}
Object around(Subject subject) : accessByUnknown( )
&& target(subject)
{
// Without a caller then reject does not really make sense
// as there is no way of deciding to reject or not
if (delegate(null, subject, thisJoinPoint))
{
return delegateRequest(null, subject, thisJoinPoint);
}
return proceed(subject);
}
protected abstract boolean reject(
Object caller,
Subject subject,
JoinPoint joinPoint);
protected abstract boolean delegate(
Object caller,
Subject subject,
JoinPoint joinPoint);
protected abstract Object rejectRequest(
Object caller,
Subject subject,
JoinPoint joinPoint);
protected abstract Object delegateRequest(
Object caller,
Subject subject,
JoinPoint joinPoint);
}
Ví dụ sử dụng:
public aspect DelegationProxy extends ProxyPattern
{
declare parents : RealSubject implements Subject;
protected pointcut requestTriggered( ) : call(* RealSubject.write(..));
protected boolean reject(
Object caller,
Subject subject,
JoinPoint joinPoint)
{
return false;
}
protected boolean delegate(
Object caller,
Subject subject,
JoinPoint joinPoint)
{
return true;
}
protected Object rejectRequest(
Object caller,
Subject subject,
JoinPoint joinPoint)
{
return null;
}
protected Object delegateRequest(
Object caller,
Subject subject,
JoinPoint joinPoint)
{
Object[] args = joinPoint.getArgs( );
if (args != null)
{
AnotherRealSubject.write((String) args[0]);
}
else
{
AnotherRealSubject.write("");
}
return null;
}
}
5.3 Các mẫu thiết kế cho hành vi của đối tượng
5.3.1 Observer pattern
5.3.1.1 Giới thiệu
Mẫu thiết kế này dùng để định nghĩa mối quan hệ phụ thuộc 1:n giữa các đối
tượng, khi một đối tượng thay đổi trạng thái thì các đối tượng phụ thuộc nó được thông
báo và cập nhật một cách tự động.
Ví dụ chúng ta muốn duy trì quan hệ phụ thuộc giữa Employe và Department, khi
Employe thay đổi trạng thái thì Department phải được cập nhật và thông báo.
Chúng ta xây dựng aspect cho mẫu thiết kế này như sau: Định nghĩa 2 vai trò:
Subject và Observer. Khi chúng ta thừa kế aspect, chúng ta sẽ sử dụng các subaspect để
tác động những quyền đó vào Employe và Department. Nó cũng duy trì tập các ánh xạ
giữa các Subject và các Observer. Mỗi Subject có một hay nhiều các Observer. Các
aspect thừa kế có thể sử dụng addObserver() hoặc removeObserver() để tác động vào
danh sách ánh xạ
Hình 27: Cấu trúc của ObserverPattern aspect
public abstract aspect ObserverPattern
{
protected interface Subject
{
public void addObserver(Observer observer);
public void removeObserver(Observer observer);
}
protected interface Observer
{
public void notifyOfChange(Subject subject);
}
private List Subject.observers = new LinkedList( );
public void Subject.addObserver(Observer observer)
{
this.observers.add(observer);
}
public void Subject.removeObserver(Observer observer)
{
this.observers.remove(observer);
}
private synchronized void Subject.notifyObservers( )
{
Iterator iter = this.observers.iterator( );
while (iter.hasNext( ))
{
((Observer)iter.next( )).notifyOfChange(this);
}
}
protected abstract pointcut subjectChange(Subject s);
after(Subject subject) : subjectChange(subject)
{
subject.notifyObservers( );
}
}
5.3.1.2 Sử dụng Observer pattern
Để sử dụng được mẫu thiết kế này đầu tiên chúng ta cần phải xác định được yêu cầu bài
toán, cụ thể là cần trả lời những câu hỏi sau.
1. Đối tượng nào là Subject và đối tượng nào là Observer ?
2. Cái gì cấu tạo thành sự thay đối trong Subject
3. Cái gì cấu tạo thành sự cập nhật trong Observer
4. Khi nào Observer bắt đầu theo dõi Subject và khi nào dừng theo dõi
Ví dụ sau minh hoạ cách sử dụng Observer pattern
Hình 28: Cấu trúc lớp trước khi áp dụng ObserverPattern
Hình 29:Cấu trúc lớp sau khi áp dụng ObserverPattern
public aspect ConcreteClassAObserver extends ObserverPattern
{
declare parents : ConcreteClassB implements Subject;
declare parents : ConcreteClassA implements Observer;
protected pointcut subjectChange(Subject s) :
call(* ConcreteClassB.set*(..))
&& target(s);
public void ConcreteClassA.notifyOfChange(Subject subject)
{
this.doSomething(
"ConcreteClassA was notified of a change on " + subject);
}
}
Hình 30:Sử dụng ObserverPattern trong ứng dụng
5.3.2 Command Pattern
Command pattern hỗ trợ sự đóng gói các yêu cầu như các đối tượng trong phạm
vi những quyền của chúng. Các đơn hoặc đa thao tác có thể được kết hợp trong một yêu
cầu hoặc một giao tác phụ thuộc vào tuỳ từng mục đích của chúng. Khi đối tượng yêu cầu
được đã được xây dựng, nó có thể được quản lý như các thực thể tách rời từ đối tượng
ban đầu.
Command pattern được sử dụng trong các trường hợp sau
1. Hỗ trợ undo, logging, hoặc transaction
2. Hàng đợi và thực hiện các lệnh tại các thời điểm khác nhau
3. Tách biệt giữa nguồn của yêu cầu với đối tượng thực hiện yêu cầu
Hình 31: Cấu trúc của CommandPattern và các hàm hỗ trợ pattern
public abstract aspect CommandPattern
{
public interface Command
{
public void executeCommand(CommandReceiver receiver);
public boolean isExecutable( );
}
public interface CommandInvoker
{
}
public interface CommandReceiver
{
}
private WeakHashMap mappingInvokerToCommand = new WeakHashMap( );
public Object setCommand(CommandInvoker invoker, Command command)
{
return mappingInvokerToCommand.put(invoker, command);
}
public Object removeCommand(CommandInvoker invoker)
{
return setCommand(invoker, null);
}
public Command getCommand(CommandInvoker invoker)
{
return (Command) mappingInvokerToCommand.get(invoker);
}
private WeakHashMap mappingCommandToReceiver = new WeakHashMap( );
public Object setReceiver(Command command, CommandReceiver receiver)
{
return mappingCommandToReceiver.put(command, receiver);
}
public CommandReceiver getReceiver(Command command)
{
return (CommandReceiver) mappingCommandToReceiver.get(command);
}
protected abstract pointcut commandTrigger(CommandInvoker invoker);
after(CommandInvoker invoker) : commandTrigger(invoker)
{
Command command = getCommand(invoker);
if (command != null)
{
CommandReceiver receiver = getReceiver(command);
command.executeCommand(receiver);
} else
{
// Do nothing: This Invoker has no associated command
}
}
protected pointcut setCommandTrigger(CommandInvoker invoker,
Command command);
after(CommandInvoker invoker, Command command) : setCommandTrigger(
invoker, command)
{
if (invoker != null)
setCommand(invoker, command);
}
protected pointcut removeCommandTrigger(CommandInvoker invoker);
after(CommandInvoker invoker) : removeCommandTrigger(invoker)
{
if (invoker != null)
removeCommand(invoker);
}
public boolean Command.isExecutable( )
{
return true;
}
}
Ví dụ sử dụng command pattern
Hình 32: Trước khi áp dụng CommandPattern
Hình 33:Trước khi áp dụng CommandPattern
public aspect ConcreteCommand extends CommandPattern
{
declare parents : TimedEvent implements CommandInvoker;
declare parents : Printer implements CommandReceiver;
declare parents : VCardPrinter implements CommandReceiver;
declare parents : BusinessCard implements Command;
public void BusinessCard.executeCommand(CommandReceiver receiver)
{
if (receiver instanceof Printer)
{
((Printer) receiver).println(this.toString( ));
} else
{
((VCardPrinter) receiver).printVCard(this);
}
}
public void executeCommand(CommandReceiver receiver)
{
((Printer) receiver).println("Command triggered on printer receiver");
}
protected pointcut commandTrigger(CommandInvoker invoker) :
call(void TimedEvent.timedOut( ))
&& target(invoker);
}
Hình 34: Sử dụng CommandPattern trong ứng dụng
5.3.3 Iterator pattern
Iterator pattern cung cấp một cơ chế thi công tách biệt nhau của tập hợp các đối
tượng, mà qua đó chúng được truy cập một cách tuần tự. Biến lặp hay con trỏ được dịch
chuyển theo tập hợp các đối tượng trong khi giấu sự sắp xếp và thi công chi tiết của
người dùng với tập hợp đó.
Iterator pattern được sử dụng khi
1. Cung cấp một cách thức đồng bộ, nhất quán để duyệt qua các thành phần của
trong các danh sách đối tượng mà nó che giấu cách thực hiện thi công của từng
danh sách đó.
Hình 35: IteratorPatternAspect và interface định nghĩa vài trò của pattern
public abstract aspect IteratorPattern
{
public interface Aggregate
{
public Iterator createIterator( );
public Iterator createReverseIterator( );
}
}
Ví dụ:
public aspect EmployeeIteration extends IteratorPattern
{
declare parents : EmployeeCollection implements Aggregate;
public Iterator EmployeeCollection.createIterator( )
{
return new EmployeeIterator(this, true);
}
public Iterator EmployeeCollection.createReverseIterator( )
{
return new EmployeeIterator(this, false);
}
}
Hình 36: Mô tả sự tương tác của EmployeeIteration với ứng dụng
5.3.4 Mediator pattern
Mẫu thiết kế này giúp đơn giản quá trình trao đổi thông tin giữa các đối tượng
trong hệ thống bằng các tạo một lớp quản lý các thông điệp phân tán giữa các đối tượng
đó.
Hình 37: Cấu trúc của MediatorPattern aspect
public abstract aspect MediatorPattern
{
protected interface Colleague
{
}
protected interface Mediator
{
}
private WeakHashMap mappingColleagueToMediator = new WeakHashMap( );
private Mediator getMediator(Colleague colleague)
{
Mediator mediator =
(Mediator) mappingColleagueToMediator.get(colleague);
return mediator;
}
public void setMediator(Colleague c, Mediator m)
{
mappingColleagueToMediator.put(c, m);
}
protected abstract pointcut change(Colleague c);
after(Colleague c) : change(c)
{
notifyMediator(c, getMediator(c));
}
protected abstract void notifyMediator(Colleague c, Mediator m);
}
Ví dụ sử dụng Mediator pattern:
public aspect DialogMediator extends MediatorPattern
{
declare parents : ListBox implements Colleague;
declare parents : EntryField implements Mediator;
protected pointcut change(Colleague c) : (
execution(void ListBox.setSelection(..)) && this(c));
protected void notifyMediator(Colleague c, Mediator m)
{
ListBox listBox = (ListBox) c;
EntryField entryField = (EntryField) m;
entryField.setText(listBox.getSelection( ));
}
}
Hình 38: Trước và sau khi áp dụng Mediator pattern
5.3.5 Chain of Responsibility Pattern
Mẫu thiết kế này có ý nghĩa đúng như tên gọi của nó, được sử dụng để hỗ trợ
chuỗi các hành động nối tiếp nhau trong hệ thống. Mỗi bước thực hiện được quản lý bởi
một đối tượng và chịu trách nhiệm trên sự phân công chức năng của hệ thống.
Hình 39: Cấu trúc của ChainOfResponsibilityPattern aspect
public abstract aspect ChainOfResponsibilityPattern
{
protected interface Handler
{
}
public WeakHashMap successors = new WeakHashMap( );
protected void receiveRequest(Handler handler, Object request)
{
if (handler.acceptRequest(request))
{
handler.handleRequest(request);
}
else
{
// The handler will not accept the request
Handler successor = getSuccessor(handler);
if (successor == null)
{
// Last handler in the chain so must deal with the request
// This is a rudimentary implementation and more complex
// logic could be applied here or perhaps in the concrete
// aspects that extend this abstract one
handler.handleRequest(request);
}
else
{
// Hand the request on to the next successor in the chain
receiveRequest(successor, request);
}
}
}
public boolean Handler.acceptRequest(Object request)
{
// The default as defined here is to reject the request
// This is implemented by the application specific
// concrete aspects
return false;
}
public void Handler.handleRequest(Object request)
{
// A default empty implementation that is overridden
// if required by the application specific concrete aspects
}
protected abstract pointcut eventTrigger(Handler handler, Object request);
after(Handler handler, Object request) : eventTrigger(handler, request)
{
receiveRequest(handler, request);
}
public void setSuccessor(Handler handler, Handler successor)
{
successors.put(handler, successor);
}
public Handler getSuccessor(Handler handler)
{
return ((Handler) successors.get(handler));
}
}
Ví dụ sử dụng:
Hình 40: Sau khi áp dụng ChainOfResponsibilityPattern
public aspect HelpChain extends ChainOfResponsibilityPattern
{
declare parents : PrintButton implements Handler;
declare parents : PrintDialog implements Handler;
declare parents : Manager implements Handler;
protected pointcut eventTrigger(Handler handler, Object event) :
call(void PrintButton.doClick(..))
&& target(handler)
&& args(event);
private boolean Handler.alreadyHandledRequest = false;
public boolean Handler.acceptRequest(Object event)
{
return !this.alreadyHandledRequest;
}
public void PrintButton.handleRequest(Object event)
{
if (!this.acceptRequest(event))
{
System.out.println(
"PrintButton Forced to handle Request" +
"due to being last in the chain (Implementation Decision)");
}
System.out.println("PrintButton handling request: " + event);
this.alreadyHandledRequest = true;
}
public void PrintDialog.handleRequest(Object event)
{
if (!this.acceptRequest(event))
{
System.out.println(
"PrintDialog Forced to handle Request" +
"due to being last in the chain (Implementation Decision)");
}
System.out.println("PrintDialog handling request: " + event);
this.alreadyHandledRequest = true;
}
public void Manager.handleRequest(Object event)
{
if (!this.acceptRequest(event))
{
System.out.println(
"Manager Forced to handle Request due to being" +
"last in the chain (Implementation Decision)");
}
System.out.println("Manager handling request: " + event);
this.alreadyHandledRequest = true;
}
}
Hình 41:Sử dụng ChainOfResponsibilityPattern trong ứng dụng
5.3.6 Memento Pattern
Mẫu thiết kế này cung cấp một cơ chế để trạng thái ban đầu của một đối tượng có
thể được phục hồi sau một thời gian mà không cần gắn với một cơ chế cụ thể trong đó
trạng thái của đối tượng được thiết lập lại với đối tượng. Memento đóng gói tất cả thông
tin cần thiết để phục hồi trạng thái nội tại trước của một đối tượng tại thời điểm muộn
hơn. Khả năng này có thể được sử dụng để áp dụng thao tác undo trạng thái đối tượng
trong các ứng dụng cụ thể.
public abstract aspect MementoPattern
{
public interface Memento
{
public void setState(Originator originator);
public Object getState( );
}
public interface Originator
{
public void setMemento(Memento memento);
public Memento createMemento( );
public Object getState( );
}
Hình 42: Cấu trúc của MementoPattern aspect.
Ví dụ sử dụng Mememto:
public aspect EmployeeMemento extends MementoPattern
{
declare parents : Employee implements Originator;
public void Employee.setMemento(Memento memento)
{
Object object = memento.getState( );
Employee stateToRestore = (Employee) object;
this.setName(stateToRestore.getName( ));
this.setSalary(stateToRestore.getSalary( ));
}
public Memento Employee.createMemento( )
{
Memento memento = new DefaultMemento( );
memento.setState(this);
return memento;
}
public Object Employee.getState( ) throws MementoException
{
Employee employee = new Employee(this.getName( ), this.getSalary( ));
return employee;
}
}
Hình 43: Sử dụng MementoPattern trong ứng dụng
5.3.7 Visitor Pattern
Visitor Pattern trong mô hình OOP được sử dụng để thể hiện các hành động được
thực hiện trên các thành phần của cấu trúc đối tượng. Visitor cho phép định nghĩa thêm
các thao tác mà không cần thay đổi lớp của các thành phần mà nó thao tác trên đó. Với
mô hình AOP, điều này không thực sự có ý nghĩa lắm vì bản chất của AOP chính là sự
can thiệp vào các cấu trúc và hành vi của đối tượng.
Hình 44: Cấu trúc của Visitor pattern aspect
public abstract aspect VisitorPattern
{
public interface Element
{
public void accept(Visitor visitor);
}
public interface CompositeElement extends Element
{
public Element[] getElements( );
}
public interface Result
{
}
public interface Visitor
{
public void visitElement(Element element);
public void visitComposite(CompositeElement element);
public Result getResult( );
}
public void CompositeElement.accept(Visitor visitor)
{
visitor.visitComposite(this);
}
public void Element.accept(Visitor visitor)
{
visitor.visitElement(this);
}
}
Ví dụ sử dụng Visitor pattern:
public aspect InventoryVisitor extends VisitorPattern
{
declare parents : FloppyDisk implements Element;
declare parents : HardDisk implements Element;
declare parents : Processor implements Element;
declare parents : Computer implements CompositeElement;
declare parents : Motherboard implements CompositeElement;
declare parents : InventoryReport implements Result;
public Element[] Computer.getElements( )
{
Element[] elements = new Element[3];
elements[0] = this.getMotherboard( );
elements[1] = this.getHardDisk( );
elements[2] = this.getFloppyDisk( );
return elements;
}
public Element[] Motherboard.getElements( )
{
Element[] elements = new Element[1];
elements[0] = this.getProcessor( );
return elements;
}
}
Cấu trúc và quan hệ giữa các thành phần của Computeur
Hình 45: Cấu trúc của Computeur
Cấu trúc và quan hệ giữa các thành phần của Computeur sau khi áp dụng Visitor pattern
Hình 46: Cấu trúc Computeur sau khi áp dụng Visitor pattern
Hình 47:Sử dụng VisitorPattern trong ứng dụng
5.3.8 Strategy pattern
Strategy pattern cung cấp một cơ chế để tách biệt các lớp client từ sự thi công chi
tiết của một thuật toán cụ thể hoặc một chiến lược nào đó. Thường thì tất cả các lớp riêng
rẽ mà thi công strategy đã thi công một interface riêng để cho phép client được tách biệt
ra với các thi công khác.
public abstract aspect StrategyPattern
{
Hashtable strategyPerContext = new Hashtable( );
protected interface Strategy
{
}
protected interface Context
{
}
private Strategy Context.strategy = null;
public void setConcreteStrategy(Context c, Strategy s)
{
strategyPerContext.put(c, s);
}
public Strategy getConcreteStrategy(Context c)
{
return (Strategy) strategyPerContext.get(c);
}
}
Hình 48:Cấu trúc của StrategyPattern aspect
Ví dụ áp dụng:
public aspect SortingStrategy extends StrategyPattern
{
declare parents : Sorter implements Context;
declare parents : LinearSorter implements Strategy;
declare parents : BubbleSorter implements Strategy;
int[] around(Sorter s, int[] numbers) : call(int[] Sorter.sort(int[]))
&& target(s)
&& args(numbers)
{
Strategy strategy = getConcreteStrategy(s);
if (strategy instanceof BubbleSorter)
((BubbleSorter) strategy).sort(numbers);
else if (strategy instanceof LinearSorter)
((LinearSorter) strategy).sort(numbers);
return numbers;
}
}
Hình 49: Cấu trúc các lớp sắp xếp khi chưa áp dụng StrategyPattern
Hình 50: Cấu trúc các lớp sắp xếp sau khi áp dụng StrategyPattern
Hình 51: Sử dụng Strategy Pattern trong ứng dụng
5.3.9 State Pattern
State Pattern cung cấp một cơ chế cho đối tượng có thể biến đổi hành vi của nó
dựa trên các trạng thái của nó.
public aspect TCPConnectionState
{
protected TCPState listening = new TCPListen( );
protected TCPState acknowledged = new TCPAcknowledged( );
protected TCPState closed = new TCPClosed( );
after(TCPConnection connection) : initialization(new ( ))
&& target(connection)
{
listening.setConnection(new SocketConnection( ));
connection.setState(listening);
}
after(TCPConnection connection, TCPState state) : call(
void TCPState +.acknowledge( ))
&& target(state)
&& this(connection)
{
if (connection.getState( ) == listening)
{
acknowledged.setConnection(listening.getConnection( ));
connection.setState(acknowledged);
}
}
after(TCPConnection connection, TCPState state) : call(
void TCPState +.close( ))
&& target(state)
&& this(connection)
{
if ((connection.getState( ) == listening)
|| (connection.getState( ) == acknowledged))
{
connection.setState(closed);
}
}
}
TCPConnectionState aspect cho thấy lớp TCPConnection sẽ được lắng nghe khi nó được
tạo, được báo khi phương thức acknowledge() được gọi và đóng khi phương thức close()
được gọi.
Hình 52: Sử dụng state pattern trong ứng dụng
6 Kết luận
AOP đang thực sự trở thành phương pháp luận cho ngành công nghệ phần mềm
hiện nay. AOP đã được đưa vào nhiều ngôn ngữ, và trên thực tế AOP đã được triểnkhai
trên các ứng dụng thương mại như JBOSS application server phiên bản 4.0, Spring
Framework và đã đạt được một số kết quả ban đầu trong việc triển khai một ứng dụng
AOP cụ thể. Điểm mạnh của AOP là xây dựng các ứng dụng middleware bao gồm các
thao tác phức tạp như security, tracing, loging, transaction. .. Đặc biệt trong công nghệ
Enterprise Java Bean của Sun Microsystem, các nhà phát triển đã lên kế hoạch đưa AOP
vào trong đặc tả phiên bản EJB 3.0 tiếp theo. AOP có phải là một cuộc cách mạng trong
phương pháp lập trình hay không thì còn phải chờ vào những kết quả triển khai thực tế
của các sản phẩm hỗ trợ AOP.
Do thời gian có hạn, đồ án môn học này mới chỉ đi vào khía cạnh ngôn ngữ và
việc xây dựng lại các mẫu thiết kế (design pattern) trong mô hình OOP chuyển sang mô
hình AOP, tận dụng những đặc điểm mới của AOP. Đây là một trong những bước quan
trọng trong việc đưa AOP vào áp dụng trong các ứng dụng cụ thể.
Trong thời gian tới, đồ án sẽ tiếp tục đi sâu hơn nữa trong việc triển khai các ứng
dụng cụ thể trên AOP, những khó khăn và thách thức cho phương pháp lập trình mới này
Chúng em xin chân thành cảm ơn Thầy giáo Huỳnh Quyết Thắng đã định hướng
và cung cấp những kiến thức cơ bản cũng như những tài liệu báu để em có thể hoàn
thành tốt đồ án này.
7 Tài liệu tham khảo
1. Elements of Reusable Object-Oriented Software Addison Wesley - Erich
Gamma, Richard Helm, Ralph Johnson, John Vlissides - Addison Wesley,
1995
2. AspectJ CookBook- Russell Miles - O'Reilly 2004
3. AspectJ in Action-RAMNIVAS LADDAD-Manning publishing - 2004
4. Mastering AspectJ-Joseph D. Gradecki, Nicholas Lesiecki -Wiley publishing
5.
6.
7. - Aspect Oreinted Software development community &
conference
Các file đính kèm theo tài liệu này:
- doko_vn_1792931_mo_hinh_aop_7162.pdf