Tất cả những gì bạn cần biết về Nguyên tắc vững chắc trong Java



Trong bài viết này, bạn sẽ tìm hiểu chi tiết về các nguyên tắc Solid trong java là gì với các ví dụ và tầm quan trọng của chúng với ví dụ trong cuộc sống thực.

Trong thế giới của (OOP), có rất nhiều hướng dẫn, mẫu hoặc nguyên tắc thiết kế. Năm trong số các nguyên tắc này thường được nhóm lại với nhau và được biết đến với tên viết tắt là SOLID. Mặc dù mỗi nguyên tắc trong số năm nguyên tắc này đều mô tả một cái gì đó cụ thể, nhưng chúng trùng lặp với nhau khiến việc áp dụng một trong số chúng bao hàm hoặc dẫn đến áp dụng một nguyên tắc khác. Trong bài viết này, chúng ta sẽ hiểu các nguyên tắc SOLID trong Java.

Lịch sử của các nguyên tắc SOLID trong Java

Robert C. Martin đã đưa ra năm nguyên tắc thiết kế hướng đối tượng và từ viết tắt “S.O.L.I.D” được sử dụng cho nó. Khi bạn sử dụng tất cả các nguyên tắc của S.O.L.I.D một cách kết hợp, bạn sẽ dễ dàng phát triển phần mềm có thể được quản lý một cách dễ dàng. Các tính năng khác của việc sử dụng S.O.L.I.D là:





  • Nó tránh được mùi mã.
  • Mã khúc xạ nhanh chóng.
  • Có thể phát triển phần mềm thích ứng hoặc nhanh nhẹn.

Khi bạn sử dụng nguyên tắc S.O.L.I.D trong quá trình viết mã của mình, bạn sẽ bắt đầu viết mã hiệu quả và hiệu quả.



Ý nghĩa của S.O.L.I.D là gì?

Solid đại diện cho năm nguyên tắc của java đó là:

  • S : Nguyên tắc trách nhiệm duy nhất
  • HOẶC LÀ : Nguyên tắc đóng mở
  • L : Nguyên tắc thay thế Liskov
  • Tôi : Nguyên tắc phân tách giao diện
  • D : Nguyên tắc nghịch đảo phụ thuộc

Trong blog này, chúng ta sẽ thảo luận chi tiết về tất cả năm nguyên tắc SOLID của Java.



Nguyên tắc trách nhiệm đơn trong Java

Nó nói gì?

Robert C. Martin mô tả nó là một lớp chỉ nên có một và trách nhiệm duy nhất.

Theo nguyên tắc trách nhiệm duy nhất, chỉ nên có một lý do duy nhất mà một lớp phải được thay đổi. Nó có nghĩa là một lớp nên có một nhiệm vụ để làm. Nguyên tắc này thường được gọi là chủ quan.

Nguyên tắc này có thể được hiểu rõ với một ví dụ. Hãy tưởng tượng có một lớp thực hiện các hoạt động sau.

  • Đã kết nối với cơ sở dữ liệu

  • Đọc một số dữ liệu từ các bảng cơ sở dữ liệu

  • Cuối cùng, ghi nó vào một tệp.

Bạn đã tưởng tượng ra viễn cảnh chưa? Ở đây, lớp có nhiều lý do để thay đổi, và một số lý do trong số đó là sửa đổi đầu ra tệp, áp dụng cơ sở dữ liệu mới. Khi chúng ta nói về trách nhiệm nguyên tắc duy nhất, chúng ta sẽ nói rằng, có quá nhiều lý do để lớp học thay đổi, do đó, nó không phù hợp với nguyên tắc trách nhiệm duy nhất.

Ví dụ, một lớp Ô tô có thể tự khởi động hoặc tự dừng nhưng nhiệm vụ rửa nó thuộc về lớp CarWash. Trong một ví dụ khác, một lớp Sách có các thuộc tính để lưu trữ tên và văn bản của chính nó. Nhưng nhiệm vụ in sách phải thuộc về lớp Máy in sách. Lớp Máy in Sách có thể in ra bảng điều khiển hoặc phương tiện khác nhưng các phần phụ thuộc như vậy sẽ bị xóa khỏi lớp Sách

