Nếu nguyên lý đóng mở đƣợc xem là nguyên lý quan trọng nhất của thiết kế hƣớng đối tƣợng, thì nguyên lý thay thế Liskov đƣợc xem nhƣ một phƣơng tiện để chúng ta có thể kiểm tra xem thiết kế hoặc chƣơng trình có thỏa mãn nguyên lý đóng mở hay không.
Các thành phần phần mềm không nên phụ thuộc vào những cái riêng, cụ thể, mà ngƣợc lại nên phụ thuộc vào những cái chung, tổng quát của những cái riêng cụ thể đó. Ngƣợc lại, những cái chung, tổng quát không nên phụ thuộc vào những cái riêng, cụ thể. Sự phụ thuộc này nên đảo ngƣợc lại.
Cái chung, tổng quát bao gồm những đặc tính chung nhất của những cái riêng, cụ thể. Còn những cái riêng, cụ thể thì tuân theo những quy tắc mà cái chung, tổng quát của nó định nghĩa. Những cái chung, tổng quát thƣờng ít biến đổi. Sự thay đổi thƣờng diễn ra ở những cái riêng, cụ thể. Do đó sự phụ thuộc vào những cái chung, tổng quát sẽ giúp các thành phần phần mềm linh động và thích ứng tốt hơn với các thay đổi. Khi phụ thuộc vào những cái chung, tổng quát, các thành phần phần mềm sẽ không bị ảnh hƣởng và không cần sửa đổi để thích nghi bởi việc thay thế cái riêng, cụ thể bằng một cái riêng, cụ thể khác.
Xét đoạn chƣơng trình đọc dữ liệu từ bàn phím và xuất ra máy in: public void copy(){
Keyboard keyboard = new Keyboard(); Printer printer = new Printer(); char c;
while ((c = keyboard.read()) != „q‟) printer.write(c);
53
Khi nâng cấp, mở rộng đoạn chƣơng trình trên để nó có thể xuất dữ liệu ra máy in hoặc tập tin, ta phải điều chỉnh lại nhƣ sau:
public void copy(OutputType type){
Keyboard objKeyboard = new Keyboard(); Printer objPrinter = new Printer(); File objFile = new File();
char c;
while ((c = objKeyboard.read()) != „q‟) if (type == OutputType.PRINTER)
objPrinter.write(c);
else if (type == OutputType.FILE) objFile.write(c);
}
Hàm copy trên đã vi phạm nguyên lý đóng mở. Vì khi thêm một thiết bị mới, ta phải chỉnh lại nó. Nguyên nhân của việc này là vì đã làm việc với các thiết bị đọc ghi cụ thể. Khi thêm một thiết bị mới, ta phải thêm vào đoạn mã nội dung làm việc với thiết bị mới đó. Khi đó ngƣời ta nói rằng, hàm copy đã vi phạm nguyên lý nghịch đảo phụ thuộc.
Để đoạn chƣơng trình trên có thể tuân theo nguyen lý nghịch đảo phụ thuộc, ta phải chỉnh sửa cho nó làm việc với thiết bị tổng quát. Với đoạn mã chƣơng trình trên, ta có thể chỉnh sửa lại nhƣ sau:
public void copy(Reader objReader, Writer objWriter){ char c;
while ((c = objReader.read()) != „q‟) objWriter.write(c);
}
Một số chú ý khi tuân theo nguyên lý nghịch đảo phụ thuộc:
Nguyên lý nghịch đảo phụ thuộc có mối liên hệ chặt chẽ với nguyên lý đóng mở. Việc vi phạm nguyên lý nghịch đảo phụ thuộc sẽ dẫn đến vi phạm nguyên lý đóng mở. Khi nguyên lý nghịch đảo phụ thuộc bị vi phạm, tức các thành phần phần mềm đã phụ thuộc vào những cái riêng, cụ thể. Do đó, việc nâng cấp, mở rộng sẽ dẫn đến các thành phần phần mềm mà phụ thuộc vào nó sẽ yêu cầu đƣợc sửa đổi, thay đổi. Điều này là đã vi phạm nguyên lý đóng mở.
Một đặc trƣng của thiết kế hƣớng đối tƣợng mà giúp cho các thành phần phần mềm tăng khả năng tuân thủ nguyên lý nghịch đảo phụ thuộc, đó là việc truy xuất đối tƣợng thông qua giao diện của nó. Việc truy xuất qua giao diện sẽ làm cho các thành phần có tính linh động cao hơn, không phải sửa đổi khi ta thay thế các đối tƣợng đó bằng các đối tƣợng cùng loại khác.
54