OOP Principle

本文探讨了面向对象设计的五大原则,包括单一职责原则、开放封闭原则、Liskov替换原则、依赖倒置原则和接口隔离原则,以及如何利用这些原则处理软件设计中的依赖关系。
依赖是和变化紧密联系在一起的概念。由于依赖关系的存在,变化在某处发生时,影响会波及开来,造成很多修改工作,这就是依赖的危害。可以说变化是始作俑者,依赖是助纣为虐。
我们可以不去拥抱变化吗?不可以。未来将是越来越不可预测,这是新经济最具挑战性的方面之一。商务和技术上的瞬息万变会产生变化,这既可以看作要防范的威胁,也可以看作应该欢迎的机遇。
既然变化不可避免,我们所能做的就是处理好依赖关系,将变化造成的影响波及范围尽量减小。

下面总结一下"面向对象设计五大原则"和良性依赖原则在应付变化方面的作用。

单 一职责原则(Single-Resposibility Principle)。"对一个类而言,应该仅有一个引起它变化的原因。"本原则是我们非常熟悉地"高内聚性原则"的引申,但是通过将"职责"极具创意地 定义为"变化的原因",使得本原则极具操作性,尽显大师风范。同时,本原则还揭示了内聚性和耦合生,基本途径就是提高内聚性;如果一个类承担的职责过多, 那么这些职责就会相互依赖,一个职责的变化可能会影响另一个职责的履行。其实OOD的实质,就是合理地进行类的职责分配。

开放封闭原则 (Open-Closed principle)。"软件实体应该是可以扩展的,但是不可修改。"本原则紧紧围绕变化展开,变化来临时,如果不必改动软件实体裁的源代码,就能扩充它 的行为,那么这个软件实体设计就是满足开放封闭原则的。如果说我们预测到某种变化,或者某种变化发生了,我们应当创建抽象类来隔离以后发生的同类变化。在 Java中,这种抽象是指抽象基类或接口;在C++中,这各抽象是指抽象基类或纯抽象基类。当然,没有对所有情况都贴切的模型,我们必须对软件实体应该面 对的变化做出选择。

Liskov替换原则(Liskov-Substituion Principle)。"子类型必须能够替换掉它们的基类型。"本原则和开放封闭原则关系密切,正是子类型的可替换性,才使得使用基类型模块无需修改就可 扩充。Liskov替换原则从基于契约的设计演化而来,契约通过为每个方法声明"先验条件"和"后验条件";定义子类时,必须遵守这些"先验条件"和"后 验条件"。当前基于契的设计发展势头正劲,对实现"软件工厂"的"组装生产"梦想是一个有力的支持。

依赖倒置原则(Dependecy- Inversion Principle)。"抽象不应依赖于细节,细节应该依赖于抽象。"本原则几乎就是软件设计的正本清源之道。因为人解决问题的思考过程是先抽象后具体, 从笼统到细节,所以我们先生产出的势必是抽象程度比较高的实体,而后才是更加细节化的实体。于是,"细节依赖于抽象"就意味着后来的依赖于先前的,这是自 然而然的重用之道。而且,抽象的实体代表着笼而统之的认识,人们总是比较容易正确认识它们,而且本身也是不易变的,依赖于它们是安全的。依赖倒置原则适应 了人类认识过程的规律,是面向对象设计的标志所在。

接口隔离原则(Interface-Segregation Principle)。"多个专用接口优于一个单一的通用接口。"本原则是单一职责原则用于接口设计的自然结果。一个接口应该保证,实现该接口的实例对象 可以只呈现为单一的角色;这样,当某个客户程序的要求发生变化,而迫使接口发生改变时,影响到其他客户程序的可能生性小。

良性依赖原则。" 不会在实际中造成危害的依赖关系,都是良性依赖。"通过分析不难发现,本原则的核心思想是"务实",很好地揭示了极限编程(Extreme Programming)中"简单设计"各"重构"的理论基础。本原则可以帮助我们抵御"面向对象设计五大原则"以及设计模式的诱惑,以免陷入过度设计 (Over-engineering)的尴尬境地,带来不必要的复杂性。
                                                                            -----------摘自<<程序员>>