Tại sao Nguyên tắc này là Bắt buộc?

Khi Nguyên tắc Trách nhiệm Đơn lẻ được tuân thủ, việc kiểm tra sẽ dễ dàng hơn. Với một trách nhiệm duy nhất, lớp học sẽ có ít trường hợp thử nghiệm hơn. Ít chức năng hơn cũng có nghĩa là ít phụ thuộc hơn vào các lớp khác. Nó dẫn đến tổ chức mã tốt hơn vì các lớp nhỏ hơn và có mục đích tốt dễ tìm kiếm hơn.

Một ví dụ để làm rõ nguyên tắc này:

Giả sử bạn được yêu cầu triển khai dịch vụ UserSetting trong đó người dùng có thể thay đổi cài đặt nhưng trước đó người dùng phải được xác thực. Một cách để thực hiện điều này sẽ là:

public class UserSettingService {public void changeEmail (User user) {if (checkAccess (user)) {// Cấp tùy chọn để thay đổi}} public boolean checkAccess (User user) {// Xác minh xem người dùng có hợp lệ hay không. }}

Tất cả có vẻ ổn cho đến khi bạn muốn sử dụng lại mã checkAccess ở một số nơi khác HOẶC bạn muốn thay đổi cách checkAccess đang được thực hiện. Trong cả hai trường hợp, bạn sẽ phải thay đổi cùng một lớp và trong trường hợp đầu tiên, bạn sẽ phải sử dụng UserSettingService để kiểm tra quyền truy cập.
Một cách để sửa lỗi này là phân tách UserSettingService thành UserSettingService và SecurityService. Và di chuyển mã checkAccess vào SecurityService.

public class UserSettingService {public void changeEmail (User user) {if (SecurityService.checkAccess (user)) {// Cấp tùy chọn để thay đổi}}} public class SecurityService {public static boolean checkAccess (User user) {// kiểm tra quyền truy cập. }}

Nguyên tắc đóng mở trong Java

Robert C. Martin mô tả nó là Các thành phần phần mềm nên mở để mở rộng, nhưng đóng để sửa đổi.

Nói một cách chính xác, theo nguyên tắc này, một lớp nên được viết theo cách mà nó thực hiện công việc của mình một cách hoàn hảo mà không có giả định rằng mọi người trong tương lai sẽ đơn giản đến và thay đổi nó. Do đó, lớp học vẫn nên đóng cửa để sửa đổi, nhưng nó phải có tùy chọn để được gia hạn. Các cách mở rộng lớp học bao gồm:

  • Kế thừa từ lớp

  • Ghi đè các hành vi được yêu cầu từ lớp

