Một cách đơn giản để giữ các cài đặt của ứng dụng Java được biểu thị bằng tệp văn bản có phần mở rộng ".properations" chứa định danh của từng cài đặt được liên kết với một giá trị cụ thể (giá trị này có thể là số, chuỗi, ngày, v.v.) . C # sử dụng một cách tiếp cận tương tự, nhưng tệp văn bản phải được đặt tên là "App.config". Trong cả hai trường hợp, trong mã nguồn, bạn phải khởi tạo một lớp cụ thể để đọc cài đặt: lớp này có một phương thức trả về giá trị (dưới dạng chuỗi) được liên kết với mã định danh cài đặt đã chỉ định.
// Java example
Properties config = new Properties();
config.load(...);
String valueStr = config.getProperty("listening-port");
// ...
// C# example
NameValueCollection setting = ConfigurationManager.AppSettings;
string valueStr = setting["listening-port"];
// ...
Trong cả hai trường hợp, chúng ta nên phân tích các chuỗi được tải từ tệp cấu hình và gán các giá trị được chuyển đổi cho các đối tượng được nhập có liên quan (lỗi phân tích cú pháp có thể xảy ra trong giai đoạn này). Sau bước phân tích cú pháp, chúng tôi phải kiểm tra xem các giá trị cài đặt có thuộc về một miền hợp lệ cụ thể không: ví dụ: kích thước tối đa của hàng đợi phải là giá trị dương, một số giá trị có thể liên quan (ví dụ: min <max ), v.v.
Giả sử rằng ứng dụng sẽ tải các cài đặt ngay khi khởi động: nói cách khác, thao tác đầu tiên được thực hiện bởi ứng dụng là tải các cài đặt. Mọi giá trị không hợp lệ cho các cài đặt phải được thay thế tự động bằng các giá trị mặc định: nếu điều này xảy ra với một nhóm các cài đặt liên quan, các cài đặt đó đều được đặt với các giá trị mặc định.
Cách dễ nhất để thực hiện các thao tác này là tạo một phương thức trước tiên phân tích tất cả các cài đặt, sau đó kiểm tra các giá trị được tải và cuối cùng đặt bất kỳ giá trị mặc định nào. Tuy nhiên, việc bảo trì rất khó khăn nếu bạn sử dụng phương pháp này: khi số lượng cài đặt tăng lên trong khi phát triển ứng dụng, việc cập nhật mã ngày càng khó khăn hơn.
Để giải quyết vấn đề này, tôi đã nghĩ đến việc sử dụng mẫu Phương thức mẫu, như sau.
public abstract class Setting
{
protected abstract bool TryParseValues();
protected abstract bool CheckValues();
public abstract void SetDefaultValues();
/// <summary>
/// Template Method
/// </summary>
public bool TrySetValuesOrDefault()
{
if (!TryParseValues() || !CheckValues())
{
// parsing error or domain error
SetDefaultValues();
return false;
}
return true;
}
}
public class RangeSetting : Setting
{
private string minStr, maxStr;
private byte min, max;
public RangeSetting(string minStr, maxStr)
{
this.minStr = minStr;
this.maxStr = maxStr;
}
protected override bool TryParseValues()
{
return (byte.TryParse(minStr, out min)
&& byte.TryParse(maxStr, out max));
}
protected override bool CheckValues()
{
return (0 < min && min < max);
}
public override void SetDefaultValues()
{
min = 5;
max = 10;
}
}
Vấn đề là theo cách này, chúng ta cần tạo một lớp mới cho mỗi cài đặt, thậm chí cho một giá trị duy nhất. Có giải pháp nào khác cho loại vấn đề này không?
Tóm tắt:
- Bảo trì dễ dàng: ví dụ: việc thêm một hoặc nhiều tham số.
- Khả năng mở rộng: phiên bản đầu tiên của ứng dụng có thể đọc một tệp cấu hình duy nhất, nhưng các phiên bản sau có thể cung cấp khả năng thiết lập nhiều người dùng (quản trị viên thiết lập cấu hình cơ bản, người dùng chỉ có thể đặt một số cài đặt nhất định, v.v.).
- Thiết kế hướng đối tượng.