This new edition demonstrates a modeling-based approach to object-oriented development. It is a significant and comprehensive revision of the book. While the central focus remains the same as in previous editions, the reader will notice substantial improvements in the presentation.
Salient features
Brahma Dathan is Professor Emeritus in the Computer Science Department at the Metropolitan State University, Minnesota, USA. He obtained his B.S. in Engineering with special focus on electronics and communication from the University of Kerala, M.Tech. in Computer Science from the Indian Institute of Technology Madras and Ph.D. in Computer Science from the University of Pittsburgh.
Sarnath Ramnath is Professor in the Computer Science and Information Technology Department at St. Cloud State University, Minnesota, USA. He received his B.Tech. and M.Tech. degrees from the Indian Institute of Technology Delhi and his Ph.D. in Computer Science from SUNY, Buffalo. His areas of interest include algorithm analysis and design, data structures, computational geometry and object-oriented software design.
Preface to the Third Edition Chapter 1: Introduction 1.1 What is the Object-Oriented Paradigm? 1.1.1 What Makes the Object-Oriented Approach Preferable? 1.1.2 Object-Oriented Software Development 1.2 Key Concepts of Object-Oriented Design 1.3 Other Related Concepts 1.3.1 Modular Design and Encapsulation 1.3.2 Cohesion and Coupling 1.3.3 Modifiability and Testability 1.3.4 Code Security 1.4 Benefits of the Paradigm 1.5 Dealing with Drawbacks of the Paradigm 1.5.1 Reduced Performance 1.5.2 Complexity of the System 1.5.3 Learning the Object-Oriented Paradigm 1.6 History 1.7 Discussion and Further Reading Projects Exercises References Chapter 2: Basics of Object-Oriented Programming 2.1 The Basics 2.2 Implementing Classes 2.2.1 Constructors 2.2.2 Printing an Object 2.2.3 Sharing Data Across All Objects 2.3 Creating and Working with Related Classes 2.4 Defining and Working with Collections 2.4.1 Creating a Collection Class 2.4.2 Implementation of StudentLinkedList 2.5 Interfaces 2.5.1 Why Use Interfaces? 2.5.2 Improving Reuse with an Interface 2.5.3 Array Implementation of Lists 2.6 Abstract Classes 2.7 Dealing with Run-time Errors 2.8 Inheritance 2.8.1 An Example of a Hierarchy 2.8.2 Inheriting from an Interface 2.8.3 Polymorphism and Dynamic Binding 2.8.4 Protected Fields and Methods 2.9 Design Patterns 2.9.1 Iterating over the Items in a List 2.9.2 Need for a Common Mechanism 2.9.3 The Iterator Pattern 2.10 Run-Time Type Identification 2.11 The Object Class 2.11.1 Using Object as a General Reference 2.11.2 Utility Methods Provided by Object 2.11.3 Methods for System Support 2.12 An Introduction to Generics in Java 2.13 Discussion and Further Reading Projects Exercises References Chapter 3: Modeling Object-Oriented Systems 3.1 A First Example 3.2 Choosing the Diagrams to Describe an Object-Oriented System 3.2.1 Building Models to Represent the System 3.2.2 Diagrams Supported by UML 3.3 Building a User Interface Model 3.3.1 Requirements for an ATM System 3.3.2 Detailed Use Cases for the ATM 3.3.3 A Simple Interface for Course Registration 3.4 Building a Logical Model 3.4.1 A Logical Model for the ATM System 3.4.2 A Logical Model for a College Registration System 3.4.3 Logical Models in Various Stages of Development 3.5 Modeling the Interaction Between Entities 3.5.1 Sequence Diagrams 3.5.2 Communication Diagrams 3.6 Modeling the Behavior of a System 3.6.1 State Transition Diagrams 3.6.2 Activity Diagrams 3.7 Discussion 3.7.1 Which UML Diagrams should we Choose? Projects Exercises Chapter 4: Analyzing a System 4.1 Gathering the Requirements 4.4.1 The Library Case Study 4.2 Building the User Interaction Model 4.2.1 Use Case Analysis 4.2.2 Detailed Use Cases for the Library System 4.3 Defining Conceptual Classes and Relationships 4.3.1 Conceptual Classes for the Library System 4.3.2 Identifying the Relationships Between the Classes 4.4 Using the Knowledge of the Domain 4.5 Discussion and Further Reading Projects Exercises References Chapter 5: Designing a System 5.1 Initiating the Design Process 5.5.1 The Major Subsystems 5.1.2 Identifying the Software Classes 5.2 Assigning Responsibilities to the Classes 5.2.1 Actions that Add New Entities (Populating the System) 5.2.2 Adding/Removing the Relationship Between Existing Entities 5.2.3 Actions that Remove Objects 5.2.4 Actions that Involve Queries 5.3 Designing the Classes 5.3.1 Designing the Member and Book Classes 5.3.2 Building the Collection Classes 5.3.3 Designing the Hold and Transaction Classes 5.3.4 Designing the Library Class 5.3.5 Constructing the User Interface 5.4 Designing for Safety and Security 5.4.1 Ensuring that the Data is not Inconsistent 5.4.2 Preventing Unauthorized Objects from Making Data Updates 5.4.3 Preventing Unauthorized Access through Exported Objects 5.5 Evaluating the Quality of the Software Design 5.5.1 A New Requirement: Charging Fines for Overdue Books 5.5.2 The Initial Design 5.5.3 Evaluating and Improving the Solution 5.6 Discussion and Further Reading 5.6.1 Conceptual Classes and Software Classes 5.6.2 The Single Responsibility Principle 5.6.3 The Interface Segregation Principle 5.6.4 Recognizing Bad Smells and Design Flaws in Object-oriented Programs 5.6.5 Building a Commercially Acceptable System 5.6.6 Further Reading Projects Exercises References Chapter 6: Implementing a System 6.1 Organization of UserInterface and Library 6.6.1 Avoiding the Creation of Multiple Libraries 6.1.2 Structure of Library 6.2 Populating the Database 6.2.1 Adding a Member 6.2.2 Creation of a Member Object 6.2.3 Maintaining the Collection of Member Objects 6.2.4 Using Pre-existing Collection Classes 6.2.5 Implementing Catalog and MemberList 6.3 Modifying Relationships Between Objects 6.3.1 Issuing Books 6.3.2 Placing a Hold 6.3.3 Maintaining the Collection of Holds 6.3.4 Returning Books 6.3.5 Process Holds 6.3.6 Renewing Books 6.4 Removing Objects 6.4.1 Removing a Hold 6.4.2 Removing Books 6.5 Displaying Transactions 6.5.1 The Filtered Iterator 6.6 Other Requirements 6.6.1 Saving and Retrieving Data 6.6.2 Protecting the Data Even Further 6.7 Discussion and Further Reading 6.7.1 Summary of the Implementation 6.7.2 Conceptual, Software, and Implementation Classes 6.7.3 Building a Commercially Acceptable System Projects Exercises Chapter 7: Designing for Reuse 7.1 Reusing through Generic Implementations 7.1.1 Designing a Generic Collection Class 7.1.2 A Caveat on Using the equals() Method 7.1.3 A Different Approach 7.1.4 Instantiating Catalog and MemberList 7.2 Using Reusable Types to Obtain Reusable Implementations 7.2.1 A Reusable Sorting Algorithm 7.3 Building an Inheritance Hierarchy 7.3.1 The Situation Without Inheritance 7.3.2 Using Inheritance to Improve the Design 7.3.3 Invoking the Constructors 7.3.4 Distributing the Responsibilities 7.3.5 Factoring Responsibilities across the Hierarchy 7.4 Combining Inheritance and Composition 7.4.1 The Java Thread Class 7.4.2 Reusing the Person Class in Faculty and Student 7.5 The Importance of Substitutability for Reuse 7.5.1 Extending a Simple Counter 7.5.2 Inheriting from an Abstract Superclass 7.5.3 Upgrading to a Generalized Counter 7.5.4 Defining, Protecting, and Programming to an Abstraction 7.6 Discussion and Further Reading 7.6.1 Language Mechanisms for Reuse 7.6.2 Programming to an Abstraction 7.6.3 Dealing with Variability 7.6.4 Principles of Class Design Projects Exercises References Chapter 8: Modeling with Finite State Machines 8.1 A Simple Example 8.1.1 How to Approach this Problem 8.2 Requirements Analysis using Finite State Modeling 8.2.1 Defining the FSM for the Microwave 8.2.2 State Minimization 8.3 A First Solution to the Microwave Problem 8.3.1 Completing the Analysis 8.3.2 Designing the System 8.3.3 The Implementation Classes 8.3.4 Display Implementations 8.4 Critiquing the Simple Solution 8.4.1 Complexity in Microwave 8.4.2 Communication among Objects 8.5 Using the State Pattern 8.5.1 Creating the State Hierarchy 8.5.2 Transitioning between States 8.5.3 The State Classes 8.6 Communicating the Timing Events 8.6.1 The Observer Pattern 8.6.2 Generating and Handling Timing Events 8.7 Replacing Event Conditionals with Polymorphism 8.7.1 Code Organization 8.8 Employing the FSM Model for Other Types of Applications 8.8.1 Graphical User Interfaces (GUIs) 8.8.2 Modeling a Network Protocol 8.9 Discussion and Further Reading 8.9.1 Implementing the State Pattern 8.9.2 Features of the State Pattern 8.9.3 Consequences of Observer 8.9.4 Recognizing and Processing External Events Projects Exercises References Chapter 9: Interactive Systems and the Model–View–Controller Architecture 9.1 The Model–View–Controller Architectural Pattern 9.1.1 Examples 9.1.2 Implementation 9.1.3 Benefits 9.2 Analyzing a Simple Drawing Program 9.2.1 Specifying the Requirements 9.2.2 Defining the User Interface 9.3.3 Meta Operations 9.3 Detailed Use Cases for the Drawing Operations 9.3.1 Drawing the Shapes 9.3.2 Shape Manipulation Operations 9.4 Designing the Drawing Program 9.4.1 Shape Representation 9.4.2 Interaction between Model, View, and Controller 9.4.3 Interface-Independent Controller 9.4.4 Interface-Independent View 9.4.5 Model–View Separation 9.4.6 Design to Support Undo and Redo 9.4.7 Grouping, Ungrouping, and Shape Collections 9.4.8 Selection, Deletion, and Moving 9.4.9 Controller Structure 9.4.10 Sequence Diagrams for Shape Manipulation 9.4.11 Details of Classes 9.4.12 Final Details of View Design 9.4.13 GUI Design 9.5 Implementation 9.5.1 Starting the Program 9.5.2 Drawing a Line 9.5.3 Selecting Shapes 9.5.4 Grouping Shapes 9.5.5 Moving Shapes 9.6 Pattern-based Solutions 9.6.1 Examples of Architectural Patterns 9.7 Discussion and Conclusion 9.7.1 Adapting to Distributed Systems 9.7.2 Interaction between the GUI and the MVC Subsystems 9.7.3 GUI Frameworks 9.7.4 The Space Overhead for the Command Pattern 9.7.5 Building the Back End Using the State Pattern 9.7.6 How to Store the Shapes 9.7.7 Exercising Caution when Allowing Undo Projects Exercises References Chapter 10: A Deeper Look into Inheritance 10.1 Applications of Inheritance 10.1.1 Restricting Behaviors and Properties 10.1.2 Abstract Superclass 10.1.3 Adding Features 10.1.4 Hiding Features of the Superclass 10.1.5 Combining Structural and Type Inheritance 10.2 Inheritance: Some Limitations and Caveats 10.2.1 Deep Hierarchies 10.2.2 Lack of Multiple Inheritance 10.2.3 Exposed Superclass Features 10.2.4 Changes in the Superclass 10.2.8 Creating False Subtypes 10.2.6 How to Verify Substitutability 10.3 Working with Inheritance 10.3.1 Employing Creational Patterns 10.3.2 Introducing a Parallel Hierarchy 10.3.3 Adding New Functionality to a Hierarchy 10.4 Transmitting Complex Properties Using Inheritance 10.4.1 Creating a Singleton Hierarchy 10.4.2 Inheriting the Property of Self-replication 10.5 Using LSP to Verify Substitutability 10.5.1 The Relationship between Bag, Set, and Queue 10.5.2 Generic Subclassing: Queue of String and Queue of Object 10.5.3 Using Queue of Object in lieu of Queue of String 10.5.4 Why is a Pixel Object not a SolidRectangle? 10.5.5 LSP in Programming Languages 10.6 Multiple Inheritance 10.6.1 Mechanisms for Resolving Conflicts 10.6.2 Repeated Inheritance 10.6.3 Multiple Inheritance in Java 10.7 Discussion and Further Reading 10.7.1 Relating Genericity and Inheritance 10.7.2 Using the Visitor Pattern 10.7.3 Performance Issues for Single Versus Double Dispatch 10.7.4 Ensuring the Safety of Reuse Projects Exercises References Appendix: Java Essentials Index