  • Mở rộng các hành vi nhất định của lớp

Một ví dụ tuyệt vời về nguyên tắc đóng mở có thể được hiểu với sự trợ giúp của trình duyệt. Bạn có nhớ cài đặt tiện ích mở rộng trong trình duyệt chrome của mình không?

Chức năng cơ bản của trình duyệt chrome là lướt các trang web khác nhau. Bạn có muốn kiểm tra ngữ pháp khi viết email bằng trình duyệt chrome không? Nếu có, bạn chỉ cần sử dụng tiện ích mở rộng Grammarly, nó cung cấp cho bạn khả năng kiểm tra ngữ pháp về nội dung.

Cơ chế này mà bạn đang thêm những thứ để tăng chức năng của trình duyệt là một tiện ích mở rộng. Do đó, trình duyệt là một ví dụ hoàn hảo về chức năng mở để mở rộng nhưng bị đóng để sửa đổi. Nói một cách dễ hiểu, bạn có thể nâng cao chức năng bằng cách thêm / cài đặt các plugin trên trình duyệt của mình, nhưng không thể xây dựng bất kỳ thứ gì mới.

Tại sao cần phải có nguyên tắc này?

OCP rất quan trọng vì các lớp học có thể đến với chúng tôi thông qua các thư viện của bên thứ ba. Chúng ta có thể mở rộng các lớp đó mà không cần lo lắng liệu các lớp cơ sở đó có thể hỗ trợ các phần mở rộng của chúng ta hay không. Nhưng kế thừa có thể dẫn đến các lớp con phụ thuộc vào việc triển khai lớp cơ sở. Để tránh điều này, nên sử dụng các giao diện. Sự trừu tượng bổ sung này dẫn đến khớp nối lỏng lẻo.

Giả sử chúng ta cần tính toán diện tích của các hình dạng khác nhau. Chúng tôi bắt đầu với việc tạo một lớp cho hình dạng đầu tiên Hình chữ nhật của chúng tôicó độ dài 2 thuộc tính& chiều rộng.

public class Rectangle {public double length public double width}

Tiếp theo, chúng ta tạo một lớp để tính diện tích của Hình chữ nhật nàytrong đó có một phương thức tính toánRectangleArealấy Hình chữ nhậtnhư một tham số đầu vào và tính diện tích của nó.

public class AreaCalculator {public đúp tính toánRectangleArea (Hình chữ nhật hình chữ nhật) {return Hình chữ nhật.length * Hình chữ nhật. width}}

Càng xa càng tốt. Bây giờ, giả sử chúng ta có được hình tròn hình dạng thứ hai. Vì vậy, chúng tôi nhanh chóng tạo một Vòng kết nối lớp mớivới một bán kính thuộc tính duy nhất.

public class Circle {public double radius}

Sau đó, chúng tôi sửa đổi Areacalculatorlớp để thêm các phép tính vòng tròn thông qua một phương thức mới allowCircleaArea ()

public class AreaCalculator {public đúp tính toánRectangleArea (Hình chữ nhật hình chữ nhật) {return Hình chữ nhật.length * Hình chữ nhật.width} public double featuresCircleArea (Hình tròn tròn) {return (22/7) * circle.radius * circle.radius}}

Tuy nhiên, lưu ý rằng có những sai sót trong cách chúng tôi thiết kế giải pháp của mình ở trên.

Giả sử chúng ta có một hình ngũ giác mới. Trong trường hợp đó, chúng tôi sẽ kết thúc việc sửa đổi lớp AreaCalculator một lần nữa. Khi các loại hình dạng phát triển, điều này trở nên lộn xộn hơn vì AreaCalculator liên tục thay đổi và bất kỳ người tiêu dùng nào thuộc loại này sẽ phải tiếp tục cập nhật thư viện của họ có chứa AreaCalculator. Do đó, lớp AreaCalculator sẽ không được tạo cơ sở (hoàn thiện) với sự chắc chắn vì mỗi khi một hình dạng mới xuất hiện, nó sẽ được sửa đổi. Vì vậy, thiết kế này không được đóng lại để sửa đổi.

AreaCalculator sẽ cần phải tiếp tục thêm logic tính toán của chúng trong các phương pháp mới hơn. Chúng tôi không thực sự mở rộng phạm vi của các hình dạng mà chúng tôi chỉ đơn giản thực hiện giải pháp từng phần (từng chút một) cho mọi hình dạng được thêm vào.

Việc sửa đổi thiết kế trên theo nguyên tắc đóng / mở:

Bây giờ chúng ta hãy xem một thiết kế thanh lịch hơn, giải quyết những sai sót trong thiết kế trên bằng cách tuân thủ Nguyên tắc Mở / Đóng. Trước hết, chúng tôi sẽ làm cho thiết kế có thể mở rộng. Đối với điều này, trước tiên chúng ta cần xác định một loại cơ sở là Shape và có giao diện Circle & Rectangle triển khai Shape.

giao diện công cộng Shape {public double featuresArea ()} public class Rectangle thực hiện Shape {double length double width public double allowArea () {return length * width}} public class Circle thực hiện Shape {public double radius public double allowArea () {return (22 / 7) * bán kính * bán kính}}

Có một giao diện cơ sở Hình dạng. Tất cả các hình dạng hiện thực hiện giao diện cơ sở Hình dạng. Giao diện hình dạng có một phương thức trừu tượng CalculArea (). Cả hình tròn & hình chữ nhật đều cung cấp cách triển khai ghi đè riêng của phương thức mathArea () bằng cách sử dụng các thuộc tính của riêng chúng.
Chúng tôi đã mang lại một mức độ mở rộng vì các hình dạng bây giờ là một thể hiện của giao diện Hình dạng. Điều này cho phép chúng tôi sử dụng Hình dạng thay vì các lớp riêng lẻ
Điểm cuối cùng ở trên đề cập đến người tiêu dùng của những hình dạng này. Trong trường hợp của chúng tôi, người tiêu dùng sẽ là lớp AreaCalculator mà bây giờ sẽ trông như thế này.

public class AreaCalculator {public double featuresShapeArea (Shape shape) {return shape.calculateArea ()}}

Khu vực nàybây giờ lớp hoàn toàn loại bỏ các lỗi thiết kế của chúng tôi đã nêu ở trên và đưa ra một giải pháp sạch sẽ tuân thủ Nguyên tắc Đóng mở. Hãy tiếp tục với các Nguyên tắc SOLID khác trong Java

Nguyên tắc thay thế Liskov trong Java

Robert C. Martin mô tả nó là Các kiểu có nguồn gốc phải hoàn toàn có thể thay thế cho các kiểu cơ sở của chúng.

Nguyên tắc thay thế Liskov giả định q (x) là một thuộc tính, có thể chứng minh được về các thực thể của x thuộc loại T. Bây giờ, theo nguyên tắc này, q (y) bây giờ có thể cho phép đối với các đối tượng y thuộc loại S, và Chữ S thực sự là một loại con của T. Bạn có đang bối rối và không biết nguyên tắc thay thế Liskov thực sự có nghĩa là gì? Định nghĩa về nó có thể hơi phức tạp, nhưng trên thực tế, nó khá dễ dàng. Điều duy nhất là mọi lớp con hoặc lớp dẫn xuất phải có thể thay thế cho lớp cha hoặc lớp cơ sở của chúng.

Bạn có thể nói rằng nó là một nguyên tắc hướng đối tượng duy nhất. Nguyên tắc có thể được đơn giản hóa hơn nữa bởi một loại con của một loại cha mẹ cụ thể mà không làm phức tạp hoặc thổi phồng mọi thứ nên có khả năng thay thế cha mẹ đó. Nguyên tắc này liên quan chặt chẽ với nguyên tắc Thay thế Liskov.

Tại sao cần phải có nguyên tắc này?

Điều này tránh lạm dụng kế thừa. Nó giúp chúng ta tuân theo mối quan hệ 'là một'. Chúng ta cũng có thể nói rằng các lớp con phải thực hiện một hợp đồng được xác định bởi lớp cơ sở. Theo nghĩa này, nó liên quan đếnThiết kế theo hợp đồngđược mô tả lần đầu tiên bởi Bertrand Meyer. Ví dụ: thật hấp dẫn khi nói rằng hình tròn là một loại hình elip nhưng hình tròn không có hai tiêu điểm hoặc trục chính / phụ.

LSP được giải thích phổ biến bằng cách sử dụng ví dụ hình vuông và hình chữ nhật. nếu chúng ta giả sử mối quan hệ ISA giữa Hình vuông và Hình chữ nhật. Do đó, chúng tôi gọi “Hình vuông là Hình chữ nhật”. Đoạn mã dưới đây đại diện cho mối quan hệ.

public class Rectangle {private int length private int breadth public int getLength () {return length} public void setLength (int length) {this.length = length} public int getBreadth () {return breadth} public void setBreadth (int breadth) { this.breadth = breadth} public int getArea () {return this.length * this.breadth}}

Dưới đây là mã cho Square. Lưu ý rằng Hình vuông mở rộng Hình chữ nhật.

public class Hình vuông mở rộng Hình chữ nhật {public void setBreadth (int breadth) {super.setBreadth (breadth) super.setLength (breadth)} public void setLength (int length) {super.setLength (length) super.setBreadth (length)}}

Trong trường hợp này, chúng tôi cố gắng thiết lập mối quan hệ ISA giữa Hình vuông và Hình chữ nhật sao cho việc gọi 'Hình vuông là Hình chữ nhật' trong đoạn mã dưới đây sẽ bắt đầu hoạt động không mong muốn nếu một phiên bản Hình vuông được chuyển qua. Một lỗi xác nhận sẽ được đưa ra trong trường hợp kiểm tra “Khu vực” và kiểm tra “Độ rộng”, mặc dù chương trình sẽ kết thúc khi lỗi xác nhận được ném ra do không kiểm tra được Khu vực.

public class LSPDemo {public void CalculArea (Rectangle r) {r.setBreadth (2) r.setLength (3) khẳng định r.getArea () == 6: printError ('area', r) khẳng định r.getLength () == 3: printError ('length', r) khẳng định r.getBreadth () == 2: printError ('breadth', r)} private String printError (String errorIdentifer, Rectangle r) {return 'Giá trị không mong muốn của' + errorIdentifer + ' ví dụ về '+ r.getClass (). getName ()} public static void main (String [] args) {LSPDemo lsp = new LSPDemo () // Một phiên bản của Rectangle được truyền lsp.calculateArea (new Rectangle ()) // Một thể hiện của Square được truyền lsp.calculateArea (new Square ())}}

Lớp thể hiện Nguyên tắc thay thế Liskov (LSP) Theo nguyên tắc, các hàm sử dụng tham chiếu đến các lớp cơ sở phải có thể sử dụng các đối tượng của lớp dẫn xuất mà không cần biết.

Do đó, trong ví dụ được hiển thị bên dưới, hàm tính toán sử dụng tham chiếu “Hình chữ nhật” sẽ có thể sử dụng các đối tượng của lớp dẫn xuất như Hình vuông và đáp ứng yêu cầu đặt ra bởi định nghĩa Hình chữ nhật. Cần lưu ý rằng theo định nghĩa của Rectangle, điều sau phải luôn đúng với dữ liệu bên dưới:

