אביב תשס"ה jctתיכון תוכנה: ד"ר ראובן גלנט1 פרק 8...

40
הההה ההה"הJCT ההההה ההההה: ה"ה ההההה הה הה1 ההה8 הההההה הההההה הההההההה7-9

Post on 20-Dec-2015

228 views

Category:

Documents


9 download

TRANSCRIPT

Page 1: אביב תשס"ה JCTתיכון תוכנה: ד"ר ראובן גלנט1 פרק 8 נקודות חשובות בתרגילים 7-9

1תיכון תוכנה: ד"ר ראובן גלנטJCT אביב תשס"ה

8פרק 7-9נקודות חשובות בתרגילים

Page 2: אביב תשס"ה JCTתיכון תוכנה: ד"ר ראובן גלנט1 פרק 8 נקודות חשובות בתרגילים 7-9

2תיכון תוכנה: ד"ר ראובן גלנטJCT אביב תשס"ה

1. Initializer

Page 3: אביב תשס"ה JCTתיכון תוכנה: ד"ר ראובן גלנט1 פרק 8 נקודות חשובות בתרגילים 7-9

3תיכון תוכנה: ד"ר ראובן גלנטJCT אביב תשס"ה

Inheritance• Make the PressureSensor and TemperatureSensor

inherit from the base class Sensor.• Add directed associations from the Motor to the

PressureSensor and to the TemperatureSensor.• Set the multiplicity to 1.

Page 4: אביב תשס"ה JCTתיכון תוכנה: ד"ר ראובן גלנט1 פרק 8 נקודות חשובות בתרגילים 7-9

4תיכון תוכנה: ד"ר ראובן גלנטJCT אביב תשס"ה

Base Class Sensor• Add attribute name of type OMString• Add a constructor that receives an argument

aName of type OMString • Initialize the attribute in the initializer name(aName)• Create an operation print with implementation

std::cout << name << “ “;

Page 5: אביב תשס"ה JCTתיכון תוכנה: ד"ר ראובן גלנט1 פרק 8 נקודות חשובות בתרגילים 7-9

5תיכון תוכנה: ד"ר ראובן גלנטJCT אביב תשס"ה

Base Class Sensor-Sensor.cpp

//file Sensor.cpp#include “Sensor.h”

Sensor::Sensor(OMString aName): name(aName) { }

void Sensor::print() {std::cout << name << “ “;}

Page 6: אביב תשס"ה JCTתיכון תוכנה: ד"ר ראובן גלנט1 פרק 8 נקודות חשובות בתרגילים 7-9

6תיכון תוכנה: ד"ר ראובן גלנטJCT אביב תשס"ה

Motor Class• Create a constructor that creates instances of

both types of Sensor:• setItsTemperatureSensor(new TemperatureSensor(“T1”));• setItsPressureSensor(new PressureSensor(“P1”));

Page 7: אביב תשס"ה JCTתיכון תוכנה: ד"ר ראובן גלנט1 פרק 8 נקודות חשובות בתרגילים 7-9

7תיכון תוכנה: ד"ר ראובן גלנטJCT אביב תשס"ה

Class Motor- Motor.cpp

//file Motor.cpp#include “Motor.cpp#include “Sensor.h” Motor::Motor() { setItsTemperatureSensor(new TemperatureSensor(“T1”)); setItsPressureSensor(new PressureSensor(“P1”));}

Page 8: אביב תשס"ה JCTתיכון תוכנה: ד"ר ראובן גלנט1 פרק 8 נקודות חשובות בתרגילים 7-9

8תיכון תוכנה: ד"ר ראובן גלנטJCT אביב תשס"ה

Derived Sensor Classes• For both derived Sensor classes:• Create a constructor that has an argument

aName of type OMString• Set the Initializer to Sensor(aName)

Sensor(aName) invokes the Sensor constructor so as to initialize the name field of the base class.