Trackback: http://tb.blog.youkuaiyun.com/TrackBack.aspx?PostId=631404

 
Chapter 3: Introduction to Objects and Classes The Object-Oriented Paradigm Course: CS101: Java Language Programming Instructor: [Instructor Name] Date: September 22, 2025 Practical Session Objective Lab Goal: Refactor to an Object-Oriented Design Our goal is to stop using loose, primitive variables to represent our contact and instead create a proper Contact object. This is a foundational step in building professional software. Prerequisites: Java JDK 11 or higher installed. An IDE like IntelliJ IDEA or VS Code ready. Your MyContactManager project from the last lab. Final Result Preview: The console output will look exactly the same as before, but the underlying code structure will be vastly superior, organized, and ready for future expansion. Step 1: Create the Contact Class Blueprint First, we need to create the blueprint for what a "Contact" is in our application. 1. Goal: Create a new Contact.java file and define the state of a contact. 2. Instructions: 1. In your IDE's project explorer, right-click on your source folder and create a new Java Class. 2. Name the file Contact . This will generate Contact.java . 3. Inside the Contact class, declare the instance variables that every contact will have. These are the same variables that are currently cluttering up your main method. 3. Code Block (for Contact.java ): --- Contact Details --- Name: John Doe Age: 42 Phone: 555-1234 1 2 3 44. Expected Result: You now have two files in your project: MyContactManager.java and Contact.java . The code should compile without errors. Step 2: Instantiate a Contact Object Now that we have the blueprint, let's go back to our main application and create an actual contact from it. 1. Goal: In MyContactManager.java , replace the old primitive variables with a single Contact object. 2. Instructions: 1. Open MyContactManager.java . 2. Delete all the old variable declarations for the contact ( String firstName = "Jane"; , int age = 32; , etc.). 3. In their place, declare and instantiate a new Contact object. 3. Code Block (in main method of MyContactManager.java ): 4. Expected Result: Your main method is now much cleaner. Your code will no longer compile because the parts that used the old variables are now broken. This is good! We'll fix it next. Step 3: Set the Object's State Our contact1 object exists, but its instance variables are all empty ( null or 0 ). Let's fill them with data using dot notation. 1. Goal: Assign values to the instance variables of our new contact1 object. public class Contact { // Instance variables to hold the state of a single contact String firstName; String lastName; int age; String phoneNumber; boolean isFriend; } 1 2 3 4 5 6 7 8 public static void main(String[] args) { // Delete the old variables: // String firstName = "Jane"; (DELETE) // String lastName = "Doe"; (DELETE) // int age = 32; (DELETE) // ...and so on. // Create an object from our blueprint Contact contact1 = new Contact(); // Now we have a single variable, 'contact1', that holds all // the information about our contact. } 1 2 3 4 5 6 7 8 9 10 11 12 132. Instructions: 1. After the line Contact contact1 = new Contact(); , use the dot operator to access each instance variable and assign it a value. 3. Code Block (in main method of MyContactManager.java ): 4. Expected Result: The contact1 object in memory now holds all the data for John Doe. The code still won't compile because the System.out.println statements are broken. Step 4: Get the Object's State Finally, let's fix our print statements to read the data back from the object, again using dot notation. 1. Goal: Update the System.out.println statements to use the object's fields. 2. Instructions: 1. Find your old println statements that are showing compile errors. 2. Prefix each old variable name with contact1. to tell Java to get the value from the object. 3. Code Block (in main method of MyContactManager.java ): 4. Expected Result: All compile errors should now be gone! Your application is fully refactored. // ... after creating the contact object Contact contact1 = new Contact(); // Use dot notation to set the object's state contact1.firstName = "John"; contact1.lastName = "Doe"; contact1.age = 42; contact1.phoneNumber = "555-1234"; contact1.isFriend = false; 1 2 3 4 5 6 7 8 9 // ... after setting the object's state System.out.println("\n--- Contact Details ---"); // OLD: System.out.println("Name: " + firstName + " " + lastName); // NEW: System.out.println("Name: " + contact1.firstName + " " + contact1.lastName); // OLD: System.out.println("Age: " + age); // NEW: System.out.println("Age: " + contact1.age); // OLD: System.out.println("Phone: " + phoneNumber); // NEW: System.out.println("Phone: " + contact1.phoneNumber); 1 2 3 4 5 6 7 8 9 10 11 12 13 14Final Code and Verification Let's look at the final, refactored MyContactManager.java and verify that it works. 1. Goal: Run the application and confirm the output is correct. 2. Code Block (Complete MyContactManager.java ): 3. Expected Output: Success! The output is the same, but our code structure is infinitely better. Optional Challenge Task For Those Who Finish Early... 🚀 If you've completed the refactoring, this challenge will solidify your understanding of objects. Challenge: Create a Second, Independent Object 1. In your main method, create a second Contact object called contact2 . 2. Set the state for contact2 with completely different data (e.g., "Jane Smith", age 35, etc.). 3. Add println statements to display the details for contact2 after displaying the details for contact1 . public class MyContactManager { public static void main(String[] args) { // 1. Create an object (an instance) from the Contact class blueprint Contact contact1 = new Contact(); // 2. Set the state of the object using dot notation contact1.firstName = "John"; contact1.lastName = "Doe"; contact1.age = 42; contact1.phoneNumber = "555-1234"; contact1.isFriend = false; // 3. Get the state of the object using dot notation System.out.println("--- Contact Details ---"); System.out.println("Name: " + contact1.firstName + " " + contact1.lastName); System.out.println("Age: " + contact1.age); System.out.println("Phone: " + contact1.phoneNumber); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 --- Contact Details --- Name: John Doe Age: 42 Phone: 555-1234 1 2 3 4This will prove that contact1 and contact2 are two separate objects in memory, each with its own independent state, even though they were built from the same class blueprint. Q&A and Wrap-up Questions? Today's Most Important Lesson Organizing code into classes that model real-world concepts is the single most powerful strategy for managing complexity in software. We took a chaotic collection of variables and transformed it into a clean, intuitive structure. A Contact is now a "thing" in our program, just as it is in the real world. This is the foundation upon which all large-scale, professional applications are built. What's Next? Up Next: Protecting Our Objects Right now, our code has a major flaw. Anyone using our Contact class can do this: contact1.age = -99; contact1.phoneNumber = "this is not a phone number"; This is dangerous and leads to bugs! An object should be in control of its own data. Next Lecture: Chapter 4: Deeper Dive into Classes - Encapsulation We'll learn about encapsulation, a core OOP principle for data hiding and protection. We'll introduce private variables and public getter/setter methods to create robust, bug-resistant objects. 以上问题的答案是什么
最新发布
09-21
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值