  1. Độ dài phải luôn bằng độ dài được truyền làm đầu vào cho phương thức, setLength
  2. Độ rộng phải luôn bằng độ rộng được truyền làm đầu vào cho phương thức, setBreadth
  3. Diện tích phải luôn bằng tích của chiều dài và chiều rộng

Trong trường hợp, chúng tôi cố gắng thiết lập mối quan hệ ISA giữa Hình vuông và Hình chữ nhật để chúng tôi gọi là “Hình vuông là Hình chữ nhật”, đoạn mã trên sẽ bắt đầu hoạt động không mong muốn nếu một trường hợp Hình vuông được thông qua Lỗi xác nhận sẽ được đưa ra trong trường hợp kiểm tra diện tích và kiểm tra đối với bề rộng, mặc dù chương trình sẽ kết thúc khi lỗi xác nhận được ném ra do không kiểm tra được Khu vực.

Lớp Square không cần các phương thức như setBreadth hoặc setLength. Lớp LSPDemo sẽ cần biết chi tiết về các lớp dẫn xuất của Hình chữ nhật (chẳng hạn như Hình vuông) để viết mã một cách thích hợp nhằm tránh gây ra lỗi. Sự thay đổi trong mã hiện tại đã phá vỡ nguyên tắc đóng mở ngay từ đầu.

Nguyên tắc phân tách giao diện

Robert C. Martin mô tả nó là khách hàng không nên bị buộc phải thực hiện các phương pháp không cần thiết mà họ sẽ không sử dụng.

Dựa theoNguyên tắc phân tách giao diệnmột ứng dụng khách, bất kể điều gì không bao giờ được buộc phải triển khai một giao diện mà nó không sử dụng hoặc khách hàng không bao giờ bị bắt buộc phải phụ thuộc vào bất kỳ phương pháp nào không được họ sử dụng. Các giao diện nhỏ nhưng dành riêng cho khách hàng thay vì giao diện nguyên khối và lớn hơn. Tóm lại, sẽ không tốt cho bạn nếu buộc khách hàng phụ thuộc vào một thứ nhất định mà họ không cần.

Ví dụ, một giao diện ghi nhật ký duy nhất để ghi và đọc nhật ký hữu ích cho cơ sở dữ liệu nhưng không hữu ích cho bảng điều khiển. Việc đọc nhật ký không có ý nghĩa gì đối với trình ghi bảng điều khiển. Tiếp tục với bài viết Nguyên tắc SOLID trong Java này.

Tại sao cần phải có nguyên tắc này?

Giả sử rằng có một giao diện Nhà hàng chứa các phương thức chấp nhận đơn đặt hàng từ khách hàng trực tuyến, khách hàng gọi điện hoặc gọi điện và khách hàng đến. Nó cũng chứa các phương thức xử lý thanh toán trực tuyến (cho khách hàng trực tuyến) và thanh toán trực tiếp (cho khách hàng đi bộ cũng như khách hàng qua điện thoại khi đơn hàng của họ được giao tại nhà).

hàm sắp xếp c ++

Bây giờ chúng ta hãy tạo một Giao diện Java cho Nhà hàng và đặt tên nó là RestaurantInterface.java.

public interface RestaurantInterface {public void acceptOnlineOrder () public void takeTelephoneOrder () public void payOnline () public void walkInCustomerOrder () public void payInPerson ()}

Có 5 phương thức được định nghĩa trong RestaurantInterface là chấp nhận đặt hàng trực tuyến, đặt hàng qua điện thoại, chấp nhận đơn đặt hàng từ khách hàng đến, chấp nhận thanh toán trực tuyến và chấp nhận thanh toán trực tiếp.

Hãy để chúng tôi bắt đầu bằng cách triển khai RestaurantInterface cho khách hàng trực tuyến dưới dạng OnlineClientImpl.java

public class OnlineClientImpl triển khai RestaurantInterface {public void acceptOnlineOrder () {// logic để đặt hàng trực tuyến} public void takeTelephoneOrder () {// Không áp dụng cho Đặt hàng trực tuyến ném mới UnsupportedOperationException ()} public void payOnline () {// logic thanh toán online} public void walkInCustomerOrder () {// Không áp dụng cho Đơn hàng trực tuyến ném mới UnsupportedOperationException ()} public void payInPerson () {// Không áp dụng cho Đơn hàng trực tuyến ném mới UnsupportedOperationException ()}}
  • Vì mã trên (OnlineClientImpl.java) dành cho các đơn đặt hàng trực tuyến, hãy ném UnsupportedOperationException.