Page 9: אביב תשס"ה JCTתיכון תוכנה: ד"ר ראובן גלנט1 פרק 8 נקודות חשובות בתרגילים 7-9

9תיכון תוכנה: ד"ר ראובן גלנטJCT אביב תשס"ה

Derived Classes: TemperatureSensor.cpp

//file TemperatureSensor.cpp

#include “TemperatureSensor.h”

TemperatureSensor::TemperatureSensor(OMString aName): Sensor(aName) { }

Page 10: אביב תשס"ה JCTתיכון תוכנה: ד"ר ראובן גלנט1 פרק 8 נקודות חשובות בתרגילים 7-9

10תיכון תוכנה: ד"ר ראובן גלנטJCT אביב תשס"ה

Animating• Create a Test component and a Debug configuration

that creates an initial instance of the Motor class• Save / Generate / Make / Run • With the browser, note that there are two instances of

Sensor. Each Sensor has a name that has been initialized.

Page 11: אביב תשס"ה JCTתיכון תוכנה: ד"ר ראובן גלנט1 פרק 8 נקודות חשובות בתרגילים 7-9

11תיכון תוכנה: ד"ר ראובן גלנטJCT אביב תשס"ה

User Types• Using the browser, right-click on the Default

package and select “Add New Type” • add a type tTempUnits declared as

– enum tTempUnits { CELSIUS, FAHRENHEIT };

An alternative declaration is :enum %s { CELSIUS, FAHRENHEIT }.

Page 12: אביב תשס"ה JCTתיכון תוכנה: ד"ר ראובן גלנט1 פרק 8 נקודות חשובות בתרגילים 7-9

12תיכון תוכנה: ד"ר ראובן גלנטJCT אביב תשס"ה

Attribute Unit• Add an attribute unit of type tTempUnits for the

TemperatureSensor.• Add an argument to the TemperatureSensor

constructor called aUnit of the same type • In the initializer add ,unit(aUnit)

Page 13: אביב תשס"ה JCTתיכון תוכנה: ד"ר ראובן גלנט1 פרק 8 נקודות חשובות בתרגילים 7-9

13תיכון תוכנה: ד"ר ראובן גלנטJCT אביב תשס"ה

TemperatureSensor• Change the read operation to :

std::cout << “Temperature = “ << rand() % 100 << “deg “;

if ( unit == CELSIUS )

std::cout << “C” << std::endl;

else

std::cout << “F” << std::endl;

• In the Motor constructor, add the argument “CELSIUS” as follows:

setItsTemperatureSensor (new TemperatureSensor( “T1”, CELSIUS));

Page 14: אביב תשס"ה JCTתיכון תוכנה: ד"ר ראובן גלנט1 פרק 8 נקודות חשובות בתרגילים 7-9

14תיכון תוכנה: ד"ר ראובן גלנטJCT אביב תשס"ה

2. Container Classes (OMCollection)

andIterators

(OMIterator)

Page 15: אביב תשס"ה JCTתיכון תוכנה: ד"ר ראובן גלנט1 פרק 8 נקודות חשובות בתרגילים 7-9

15תיכון תוכנה: ד"ר ראובן גלנטJCT אביב תשס"ה

Using OMIterator• Rhapsody provides an OMIterator class that

can be used as follows to iterate through a container:

OMCollection<Sensor*> itsSensor; // a container

OMIterator<Sensor*> iSensor(itsSensor);iSensor.reset(); // point to firstwhile ( *iSensor != NULL ) { (*iSensor)->print(); // print ++iSensor; // point to next}

Page 16: אביב תשס"ה JCTתיכון תוכנה: ד"ר ראובן גלנט1 פרק 8 נקודות חשובות בתרגילים 7-9

16תיכון תוכנה: ד"ר ראובן גלנטJCT אביב תשס"ה

Collection of Sensors• Load the “Virtual” project and save as “Collection”• Delete from Model the relations between the Motor and

