- 快召唤伙伴们来围观吧
- 微博 QQ QQ空间 贴吧
- 文档嵌入链接
- 复制
- 微信扫一扫分享
- 已成功复制到剪贴板
定点圆弧矩形与矢量叠加
展开查看详情
1 .CMPE 135: Object-Oriented Analysis and Design September 27 Class Meeting Department of Computer Engineering San Jose State University Fall 2018 Instructor: Ron Mak www.cs.sjsu.edu/~mak 1
2 .Point-Circle 2 class Point { public : Point( int x, int y ) : x(x), y ( y ) {} virtual ~Point() {} int get_x () const { return x; } int get_y () const { return y ; } void move ( int dx, int dy ) { x += dx; y += dy ; } private: int x, y ; }; class Circle : public Point { public: Circle(Point center, int r) : Point( center.get_x (), center.get_y ()) , radius(r) {} private: int radius; }; Is there anything wrong with this code? A Circle has a center Point . But a Circle is not a Point .
3 .Point-Circle, Fixed 3 class Point { public : Point( int x, int y ) : x(x), y ( y ) {} virtual ~Point() {} int get_x () const { return x; } int get_y () const { return y ; } void move ( int dx, int dy ) { x += dx; y += dy ; } private: int x, y ; }; class Circle { public: Circle(Point center, int radius) : center(center), radius(radius) {} private: Point center; // composition int radius; }; A Circle has a center Point .
4 .Point-Rectangle Even worse! The upper-left corner is kept in the superclass. The lower-right corner is a member variable. 4 class Rectangle : public Point { public: Rectangle(Point upper_left , Point lr ) : Point( upper_left.get_x (), upper_left.get_y ()) , lower_right ( lr ) {} void move( int dx, int dy ) // override Point::move() { Point::move(dx, dy ); lower_right.move (dx, dy ); } private: Point lower_right ; }; A Rectangle has two Point s. But a Rectangle is not a Point .
5 .Point-Rectangle, Fixed 5 class Rectangle { public: Rectangle(Point upper_left , Point lower_right ) : upper_left ( upper_left ), lower_right ( lower_right ) {} void move( int dx, int dy ) // override Point::move() { upper_left.move (dx, dy ); lower_right.move (dx, dy ); } private: Point upper_left ; // composition Point lower_right ; }; A Rectangle has two Point s.
6 .Vector-Stack 6 #include <string> #include <vector> using namespace std ; class Stack : public vector<string> { public: Stack(); void push (string item); string pop (); }; void Stack:: push (string item) { this-> push_back (item); } T Stack:: pop () { string top_item = this->at(this->size() - 1); this-> pop_back (); return top_item ; } int main () { Stack stk ; stk.push (" A "); stk.push (" B "); stk.push ("C"); stk.erase ( stk.begin () + 1); // remove " B " } A stack is not a special case of a vector. Violates the Liskov Substitution Principle. You cannot substitute a vector by a stack.
7 .Vector-Stack, Fixed 7 #include <string> #include <vector> using namespace std ; class Stack { public: Stack(); void push (string item); string pop (); private: vector<string> stack; }; int main () { Stack < string > stk ; stk.push (" A "); stk.push (" B "); stk.push ("C"); // stk.erase ( stk.begin () + 1); // not allowed } void Stack:: push (string item) { stack.push_back (item); } T Stack:: pop () { string top_item = this->at(this->size() - 1); stack.pop_back (); return top_item ; } A stack is not a vector. Delegate storage to a private vector.
8 .SimUDuck Simulation Game Use object-oriented design techniques to create a duck simulation game . 8 Head First Design Patterns by Eric & Elisabeth Freeman O’Reilly, 2004
9 .SimUDuck Simulation Game , cont’d We need to make the ducks fly. 9 Head First Design Patterns by Eric & Elisabeth Freeman O’Reilly, 2004
10 .Something Went Wrong 10 Head First Design Patterns by Eric & Elisabeth Freeman O’Reilly, 2004
11 .Joe Thinks about Inheritance 11 Head First Design Patterns by Eric & Elisabeth Freeman O’Reilly, 2004
12 .What about Interfaces? 12 Head First Design Patterns by Eric & Elisabeth Freeman O’Reilly, 2004
13 .What about Interfaces? cont’d 13 Head First Design Patterns by Eric & Elisabeth Freeman O’Reilly, 2004
14 .What about Interfaces? cont’d 14 Head First Design Patterns by Eric & Elisabeth Freeman O’Reilly, 2004
15 .Encapsulate What Varies 15 Head First Design Patterns by Eric & Elisabeth Freeman O’Reilly, 2004
16 .Design the Duck Behaviors 16 Head First Design Patterns by Eric & Elisabeth Freeman O’Reilly, 2004 In C++, an interface is a superclass , which is often (but not necessarily) abstract .
17 .Program to an Interface Suppose abstract class Animal has two concrete implementations, Dog and Cat . Program to a specific implementation : Program to an interface : 17 Dog *d = new Dog(); d->bark(); Animal *animal = new Dog(); animal-> make_sound (); Head First Design Patterns by Eric & Elisabeth Freeman O’Reilly, 2004 inflexible much better
18 .Implement the Duck Behaviors 18 Head First Design Patterns by Eric & Elisabeth Freeman O’Reilly, 2004
19 .Code Reuse With this design, other types of objects can reuse our fly and quack behaviors because these behaviors are no longer hidden away in our Duck classes. We can add new behaviors without modifying any of our existing behavior classes or touching any of the Duck classes that use flying behaviors. So we get the benefit of reuse without all the baggage that comes along with inheritance. 19
20 .Delegate Duck Behaviors A Duck can delegate its flying and quacking behavior, instead of using quacking and flying member functions defined in the Duck class or in the subclasses. 20
21 .Delegate Duck Behaviors , cont’d 21 Head First Design Patterns by Eric & Elisabeth Freeman O’Reilly, 2004
22 .class QuackBehavior { public: virtual ~ QuackBehavior () {} virtual void quack() = 0; }; #include " QuackBehavior.h " class Quack : public QuackBehavior { public: void quack() { cout << " Quack!" << endl ; } }; class Squeak : public QuackBehavior { public: void quack() { cout << " Squeak!" << endl ; } }; class Mute : public QuackBehavior { public: void quack() { /* silent */ } }; Quack Behaviors 22 QuackBehavior.h Quack.h The interface Specific implementations
23 .class QuackBehavior { public: virtual ~ QuackBehavior () {} virtual void quack() = 0; }; #include " QuackBehavior.h " class Quack : public QuackBehavior { public: void quack() { cout << " Quack!" << endl ; } }; class Squeak : public QuackBehavior { public: void quack() { cout << " Squeak!" << endl ; } }; class Mute : public QuackBehavior { public: void quack() { /* silent */ } }; Quack Behaviors 22 QuackBehavior.h Quack.h The interface Specific implementations
24 .The Abstract Duck Superclass 24 #include " QuackBehavior.h " #include " FlyBehavior.h " class Duck { public: virtual ~Duck() {} void perform_quack () { quack_behavior ->quack() ; } void perform_fly () { fly_behavior ->fly(); } virtual void identify() = 0; protected: QuackBehavior * quack_behavior ; FlyBehavior * fly_behavior ; }; Quacking is delegated to the QuackBehavior object. Flying is delegated to the FlyBehavior object. Duck.h The interface for a duck
25 .Create Ducks 25 #include " Duck.h " #include " Quack.h " #include " Fly.h " class MallardDuck : public Duck { public: MallardDuck () { quack_behavior = new Quack(); fly_behavior = new Fly(); } void identify() { cout << "Mallard duck" << endl ; } }; class RubberDuck : public Duck { public: RubberDuck () { quack_behavior = new Squeak(); fly_behavior = new NoFly (); } void identify() { cout << "Rubber duck" << endl ; } }; DuckTypes.h Specific duck implementations
26 .Create Ducks 25 #include " Duck.h " #include " Quack.h " #include " Fly.h " class MallardDuck : public Duck { public: MallardDuck () { quack_behavior = new Quack(); fly_behavior = new Fly(); } void identify() { cout << "Mallard duck" << endl ; } }; class RubberDuck : public Duck { public: RubberDuck () { quack_behavior = new Squeak(); fly_behavior = new NoFly (); } void identify() { cout << "Rubber duck" << endl ; } }; DuckTypes.h Specific duck implementations
27 .The Big Picture on Encapsulated Behaviors 27 Head First Design Patterns by Eric & Elisabeth Freeman O’Reilly, 2004
28 .“Has a” is Often Better Than “Is a” Design principle: Composition is more flexible . A duck is composed of quack and fly behaviors. You can set and change behavior at run time. 28 Favor composition over inheritance. “has a” “is a”
29 .The Need for Virtual Destructors Which destructor(s) is/are called? 29 class Person { public: ~Person() { cout << "~Person executed" << endl ; } }; class Employee : public Person { public: ~Employee() { cout << "~Employee executed" << endl ; } private: string name; }; #include " Person.h " int main() { Person *p = new Employee (); delete p; return 0; } Person.h PersonTest.cpp