2009-03-18 22 views
17

Tôi có một mã phân tích một số tệp mẫu và khi tìm thấy một trình giữ chỗ, nó sẽ thay thế nó bằng một giá trị. Một cái gì đó như:Thay thế tuyên bố chuyển đổi khổng lồ bằng cái gì?

<html> 
<head> 
    <title>%title%</title> 
</head> 
<body bgcolor="%color%"> 
...etc. 

Trong mã, phân tích cú pháp tìm thấy những, gọi chức năng này:

string getContent(const string& name) 
{ 
    if (name == "title") 
     return page->getTitle(); 
    else if (name == "color") 
     return getBodyColor(); 
    ...etc. 
} 

và sau đó thay thế giữ chỗ ban đầu với giá trị trả về.

Trong trường hợp thực, đây không phải là trang web giả và có nhiều (50+) trình giữ chỗ khác nhau có thể xảy ra.

Mã của tôi là C++, nhưng tôi đoán vấn đề này tồn tại với bất kỳ ngôn ngữ nào. Đó là nhiều hơn về các thuật toán và thiết kế OO tôi đoán. Chỉ có điều quan trọng là điều này phải được biên dịch, ngay cả khi tôi muốn tôi không thể có bất kỳ mã động/eval'd.

Tôi mặc dù về việc triển khai mẫu Chuỗi trách nhiệm, nhưng dường như nó không cải thiện tình hình nhiều.

CẬP NHẬT: và tôi cũng lo ngại về this comment trong một chuỗi khác. Tôi có nên quan tâm đến nó?

Trả lời

25

Sử dụng từ điển bản đồ tên thẻ cho trình xử lý thẻ.

+0

+1 Để làm rõ, trong C++, chúng được gọi là std :: map. – Eclipse

+1

Đặc biệt tốt nếu từ điển của bạn có thể sử dụng tra cứu O (1) như băm. –

+0

Câu trả lời hay. Một chút về phía nạc, nhưng chắc chắn là một cách tốt để đi. :) –

4

Bạn muốn replace conditional with polymorphism. Roughly:

string getContent(const string& name) { 
    myType obj = factory.getObjForName(name); 
    obj.doStuff(); 
} 

nơi doStuff bị quá tải.

+2

Tất nhiên, việc chuyển đổi chỉ đang được di chuyển ở một nơi khác (nhà máy), đó là nơi mà nó nên được. –

+0

Bạn có thể muốn kết hợp nhà máy với bản đồ của Neil Butterworth và tải logic instantiation từ một số tệp cấu hình. Biên dịch * và * động - tuyệt vời. –

+0

Thực ra, mẫu đó là tệp cấu hình. Người dùng có thể tự thay đổi nó. –

3

Bạn đã xem XSLT chưa? Nó rất phù hợp với loại điều này. Tôi đã phát triển một hệ thống quản lý nội dung đã làm điều tương tự và thấy XSLT rất hiệu quả. Trình phân tích cú pháp thực hiện rất nhiều công việc cho bạn.

CẬP NHẬT: Nhận xét của Steven nêu lên một điểm quan trọng - bạn sẽ muốn mẫu của mình là XHTML hợp lệ nếu bạn quyết định đi tuyến XSLT. Ngoài ra, tôi sẽ sử dụng dấu tách khác nhau cho mã thông báo thay thế của bạn. Một cái gì đó ít có khả năng xảy ra tự nhiên. Tôi đã sử dụng #! PLACEHOLDER #! trong CMS của tôi.

+0

Tôi nghĩ rằng bạn khá lạc quan khi nghĩ rằng các mẫu HTML sẽ là XML hợp lệ. :) –

2

Thay vì phân tích cú pháp, hãy thử đọc mẫu thành chuỗi và sau đó chỉ thực hiện thay thế.

fileContents = fileContents.Replace("%title%", page->getTitle()); 
fileContents = fileContents.Replace("%color%", getBodyColor()); 
+0

hiệu suất đạt được, nhưng có lẽ đáng để đơn giản hóa mã nếu hiệu quả tuyệt đối không hoàn toàn cần thiết. +1 –

+1

Nếu biến "titleValue" chứa chuỗi "% color%", nó sẽ không hoạt động chính xác. –

+0

ya cũng kém an toàn hơn, nhưng vẫn đơn giản hơn :) –

3

tôi sẽ kết hợp 3 ý tưởng:

  1. (từ Steven Hugig): sử dụng một phương pháp nhà máy mà được bạn một lớp học khác nhau cho mỗi selector.
    • (từ Neil Butterworth): bên trong nhà máy, sử dụng từ điển để bạn loại bỏ số lớn switch(){}.
    • (của tôi): thêm phương thức setup() vào mỗi lớp trình xử lý, tự thêm (hoặc phiên bản lớp mới) vào từ điển.

giải thích một chút:

  • làm cho một lớp trừu tượng mà có một dict static, và phương pháp để đăng ký một thể hiện bằng một chuỗi selector.
  • trên mỗi phân lớp các phương pháp setup() tự đăng ký với dict của lớp cha
  • phương pháp nhà máy là hơn chút so với một cuốn từ điển đọc
+0

Nghiên cứu guy..không phải là bạn – Warrior

+0

+1. Tôi sẽ đề nghị loại bỏ hàm setup() riêng biệt và di chuyển hành vi của nó tới hàm khởi tạo - theo cách đó nó không thể bị lãng quên. –

2

Như "Uncle" Bob Martin mentioned in a previous podacast with Joel and Jeff, khá nhiều bất cứ điều gì bạn đưa ra sẽ chủ yếu được tái tạo câu lệnh chuyển đổi lớn.

Nếu bạn cảm thấy thực hiện tốt hơn một trong các giải pháp được chọn ở trên, điều đó là tốt. Nó có thể làm cho mã của bạn đẹp hơn, nhưng dưới bìa, nó cơ bản là tương đương.

Điều quan trọng là đảm bảo rằng chỉ có một trường hợp của câu lệnh chuyển đổi lớn của bạn. Câu lệnh chuyển đổi hoặc từ điển của bạn nên xác định lớp nào xử lý thẻ này, và sau đó các quyết định tiếp theo phải được xử lý bằng cách sử dụng đa hình.

+0

Điều này là không đúng (và là điển hình của crap mà Martin đi ra với). Để thêm vào một công tắc, tôi cần sửa đổi mã của công tắc - tôi có thể thêm vào từ điển mà không sửa đổi mã hiện tại. –

+0

Thêm vào từ điển vẫn là một thay đổi mã, và một trình biên dịch có ít cơ hội nhận các vấn đề với .. nó không giống như từ điển đang được phổ biến từ dữ liệu, nó sẽ được phổ biến thông qua mã. Thêm các trường hợp vào một câu lệnh chuyển đổi không cần ảnh hưởng đến bất kỳ trường hợp hiện có nào ...? – Bittercoder

+0

Về lý thuyết, có, độc tài có thể được điền từ một tệp cấu hình hoặc một bảng cơ sở dữ liệu, vì vậy nó có thể được sửa đổi mà không cần biên dịch lại. Trong thực tế, nếu bạn đang thay đổi ánh xạ, có thể vì bạn có một trình xử lý mới, do đó bạn đã thực hiện việc biên dịch lại. – JohnMcG

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