the Sensors. Check in the Browser that these relations have been deleted from the model not just the view.

• Add a directed aggregation itsSensor from the Motor to the Sensor. Set Multiplicity to * (many).

Page 17: אביב תשס"ה JCTתיכון תוכנה: ד"ר ראובן גלנט1 פרק 8 נקודות חשובות בתרגילים 7-9

17תיכון תוכנה: ד"ר ראובן גלנטJCT אביב תשס"ה

OMCollection• Delete implementation of Motor constructor• Save / Generate / Examine code for Motor• Note that the relation has been implemented as a collection of

Sensors:

OMCollection<Sensor*> itsSensor;• Note also that there is an operation

addItsSensor(Sensor* p_Sensor);

Page 18: אביב תשס"ה JCTתיכון תוכנה: ד"ר ראובן גלנט1 פרק 8 נקודות חשובות בתרגילים 7-9

18תיכון תוכנה: ד"ר ראובן גלנטJCT אביב תשס"ה

OMCollection: Motor.h#ifndef Motor_H #define Motor_H #include "PressureSensor.h"#include "TemperatureSensor.h"class Sensor;public : //defined by user void addSensor(); void deleteSensor(); void pollSensors();

public: //defined by Rhapsody OMIterator<Sensor*> getItsSensor() const; void addItsSensor(Sensor* p_Sensor); void removeItsSensor(Sensor* p_Sensor); void clearItsSensor();

protected : OMCollection<Sensor*> itsSensor;};#endif

Page 19: אביב תשס"ה JCTתיכון תוכנה: ד"ר ראובן גלנט1 פרק 8 נקודות חשובות בתרגילים 7-9

19תיכון תוכנה: ד"ר ראובן גלנטJCT אביב תשס"ה

Adding to OMCollection• In the motor constructor add Sensors:

– addItsSensor(new TemperatureSensor(“Sensor1”,CELSIUS));

– addItsSensor(new TemperatureSensor(“Sensor2”,FAHRENHEIT));

– addItsSensor(new PressureSensor(“Sensor3”) );

Page 20: אביב תשס"ה JCTתיכון תוכנה: ד"ר ראובן גלנט1 פרק 8 נקודות חשובות בתרגילים 7-9

20תיכון תוכנה: ד"ר ראובן גלנטJCT אביב תשס"ה

2.a Dependencies

Page 21: אביב תשס"ה JCTתיכון תוכנה: ד"ר ראובן גלנט1 פרק 8 נקודות חשובות בתרגילים 7-9

21תיכון תוכנה: ד"ר ראובן גלנטJCT אביב תשס"ה

Dependencies• In order to compile, the Motor needs to include

the Pressure and Temperature Sensors header files. To do this we will add dependencies from the Motor to those classes:

• Double-click on each dependency and select the stereotype Usage.

Page 22: אביב תשס"ה JCTתיכון תוכנה: ד"ר ראובן גלנט1 פרק 8 נקודות חשובות בתרגילים 7-9

22תיכון תוכנה: ד"ר ראובן גלנטJCT אביב תשס"ה

Implementation Includes• Alternatively instead of drawing dependencies,

we can just modify the properties for the Motor class and for CPP_CG->Class->ImpIncludes add TemperatureSensor.h,PressureSensor.h

CPP_CG means C++ Code Generation.

Page 23: אביב תשס"ה JCTתיכון תוכנה: ד"ר ראובן גלנט1 פרק 8 נקודות חשובות בתרגילים 7-9

23תיכון תוכנה: ד"ר ראובן גלנטJCT אביב תשס"ה

Multiple Relation• Save / Generate / Make / Run• Show that the Motor has a collection of three

Sensors.

Page 24: אביב תשס"ה JCTתיכון תוכנה: ד"ר ראובן גלנט1 פרק 8 נקודות חשובות בתרגילים 7-9

