2009-12-29 40 views
8

Giới thiệu nhỏ:Lập trình và giao dịch hướng đối tượng

Lớp chứa các trường và phương thức (để tôi bỏ qua thuộc tính lần này).
Các trường đại diện cho trạng thái của lớp học.
Phương pháp mô tả hành vi của lớp học.

Trong một lớp được thiết kế tốt, một phương pháp sẽ không thay đổi trạng thái của lớp nếu nó ném một ngoại lệ, phải không? (Nói cách khác, bất cứ điều gì xảy ra, tình trạng lớp của nên không bị hỏng)

Câu hỏi:

Có một khuôn khổ, một mẫu thiết kế, thực hành tốt nhất hoặc một ngôn ngữ lập trình để gọi một chuỗi các phương pháp trong một giao dịch phong cách, để trạng thái của một trong hai lớp không được thay đổi (trong trường hợp ngoại lệ), hoặc mọi thứ thành công?

ví dụ .:

// the class foo is now in the state S1 
foo.MoveToState2(); 
// it is now (supposed to be) in the state S2 
foo.MoveToFinalState(); 
// it is now (supposed to be) in the state, namely, S3 

Chắc chắn, một ngoại lệ có thể xảy ra cả trong MoveToState2()MoveToFinalState(). Nhưng từ khối mã này tôi muốn lớp foo ở trạng thái S1 hoặc S3.

Đây là một kịch bản đơn giản với một lớp duy nhất liên quan, không có if 's, không có while' s, không có tác dụng phụ, nhưng tôi hy vọng ý tưởng là rõ ràng.

Trả lời

3

Không phải phương pháp hiệu quả nhất, nhưng bạn có thể có đối tượng thể hiện dữ liệu giao dịch của bạn. Khi bạn bắt đầu một giao dịch, tạo một bản sao dữ liệu và thực hiện tất cả các thao tác trên đó. Khi giao dịch kết thúc thành công, di chuyển bản sao sang dữ liệu thực của bạn - điều này có thể được thực hiện bằng cách sử dụng con trỏ, vì vậy không cần quá kém hiệu quả.

0

Tôi nghĩ rằng một Mẫu lệnh có thể rất phù hợp với vấn đề này. Linky.

1

Điều này sẽ khá xấu để triển khai ở mọi nơi, nhưng chỉ lưu trạng thái cục bộ, sau đó khôi phục trạng thái trong trường hợp ngoại lệ sẽ hoạt động trong các tình huống đơn giản. Bạn sẽ phải nắm bắt và trả lại ngoại lệ, điều này có thể mất một số ngữ cảnh ở một số ngôn ngữ. Nó có thể là tốt hơn để bọc nó nếu có thể để giữ lại bối cảnh.

try { 
    save state in local variables 
    move to new state 
} catch (innerException) { 
    restore state from local variables 
    throw new exception(innerException) 
} 
5

Hãy nhìn vào các Memento pattern

Các Memento pattern là một mẫu thiết kế phần mềm cung cấp khả năng để khôi phục lại một đối tượng trạng thái trước đó (undo qua rollback).

+1

Như tôi đã nói trong bài đăng của tôi, các vật lưu niệm được sử dụng nhiều hơn trong môi trường gui, cho sự kiên trì và hoàn tác/làm lại. Mặc dù khái niệm cơ bản là như nhau (tạo một lớp khác đại diện cho trạng thái), bạn không nên chuyển tiếp sang trạng thái mới cho đến khi nó hoàn toàn an toàn để làm như vậy. Điều đó gợi ý để cố gắng tạo ra trạng thái mới, và chỉ khi bước này thành công, thay đổi trạng thái trong trạng thái mới. – fabrizioM

2

Lập trình hàm là mô hình có vẻ phù hợp với tính toán giao dịch. Vì không có tác dụng phụ nào được phép mà không khai báo rõ ràng, bạn có toàn quyền kiểm soát tất cả luồng dữ liệu.

Do đó phần mềm bộ nhớ giao dịch thể được thể hiện một cách dễ dàng trong điều kiện chức năng - Xem STM for F#

Ý tưởng chính là khái niệm về monads.Một đơn nguyên có thể được sử dụng để lập mô hình một phép tính tùy ý thông qua hai nguyên thủy: Trả lại để trả về một giá trị và Ràng buộc để tính hai trình tự. Sử dụng hai phương pháp này, bạn có thể lập mô hình một đơn vị giao dịch kiểm soát và lưu tất cả trạng thái theo dạng tiếp tục.

Người ta có thể cố gắng mô hình hóa chúng theo cách hướng đối tượng thông qua mẫu State + Memento, nhưng nói chung, giao dịch bằng ngôn ngữ mệnh lệnh (như các OO phổ biến) khó triển khai hơn. - hiệu ứng. Nhưng tất nhiên bạn có thể nghĩ về một đối tượng xác định phạm vi giao dịch, tiết kiệm, xác nhận và khôi phục dữ liệu khi cần thiết, vì chúng lộ ra một giao diện phù hợp cho điều này (các mẫu mà tôi đã đề cập ở trên).

