2012-10-29 21 views
5

Tôi có một lớp có thể giao tiếp với Oracle hoặc MySQL. Lớp được khởi tạo với một từ khóa là "Oracle" hoặc "MySQL" và một vài tham số khác là tiêu chuẩn cho cả hai loại cơ sở dữ liệu (những gì cần in, có hoặc không dừng lại trên một ngoại lệ, vv). Thật dễ dàng để thêm if Oracle do A, elif MySQL do B khi cần thiết khi tôi bắt đầu, nhưng khi tôi thêm mã chuyên biệt hơn chỉ áp dụng cho một loại cơ sở dữ liệu, điều này đang trở nên xấu xí. Tôi đã chia lớp thành hai, một cho Oracle và một cho MySQL, với một số chức năng được chia sẻ để tránh mã trùng lặp.Cách Pythonic nhất để xử lý chia lớp thành nhiều lớp

Cách Pythonic nhất để xử lý việc gọi các lớp mới này là gì? Tôi có tạo một hàm/lớp bao bọc sử dụng cùng từ khóa này và trả về đúng lớp không? Tôi có thay đổi tất cả mã của tôi gọi lớp chung cũ để gọi đúng lớp DB cụ thể không?

Tôi sẽ sẵn sàng thử một số mã mẫu nếu cần, nhưng tôi không nghĩ là cần thiết. Cảm ơn trước sự giúp đỡ nào!

Trả lời

4

Tôi có tạo một hàm/lớp bao bọc sử dụng cùng từ khóa này và trả về đúng lớp không?

Đó là ý tưởng. Hàm như vậy được gọi là chức năng của nhà máy:

def connect_to(db, *args): 
    if db == "MySQL": 
     return MySQL(*args) 
    elif db == "Oracle": 
     return Oracle(*args) 
    else: 
     raise ValueError("unknown database type: %r" % db) 

Đảm bảo rằng cả hai lớp cơ sở dữ liệu đều có cùng một API. Bạn có thể đạt được điều này bằng cách gõ vịt hoặc với các lớp cơ sở trừu tượng (ABC); thứ hai chủ yếu là hữu ích nếu chức năng được chia sẻ giữa các lớp, hoặc nếu bạn muốn thực hiện kiểm tra isinstance để tìm hiểu xem một đối tượng có biểu thị kết nối cơ sở dữ liệu hay không.

Trong trường hợp chức năng được chia sẻ, template method pattern thường có ích.

3

Tạo lớp nhà máy trả về triển khai dựa trên tham số. Sau đó, bạn có thể có một lớp cơ sở chung cho cả hai loại DB, một thực thi cho mỗi và cho phép nhà máy tạo, cấu hình và trả về việc triển khai chính xác cho người dùng dựa trên tham số.

Điều này hoạt động tốt khi hai lớp hoạt động rất giống nhau; nhưng ngay khi bạn muốn sử dụng các tính năng DB cụ thể, nó trở nên xấu xí vì bạn cần các phương thức như isFeatureXSupported() (cách tiếp cận tốt) hoặc isOracle() (đơn giản hơn nhưng xấu vì nó di chuyển kiến ​​thức về DB nào có tính năng từ lớp trợ giúp vào mã ứng dụng).

Hoặc, bạn có thể triển khai tất cả các tính năng cho cả hai và ném ngoại lệ khi không được hỗ trợ. Trong mã của bạn, bạn có thể tìm ngoại lệ để kiểm tra điều này. Điều này làm cho mã sạch hơn nhưng bây giờ, bạn thực sự có thể kiểm tra xem một tính năng có sẵn mà không thực sự sử dụng nó hay không. Điều đó có thể gây ra các sự cố trong mã ứng dụng (ví dụ: khi bạn muốn vô hiệu hóa menu, hoặc khi ứng dụng có thể thực hiện theo cách khác).

+2

Lời khuyên tốt, nhưng trừ khi lớp nhà máy của bạn cũng là lớp cơ sở, bạn cũng có thể sử dụng chức năng của nhà máy. – Marcin

+0

Sử dụng một lớp nhà máy rất hữu ích khi bạn cần cấu hình nó. Nếu không, bạn sẽ nhận được một hàm với quá nhiều tham số. –

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