24תיכון תוכנה: ד"ר ראובן גלנטJCT אביב תשס"ה

Statechart• Create a simple Statechart for the Motor class

that calls a pollSensors() routine every two seconds.

Page 25: אביב תשס"ה JCTתיכון תוכנה: ד"ר ראובן גלנט1 פרק 8 נקודות חשובות בתרגילים 7-9

25תיכון תוכנה: ד"ר ראובן גלנטJCT אביב תשס"ה

pollSensors()• Create the pollSensors() operation that will

poll all the Sensors in the collection:

Note that if any more Sensors of any other type are added, the operation still functions!

OMIterator<Sensor*> iSensor(itsSensor);for ( iSensor.reset(); *iSensor; ++iSensor ) { (*iSensor)->print(); (*iSensor)->read();} cout << "---------------------" << endl;

Page 26: אביב תשס"ה JCTתיכון תוכנה: ד"ר ראובן גלנט1 פרק 8 נקודות חשובות בתרגילים 7-9

26תיכון תוכנה: ד"ר ראובן גלנטJCT אביב תשס"ה

Extended Exercise• For the Sensor class, add a static attribute

numberOfSensors of type int with initial value 0.

• In the Sensor Constructor add numberOfSensors++;

• For the Sensor class, add a virtual Destructor with implementation : numberOfSensors--;

• Add the following to pollSensors() cout << “Number of sensors = “ << Sensor::getNumberOfSensors() << endl;

• Generate code and execute to check that numberOfSensors = 3.

Page 27: אביב תשס"ה JCTתיכון תוכנה: ד"ר ראובן גלנט1 פרק 8 נקודות חשובות בתרגילים 7-9

27תיכון תוכנה: ד"ר ראובן גלנטJCT אביב תשס"ה

3. Threads, Active Classes, Statechart Inheritance

Page 28: אביב תשס"ה JCTתיכון תוכנה: ד"ר ראובן גלנט1 פרק 8 נקודות חשובות בתרגילים 7-9

28תיכון תוכנה: ד"ר ראובן גלנטJCT אביב תשס"ה

Concurrency• We want each Sensor to run on its own thread

(active class). • To do so, we need each Sensor to be

Reactive (class that waits for events). • So we will create a Statechart for the base

Sensor class as follows:

Page 29: אביב תשס"ה JCTתיכון תוכנה: ד"ר ראובן גלנט1 פרק 8 נקודות חשובות בתרגילים 7-9

29תיכון תוכנה: ד"ר ראובן גלנטJCT אביב תשס"ה

Active Classes• With the browser, change the concurrency of

the Sensor class from sequential to active.

Page 30: אביב תשס"ה JCTתיכון תוכנה: ד"ר ראובן גלנט1 פרק 8 נקודות חשובות בתרגילים 7-9

30תיכון תוכנה: ד"ר ראובן גלנטJCT אביב תשס"ה

Inheriting Behavior• Open the Statecharts for the PressureSensor

and TemperatureSensor. Note that they have inherited the base class Statechart.

• Specialize the behavior of the TemperatureSensor as below:

Grayed out indicatinginherited behavior

Page 31: אביב תשס"ה JCTתיכון תוכנה: ד"ר ראובן גלנט1 פרק 8 נקודות חשובות בתרגילים 7-9

31תיכון תוכנה: ד"ר ראובן גלנטJCT אביב תשס"ה

Starting the Behavior• Add a call to startBehavior() from the

TemperatureSensor and PressureSensor constructors to initialize the statecharts.

If we had used a composite class, Rhapsody would have done this for us, but that would have been too easy !

Page 32: אביב תשס"ה JCTתיכון תוכנה: ד"ר ראובן גלנט1 פרק 8 נקודות חשובות בתרגילים 7-9

32תיכון תוכנה: ד"ר ראובן גלנטJCT אביב תשס"ה

Multi-threads• Save / Generate / Make / Run• Check that there are four active threads.• Setting the focus to a particular thread displays