  • Khách hàng trực tuyến, điện thoại và khách hàng đi bộ sử dụng triển khai RestaurantInterface dành riêng cho từng khách hàng trong số họ.

  • Các lớp triển khai cho máy khách Telephonic và máy khách Walk-in sẽ có các phương thức không được hỗ trợ.

  • Vì 5 phương thức là một phần của RestaurantInterface, các lớp triển khai phải triển khai cả 5 phương thức đó.

  • Các phương thức mà mỗi lớp thực thi ném ra UnsupportedOperationException. Như bạn có thể thấy rõ - thực hiện tất cả các phương pháp đều không hiệu quả.

  • Bất kỳ thay đổi nào trong bất kỳ phương thức nào của RestaurantInterface sẽ được phổ biến cho tất cả các lớp triển khai. Việc bảo trì mã sau đó bắt đầu trở nên thực sự cồng kềnh và tác động hồi quy của các thay đổi sẽ tiếp tục tăng lên.

  • RestaurantInterface.java phá vỡ Nguyên tắc trách nhiệm duy nhất vì logic cho các khoản thanh toán cũng như logic để đặt hàng được nhóm lại với nhau trong một giao diện duy nhất.

Để khắc phục các vấn đề nêu trên, chúng tôi áp dụng Nguyên tắc phân tách giao diện để cấu trúc lại thiết kế trên.