1

.) Bộ nhớ giao dịch phù hợp ở đây tốt nhất.

.) Một tùy chọn có thể là bộ nhớ giao dịch. thực hiện mẫu mà bạn có thể tìm thấy ở đây:.. http://www.codeproject.com/KB/dotnet/Transactional_Repository.aspx

) Memento pattern

) Ngoài ra hãy để tôi mô tả một mô hình tốt về cách thực hiện hành vi như vậy: Định nghĩa một lớp cơ sở TransactionalEntity. Lớp này chứa từ điển thuộc tính. Tất cả các lớp giao dịch của bạn được kế thừa từ TransactionalEntity và sẽ hoạt động trên một số loại Thuộc tính phụ thuộc/Trường, tức là thuộc tính (getters/setters) lưu trữ các giá trị của nó không phải trong các trường lớp địa phương, nhưng trong từ điển, được lưu trữ trong cơ sở lớp học. Sau đó, bạn xác định lớp học TransactionContext. TransactionContext lớp nội bộ chứa một bộ từ điển (một từ điển cho mỗi thực thể tham gia vào giao dịch) và khi một thực thể giao dịch tham gia vào giao dịch, nó ghi tất cả dữ liệu vào từ điển trong ngữ cảnh giao dịch. Sau đó, tất cả các bạn cần về cơ bản là bốn phương pháp:

TransactionContext.StartTransaction(); 
TransactionalEntity.JoinTransaction(TransactionContext context); //if your language/framework supports Thread Static fields, then you do not need this method 
TransactionContext.CommitTransaction(); 
TransactionContext.RollbackTransaction(); 

Tóm lại, bạn cần lưu trữ nhà nước trong lớp cơ sở TransactionalEntity và trong quá trình giao dịch TransactionalEntity sẽ hợp tác với TransactionContext.

Tôi hy vọng, tôi đã giải thích đủ rõ.

0

Khi sử dụng phương pháp sao chép đối tượng, bạn phải xem các câu lệnh được cuộn ngược chỉ ảnh hưởng đến chính đối tượng hoặc dữ liệu (và tổng hợp).

Nhưng mọi thứ đang trở nên thực sự khó khăn nếu các tác dụng phụ của các câu lệnh là "bên ngoài hơn". Ví dụ các hoạt động I/O, các cuộc gọi mạng. Bạn luôn phải phân tích toàn bộ các thay đổi trạng thái của các phát biểu của mình.

Nó cũng sẽ thực sự phức tạp nếu bạn chạm vào dữ liệu tĩnh (hoặc những người độc ác có thể thay đổi được). Việc hoàn nguyên dữ liệu này được phân lập rất khó, bởi vì các chủ đề khác có thể đã sửa đổi chúng ở giữa (bạn có thể gặp phải các cập nhật bị mất).

Lùi lại/rollback về quá khứ thường không phải là quá tầm thường;)

3

Cách đơn giản nhất và đáng tin cậy nhất "mẫu" để sử dụng ở đây là một cấu trúc dữ liệu không thay đổi.

Thay vì viết:

foo.MoveToState2(); 
foo.MoveToFinalState(); 

Bạn viết:

MyFoo foo2 = foo.MoveToState2(); 
MyFoo finalFoo = foo2.MoveToFinalState(); 

Và thực hiện các biện pháp phù hợp - đó là, MoveToState2 không thực sự thay đổi bất cứ điều gì về MyFoo, nó tạo ra một mới MyFoo đó là ở trạng thái 2. Tương tự với trạng thái cuối cùng.

Đây là cách các lớp chuỗi trong hầu hết các ngôn ngữ OO hoạt động. Nhiều ngôn ngữ OO cũng bắt đầu thực hiện (hoặc đã thực hiện) các bộ sưu tập bất biến. Một khi bạn có các khối xây dựng, nó khá đơn giản để tạo ra một "thực thể" toàn bộ bất biến.

0

tôi đã ngạc nhiên mà không ai gợi ý một cách rõ ràng mô hình đơn giản nhất để sử dụng .. các State Pattern

Bằng cách này bạn cũng có thể loại bỏ rằng phương pháp 'finalState' và chỉ sử dụng 'xử lý()'. Làm cách nào để bạn biết trạng thái cuối cùng là gì? Mẫu ký tự được sử dụng tốt nhất với mẫu Lệnh và thường áp dụng cho các hoạt động GUI để thực hiện tính năng hoàn tác/làm lại.

Fields đại diện cho một nhà nước của lớp

Fields thể hiện trạng thái của đối tượng instanced. Bạn sử dụng nhiều định nghĩa sai về các thuật ngữ OOP. Xem xét và sửa lại.

Các vấn đề liên quan