the call stack and event queue for that thread.

There will always be one thread called mainThread.

Page 33: אביב תשס"ה JCTתיכון תוכנה: ד"ר ראובן גלנט1 פרק 8 נקודות חשובות בתרגילים 7-9

33תיכון תוכנה: ד"ר ראובן גלנטJCT אביב תשס"ה

Suspending Threads• Note that a thread can be suspended.

Page 34: אביב תשס"ה JCTתיכון תוכנה: ד"ר ראובן גלנט1 פרק 8 נקודות חשובות בתרגילים 7-9

34תיכון תוכנה: ד"ר ראובן גלנטJCT אביב תשס"ה

Problems with the Design• With the current design there are a few

potential problems:– The Motor class needs to know about all

the different types of Sensor.– If another class wants access to the

Sensors, it too will need to depend upon all the different types of Sensor.

– Starting the behavior of a Sensor, in the constructor is not very elegant.

– Adding a new type of Sensor means finding and modifying all classes that use Sensor.

Page 35: אביב תשס"ה JCTתיכון תוכנה: ד"ר ראובן גלנט1 פרק 8 נקודות חשובות בתרגילים 7-9

35תיכון תוכנה: ד"ר ראובן גלנטJCT אביב תשס"ה

4. Singleton, Abstract Factory

Page 36: אביב תשס"ה JCTתיכון תוכנה: ד"ר ראובן גלנט1 פרק 8 נקודות חשובות בתרגילים 7-9

36תיכון תוכנה: ד"ר ראובן גלנטJCT אביב תשס"ה

Improving the Design• Using the “factory method design pattern” will

solve all these concerns.• A SensorFactory class can be introduced that is

used by all classes ( ex: Motor ) that need to get a Sensor. This decouples the Motor class from the actual Sensors and can also start the behavior of the Sensors.

• The SensorFactory will be implemented using the “Singleton design pattern” (to ensure that there is only one instance of SensorFactory).

See the “SensorFactory” example.

Page 37: אביב תשס"ה JCTתיכון תוכנה: ד"ר ראובן גלנט1 פרק 8 נקודות חשובות בתרגילים 7-9

37תיכון תוכנה: ד"ר ראובן גלנטJCT אביב תשס"ה

The Improved Design

Page 38: אביב תשס"ה JCTתיכון תוכנה: ד"ר ראובן גלנט1 פרק 8 נקודות חשובות בתרגילים 7-9

38תיכון תוכנה: ד"ר ראובן גלנטJCT אביב תשס"ה

The Singleton Design Pattern I

Protectedconstructor

Static attribute

Page 39: אביב תשס"ה JCTתיכון תוכנה: ד"ר ראובן גלנט1 פרק 8 נקודות חשובות בתרגילים 7-9

39תיכון תוכנה: ד"ר ראובן גלנטJCT אביב תשס"ה

The Singleton Design Pattern II

Static factoryoperation

Calling thecreateRandomSensor

operation

Page 40: אביב תשס"ה JCTתיכון תוכנה: ד"ר ראובן גלנט1 פרק 8 נקודות חשובות בתרגילים 7-9

40תיכון תוכנה: ד"ר ראובן גלנטJCT אביב תשס"ה

SensorFactory::createRandomSensor()Sensor * SensorFactory::createRandomSensor(){ Sensor* aSensor; OMString aName; char index[10];

//itoa(Sensor::getCount(), index, 10); strcpy ( index, "1" ); aName = "Sensor" + OMString(index);

switch ( rand() % 4 ) { default: case 0: aSensor = new TemperatureSensor( aName, CELSIUS ); break; case 1: aSensor= new TemperatureSensor( aName, FAHRENHEIT ); break; case 2: aSensor = new PressureSensor( aName ); break; case 3: aSensor = new SpeedSensor( aName ); break; } aSensor->startBehavior(); return aSensor;}