  1. Tách các chức năng thanh toán và đặt hàng thành hai giao diện gọn nhẹ riêng biệt, PaymentInterface.java và OrderInterface.java.

  2. Mỗi khách hàng sử dụng một triển khai mỗi PaymentInterface và OrderInterface. Ví dụ - OnlineClient.java sử dụng OnlinePaymentImpl và OnlineOrderImpl, v.v.

  3. Nguyên tắc trách nhiệm duy nhất hiện được đính kèm dưới dạng giao diện Thanh toán (PaymentInterface.java) và giao diện Đặt hàng (OrderInterface).

  4. Thay đổi bất kỳ một trong các đơn đặt hàng hoặc giao diện thanh toán không ảnh hưởng đến các giao diện khác. Bây giờ chúng độc lập, sẽ không cần thực hiện bất kỳ triển khai giả nào hoặc ném một ngoại lệ UnsupportedOperationException vì mỗi giao diện chỉ có các phương thức mà nó sẽ luôn sử dụng.

Sau khi áp dụng ISP

Nguyên tắc đảo ngược phụ thuộc

Robert C. Martin mô tả nó phụ thuộc vào sự trừu tượng hóa chứ không phụ thuộc vào sự cụ thể hóa, theo đó, mô-đun cấp cao không bao giờ được dựa vào bất kỳ mô-đun cấp thấp nào. ví dụ

Bạn đến một cửa hàng địa phương để mua một thứ gì đó và bạn quyết định thanh toán bằng thẻ ghi nợ của mình. Vì vậy, khi bạn đưa thẻ của mình cho nhân viên thanh toán, nhân viên bán hàng sẽ không bận tâm đến việc kiểm tra loại thẻ bạn đã đưa.

Ngay cả khi bạn đã đưa thẻ Visa, anh ta sẽ không đưa ra máy làm thẻ Visa để quẹt thẻ của bạn. Loại thẻ tín dụng hoặc thẻ ghi nợ mà bạn có để thanh toán thậm chí không quan trọng họ sẽ chỉ cần quẹt thẻ. Vì vậy, trong ví dụ này, bạn có thể thấy rằng cả bạn và nhân viên bán hàng đều phụ thuộc vào tính trừu tượng của thẻ tín dụng và bạn không lo lắng về các chi tiết cụ thể của thẻ. Đây là nguyên tắc nghịch đảo phụ thuộc.

Tại sao cần phải có nguyên tắc này?

Nó cho phép lập trình viên loại bỏ các phần phụ thuộc được mã hóa cứng để ứng dụng trở nên liên kết lỏng lẻo và có thể mở rộng.

public class Student {private Address address public Student () {address = new Address ()}}

Trong ví dụ trên, lớp Sinh viên yêu cầu một đối tượng Địa chỉ và nó chịu trách nhiệm khởi tạo và sử dụng đối tượng Địa chỉ. Nếu lớp Địa chỉ được thay đổi trong tương lai thì chúng tôi cũng phải thực hiện các thay đổi trong lớp Sinh viên. Điều này làm cho sự kết hợp chặt chẽ giữa các đối tượng Sinh viên và Địa chỉ. Chúng tôi có thể giải quyết vấn đề này bằng cách sử dụng mẫu thiết kế đảo ngược phụ thuộc. tức là đối tượng Address sẽ được triển khai độc lập và sẽ được cung cấp cho Sinh viên khi Sinh viên được khởi tạo bằng cách sử dụng đảo ngược phụ thuộc dựa trên phương thức khởi tạo hoặc dựa trên setter.

Với điều này, chúng ta đến phần cuối của Nguyên tắc RẮN trong Java.

Kiểm tra của Edureka, một công ty học trực tuyến đáng tin cậy với mạng lưới hơn 250.000 người học hài lòng trải dài trên toàn cầu. Khóa đào tạo và cấp chứng chỉ về Java J2EE và SOA của Edureka được thiết kế cho sinh viên và các chuyên gia muốn trở thành Nhà phát triển Java. Khóa học được thiết kế để cung cấp cho bạn khởi đầu về lập trình Java và đào tạo bạn về cả khái niệm Java cốt lõi và nâng cao cùng với các khung Java khác nhau như Hibernate & Spring.

Có một câu hỏi cho chúng tôi? Vui lòng đề cập đến nó trong phần nhận xét của blog “Nguyên tắc RẮN trong Java” này và chúng tôi sẽ liên hệ lại với bạn sớm nhất có thể.