Download as pdf or txt
Download as pdf or txt
You are on page 1of 566









































‬ ‫בית הספר למדעי המחשב‬

‬ ‫‪1‬‬

1.1 The Software Crisis

TO SOFTWARE ENGINEERING

Programming in binary…

Full of bugs!

Assembly Language

oAppeared in the late 40s

oLow-level programming language

oMeaningful Words instead of Numbers

oGreat success!

oGreat hope for reducing bugs!

sum:

pushl %ebp simply a sequence of bytes encoding a series of instructions

movl %esp, %ebp

movl 12(%ebp), %eax


addl 8(%ebp), %eax Assembler 55 89 e5 8b 45 0c 03 45 08 01 05 00 00 00 00 5d c3

addl %eax, accum

popl %ebp

ret

Fortran

oFirst appeared in 1957

oDesigned by John Backus

oHigh level programming language

◦ IF-THEN-ELSE

◦ GOTO

◦ DO loops

◦ Etc.

o“Formula Translation”

oThe first optimizing compiler

oMany improvements over the years


◦ Still active today

oEncouraged the production of compilers that generate faster and more efficient code

Programming Languages Evolution

So…

no more bugs then?

High-level languages

Complex software

More bugs

The Software Crisis

o The term used for the difficulty of writing useful and efficient computer programs

o in the required time

o NATO Software Engineering Conference in 1968 at Garmisch, Germany

The Software Crisis

oLinked to the complexity of hardware and the software development process

oThe crisis manifested itself in several ways:

◦ Projects running over-budget

◦ Projects running over-time

◦ Software was very inefficient

◦ Software was of low quality

◦ Software often did not meet requirements

◦ Projects were unmanageable and code difficult to maintain

◦ Software was never delivered

Example: the FBI’s Virtual Case File

oSoftware application developed for the FBI 2000-2005

oOfficially abandoned

oCost the federal government about 400 million dollars

o“incomplete, inadequate and so poorly designed that it would be essentially

unusable under real-world conditions”

o800 pages of requirements… (waterfall approach)

oIt was found out to be irrelevant…

oThe FBI kept changing the requirements…

The Software Crisis

oExamples of suggested solutions:

◦ Tools

◦ Modeling languages

◦ Programming languages

◦ Programming paradigms

◦ Software development and testing methodologies

◦ Etc.

oAt the beginning of the 21st century – only 34% are successful projects

The Software Crisis

Software size and complexity

Developer’s productivity

Development Effort

Size Example

102 Loc Class assignment

103 Loc Small project Programming Effort

104 Loc Semester project

105 Loc Word processor

106 Loc Operating system Software Engineering Effort










































‬ ‫בית הספר למדעי המחשב‬

‬ ‫‪15‬‬

1.2 Introduction To

Software Engineering

DR. ELIAHU KHALASTCHI

History

oIn the 1940s the instructions were wired to the computers – not flexible

oIn the 1950s programming languages started to appear

◦ Fortran, Algol, Cobol

oThe term "software engineering“

◦ coined first by Anthony Oettinger and then used by Margaret Hamilton

◦ the title for the world's first conference on software engineering (1968)

oUp until then, it was a secondary branch of Computer Science

oThe “Software Crises”

History

o1996 – the first BSc academic program (US, Israel)

o1999 – “Software Engineering Body of Knowledge” (SWEBOK) is completed

◦ A document, an international standard

◦ Specifying a guide to the generally accepted Software Engineering Body of Knowledge

◦ Latest version in 2004

oMost of the professionals in the field have background in Computer Science

◦ But are accepted to work as software engineers

oSoftware engineering is now an independent field

Related Fields

Computer

Science

Theoretical

Applied

Quality

Assurance

Software
Computer

Engineering Engineering

Project

Systems Management

Engineering

Software Engineering

As opposed to other engineering disciplines, software engineering

oDoes not ensure consistent, reliable, or even useful products

oThe methods are

◦ Not uniformed

◦ Not regulated

◦ Mostly based on rules of thumb

◦ Lack sold mathematical foundations

oIs it Engineering? Science? Art?

Software Engineering vs. Computer Science

Topic Software Engineering Computer Science

Discovering truths about computability, algorithms, and

Ideal Software system development


other theoretical topics

Developing software that has a value General truths about the complexity, correctness,

Emphasis
to a user soundness and completeness of algorithms

Goal Creating useful software Creating algorithms

Additional Engineering, project management,


Math

knowledge technology

Software Engineering vs. Traditional Engineering

Topic Software Engineering Traditional Engineering

Computer science, Discrete

Fundamentals
mathematics
Physics, chemistry, Calculus

Rules of thumb, not based on a Uniformed, regulated, based on proven mathematical

Methods
solid mathematical foundation models

Development Almost ½ of the total cost. Tools

Relatively cheap.
cost are relatively cheap.

Production cost Trivial Most of the effort goes to production

Product life span Several years Decades










































‬ ‫בית הספר למדעי המחשב‬

‬ ‫‪23‬‬

1.3 Object Oriented Software Engineering

DR. ELIAHU KHALASTCHI

Understand our problem &

Analysis required functionality

Object Oriented Design


Programming Plan a solution that meets these
requirements

Implement the design with an


Object Oriented Programming

Language

Understand our problem &

Analysis required functionality

Object Oriented Design Plan a solution that meets these


requirements

Diagrams, sketches, etc.

No code!

Core Activities

oRequirements

oDesign

oConstruction

oTesting
The Software

oDebugging Development

Cycle

oDeployment

oMaintenance










































‬ ‫בית הספר למדעי המחשב‬

‬ ‫‪31‬‬

1.4 Object Oriented Analysis

DR. ELIAHU KHALASTCHI

Object Oriented Analysis – the steps

oThere are different methodologies, but the ideas are similar:

1. Gather requirements

These steps are not done once.

2. Describe the application

3. Identify the main objects In an iterative approach you

continually revisit and refine

4. Describe the interaction between these objects these steps over the time of

your software development

Create a class diagram

Object Oriented Analysis – the steps

oThere are different methodologies, but the ideas are similar:

1. Gather requirements

2. Describe the application

3. Identify the main objects

4. Describe the interaction between these objects A conceptual model

Create a class diagram Object Oriented Design

Object Oriented Analysis – the steps

oThere are different methodologies, but the ideas are similar:

1. Gather requirements

2. Describe the application

3. Identify the main objects

4. Describe the interaction between these objects

Create a class diagram

Gather Requirements

oFunctional requirements

◦ What does the application suppose to do?

◦ Features

oNon-Functional requirements

◦ Documentation / Help

Examples:

◦ Legal Functional requirements:


the app MUST generate a maze

◦ Performance
the app MUST allow the user to solve a maze

◦ Support the app MUST solve a maze automatically

◦ Security

Non-Functional requirements:

the app MUST return a solution within 3 seconds

FURPS

oFunctional Requirements

◦ Features

oUsability Requirements

◦ Documentation, tutorials

oReliability Requirements

FURPS+
◦ Recovery, acceptable failure rates

• Design Requirements

oPerformance Requirements • Must be an Android app

◦ Response times, memory usage • Implementation Requirements

• Programming language
oSupportability Requirements • Interface Requirements

• With other systems

• Physical Requirements

• Must run on a device with a camera

Object Oriented Analysis – the steps

oThere are different methodologies, but the ideas are similar:

1. Gather requirements

2. Describe the application

3. Identify the main objects

4. Describe the interaction between these objects

Create a class diagram

Describe the application

oFrom the user point of view

oHow does the user accomplish a certain goal with our application

oWrite it in a free, every day, non-technical language

◦ Use case

◦ User stories / scenarios

oExample

1. The user asks to create a maze

2. The UI displays the maze

3. The user moves a character to solve the maze

4. The user asks for a solution

5. The UI displays the solution

1.5 Use Cases

DR. ELIAHU KHALASTCHI

Use Case

oWe have written the requirements (“the app must have this feature”)

oNow we focus on the different users

oUse cases describe how the application should work

◦ From the users perspectives

oA Use Case has a

◦ Title – What is the goal? This is not an isolated feature.

◦ Actor – Who desires it?


It is an interaction

in full context
◦ Scenario – How is it accomplished?

Other typical details of a Use Case

oPreconditions

◦ Conditions that must be satisfied before the action can be taken

oTriggers

◦ The events that lead to the execution of the action

oMain Success Scenario (sunny day scenarios)

oAlternative Scenarios

◦ Also details exceptions and unsuccessful scenarios

Example: Withdraw Money from ATM

oPreconditions

◦ The system has to be online


◦ The money is above a minimal threshold

oTriggers

◦ User’s request

oMain Success Scenario

◦ User logs in, System displays a menu, User selects “money withdrawal”, System registers the transaction,

System counts the money, etc.

oAlternative Scenarios

◦ There isn’t enough money in the ATM

◦ System’s informs the user, System aborts the action, System displays a menu, etc.

Use Case: Title

oAn active-verb (short) goal phrase

othat names the goal of the actor

oExamples

◦ Register a new Student Student registration

◦ Enroll a course

◦ Submit a paper

◦ Grade a paper

◦ View class participants

◦ Upload course material

◦ View course material

Use Case: Actor

oAn actor is not a generic user…

o“Actor” refers to any external system that acts on our system

◦ Different types of users


◦ Each with different goals

◦ Other machines…

Teacher Assistant

Student

Info-Net System

Admin

Lecturer

Staff
Dean

Identifying the Actors

oDoes your system need to interact with other systems / organizations?

◦ Backup systems, web services, external data sources, etc.

oDo you need to distinguish between roles or security groups?

◦ Guests, Registered, Administrator, Owner, etc.

oAre there any different job titles or departments?

◦ Staff, Dean, Lecturer, Teacher Assistant, Board member, etc.

Identifying the Actors

oActors are identified according to goals

Teacher Assistant Student

Courses Syllabus System

Admin Lecturer

Dean Staff

Identifying the Actors

oActors are identified according to goals

Primary Actor Viewer

Courses Syllabus System

Secondary Actor

Editor

Use Case: Scenario

oDescribes the details of accomplishing this one goal

◦ As a paragraph

◦ As a list of steps

oThe typical user should understand it

oExample:

◦ Title: Submit a paper This is not a pseudo code

◦ Actor: Student It is the normal expected flow,

◦ Scenario:
described from the perspective of a user

◦ Student logs in

◦ Student views the course page and enters a submission box

◦ Student uploads a paper

◦ System validates the size of the paper

◦ System stores the paper in the submission box

◦ System responds with confirmation

Identifying Scenarios

oWe look for

◦ User focused goals,

◦ each with several steps,

◦ that can be achieved in one encounter

oExamples

Log in
◦ Submit a paper

◦ Upload course material Build a course

◦ View syllabus

Be concise

oDon’t go into too much details

oThe System connects the server through HTTPS, and uses XML to submit the provided search

problem to be solved, then waits for a response, in the form of a Solution object

oThe system requests a solution to the search problem

Focus on Intention, not UI

oExample:

◦ Title: Submit a paper

◦ Actor: Student This is no mention of:

mouse, click, button, select, link,


◦ Scenario: Java script, object, etc.

◦ Student logs in

◦ Student views the course page and enters a submission box

◦ Student uploads a paper

◦ System validates the size of the paper

◦ System stores the paper in the submission box

◦ System responds with confirmation

◦ …

Use Case Diagram

oA diagram of several use cases and multiple actors at the same time

oWe can get an overview of their interaction within a certain context

oIt is not a replacement for a written use case

oIt is not a sequence diagram

The Diagram

Wikipedia System

Create an article

«actor»
Visitor Search an article

Backup System

View an article

Contributor

Manage users «actor»

Analytics System

View analytics

Administrator

1.6 Conceptual Model

DR. ELIAHU KHALASTCHI

Object Oriented Analysis – the steps

oThere are different methodologies, but the ideas are similar:

1. Gather requirements

2. Describe the application

3. Identify the main objects

4. Describe the interaction between these objects

Create a class diagram

Object Oriented Analysis – the steps

oThere are different methodologies, but the ideas are similar:

1. Gather requirements

2. Describe the application

3. Identify the main objects

4. Describe the interaction between these objects

Create a class diagram

Describe the interaction of objects

oSimply put a line between boxes that have a relationship

oDescribe the relationship

moves
Character

interaction activates Maze creates

User UI Maze
Generator

uses

solves

Solver creates Solution

displays

Displayer

Object Oriented Analysis – the steps

1. Gather requirements

2. Describe the application

3. Identify the main objects

4. Describe the interaction between these objects

Create a class diagram

1.7 Class Diagram Example

DR. ELIAHU KHALASTCHI

Class Diagram

Conceptual Model
Character

creates
*
1

Maze creates
1..* (has)

Generator Maze

<<MazeGenerator>>
creates

<<IMaze>>
generate(): IMaze

Maze

- name: String = “new maze”


2
Position
Maze2D

Generator
- entry, exit: Position
- data: Integer[][]

- isSolved: Boolean 1..*


Character

Maze3D
- characters: Character[]

Generator + setSolved (Boolean)


+ possibleMoves (Position) : Position[]

- formatMazeData () : String
This is a note
+ toString ()

Maze2D

Factory Design Pattern!


Maze3D

1.8 Software Development

Methodologies

DR. ELIAHU KHALASTCHI

Quick & dirty / build & fix

oA methodology for developing and maintaining software fast

oWithout

◦ Defining user requirements

◦ Distinction between development phases


build fix

oLow overhead

oResponsive use

oNo testing no

Customer

oNot suitable for large teams happy?


yes

oTiming

end
oHard to measure progress

oIt takes more time to fix bugs as the development time increases

The waterfall approach

oA linear approach, one life cycle

oUpon completion of a step, you move to the next

oEarly and extensive formalization of requirements

◦ Almost ½ of the development time is dedicated to documentation, not code.

oIt does not work!

oDuring implementation

◦ Encounter problems you didn’t think of

◦ New requirements

◦ The customers (and you) are going to change their mind

The V model

o Each development phase has its own parallel verification phase

o Sophisticated waterfall model

o Attach testing to each development phase

◦ Verification / Validation

o Coding joins two sides of model

Software Prototyping

oThe creation of software prototypes – incomplete versions of the program

◦ Throwaway prototype

◦ after it is approved, software development continues regularly (e.g., waterfall)

◦ Evolutionary prototype
◦ The construction of the prototype continues until the final version

Requirements

oAdvantages

Prototype
◦ Improved and increased user involvement = less time & costs

Review

oDisadvantages

◦ Insufficient analysis
◦ Excessive development time of the prototype Revise

◦ Developer attachment to prototype

◦ Need to avoid quick & dirty!!!

A software development methodology

oShould be responsive

◦ Should allow the addition of new features

◦ Should allow to bugs to be fixed

oShould allow continual programming,

◦ Supported by continual analysis and design

Analysis Analysis Analysis


Design Design Design

oIt should be iterative Programming Programming Programming

◦ Several incremental cycles

◦ Each includes analysis, design and programming

Iterative Incremental Model

oThe product is designed, implemented and tested incrementally

◦ a little more is added each time

oCombines waterfall + the iterative philosophy of prototyping

oAdvantages

◦ Few changes = easier to find bugs

◦ Customer response

◦ Initial product delivery is faster

◦ (and costs lower)

oDisadvantages

◦ Resulting cost >? expected cost

◦ Architectural problems as additional functionality is added

Iterative: +/-

oPros:

◦ Working functionality developed quickly


◦ Results obtained early

◦ Parallel development

◦ Progress easily measured

◦ Less costly to changes

◦ Easy to test in small portions

◦ Ongoing deliveries

oCons:

◦ May require more resources

◦ Management attention

◦ Requires thorough risk analysis


◦ Still cost of change in requirements

◦ Defining increments may require definition of complete system

Iterative: When used?

oRequirements of the system well defined

oSystem with separate components

oMajor requirements defined, some functionalities may evolve in time

oTime constraints

oLarge projects with milestones

oNew, unknown, technology

oHigh risk goals that may change

Spiral Model

oCombination of linear (waterfall) and iterative

oEmphasis on risk analysis

◦ identify risk and alternate solutions

oIncremental release of product

oStages:

1. Identification

2. Design

3. Construct/Build

4. Evaluation and risk analysis

oEach cycle in spiral: linear

oLearning with maturity

Phases of Spiral

oIdentification

◦ Gather business requirements (base)

◦ Identify system/subsystem/unit requirements

oDesign

◦ Conceptual design (base)

◦ Architectural design, logical design of modules, physical design

oConstruction/Build

◦ Production of actual software

◦ Base: Proof of concept


◦ Later: working model of software (build)

oEvaluation and risk analysis

◦ Identifying, estimating, and monitoring technical feasibility and management risks

Spiral: +/-

oPros:

◦ Easily accommodates change in requirements

◦ Early release of system

◦ Development divided into smaller parts

oCons:

◦ Complex management

◦ End of project unknown

◦ Expensive for small / low risk projects

◦ Large number of intermediate steps

Spiral: When used?

oRisk evaluation important

oLarge, complicated projects

oMedium to high risk projects

oLong-term project commitment

oCustomer unsure of requirements

oComplex requirements

oSignificant changes expected throughout development

Agile Model

oBorn early 1990s

oA conceptual framework, with several methodologies

oBreak model into small incremental builds

oEach iteration very short (2-4 weeks) towards feature release

oDuring each iteration, simultaneous work:

◦ Planning, requirement analysis, design, testing

oSimilar to spiral, but shorter phases

Agile Process: Principles

oIndividuals and interactions

◦ Self-organization and motivation are important, as are interactions like co-location and pair

programming.

oWorking software

◦ Demo working software is best means of communication with the customer

◦ Instead of just depending on documentation

oCustomer collaboration

◦ Requirements cannot be gathered completely in the beginning of the project

◦ Continuous customer interaction is crucial for getting proper product requirements

oResponding to change

◦ Focusing on quick responses to change and continuous development.

Agile Process

oCan be used with any type of project, but more common in small-medium projects

oUsed in projects that have quick functional requirements

oWhen requirements are unclear

oPast: used to require local development, now can be anywhere

Extreme Programming (XP)

oBased on the iterative-and-incremental model

oDetermine the various features the client would like the product to support

oBased on the features the client wants:

◦ Development team estimates the duration and cost of each feature

◦ Client selects the features for next build using cost-benefit analysis

◦ The proposed build is broken down into smaller pieces termed tasks

◦ The programmer draws up test cases for a task


Test-driven development (TDD)

oDeliver working software frequently

◦ Ideally every 1 or 2 weeks

88

Extreme Programming (XP)

oThere is no overall design step before the various builds are constructed.

◦ The design is modified while the product is being built: refactoring

oContinuous integration of tasks


◦ Tasks implemented in parallel

oTDD test cases are retained and utilized in all further integration testing

oDeliver working software frequently


◦ Ideally every 1 or 2 weeks

oTimeboxing: Do the best you can during time frame

◦ Demand fixed time, not fixed features

oStand-up meetings

89

SCRUM

oFlexible development strategy

oEach team member has a role, team is a complete functionality

◦ Product owner: customer representative, responsible for managing product backlog

◦ Development team: Develop deliverables at each sprint

◦ SCRUM master

oDeliverables: Sprint

◦ Every 2-4 weeks

◦ No changes once sprint goals are made

SCRUM Burndown Chart

Agile: +/-

oPros:

◦ Realistic
◦ Functionality developed rapidly

◦ Resource requirements minimal

◦ Good for dynamic requirements

◦ Minimal rules

◦ The end result is the high-quality software in the least possible time duration and satisfied customer

◦ Enables concurrent development

◦ Flexible

oCons:

◦ Unsuitable for complex dependencies

◦ High risk for sustainability, maintainability and extensibility


◦ Depends heavily on customer interaction

◦ High individual dependency, no transferability (little documentation)

triple constraints:

schedule, cost, and scope

2.1 Object Oriented Design Principles

Design Principles

o Abstraction Private members,

Iterators,

etc.

o Encapsulation

Class hierarchy to prevent

o Inheritance duplicated code…

Generalization of code

o Polymorphism (general algorithms & containers)

General Principles

o DRY: don’t repeat yourself

◦ Obvious: we do not copy and paste blocks of code

◦ Not obvious: also avoid duplications in


◦ The data base schemers, diagrams and documentation…

◦ “A single source of truth”

o YAGNI: you ain’t gonna need it

◦ Don’t write speculative code, solve the problem you know to exist

o Avoid code smells…

Pointless comments Same name, different meaning



Middle Man


class
Data

A Class with too many variables Inappropriate intimacy


Code Smells

YOU MUST AVOID THEM!

Application-Level Code Smells…

o Duplicated code

◦ Identical or very similar code exists in more than one location

o Contrived complexity

◦ Forced usage of complicated design patterns

◦ where simpler design would suffice

o Trivial modules or layers

◦ When they only call the next layer down

Class-Level Code Smells…

o The GOD class

◦ A master class that tries to do everything…

◦ Has very different responsibilities, which have nothing to do with each other

◦ Has too many instance variables (data members)

◦ Common for a procedural programmer that has leaned only the syntax

o Feature Envy

◦ Does very little except use all the methods of another class

o Inappropriate intimacy
◦ A class that has dependencies on implementation details of another class

Class-Level Code Smells…

o Freeloader

◦ A class that does too little

o Conditional complexity

◦ Too many branches or loops

◦ This may indicate a function needs to be broken up into smaller functions

◦ Or that it has potential for simplification

o Downcasting

◦ A type cast which breaks the abstraction model

◦ Example, java containers before java generics

Class-Level Code Smells…

o A Class with too many variables

◦ Consider divide the responsibilities with another class

o Strikingly similar subclasses

◦ Example, two subclasses that handle different inputs in the same way

o Multiple inheritance

◦ The diamond of death

Class-Level Code Smells…

o Too many none-public methods

◦ Harder to test…

o Data class

◦ Avoid classes that passively store data

◦ Classes should contain data and methods

o Middle Man

◦ A class that delegates all of its work – cut the middle man

◦ Wrappers should manipulate something

Method-Level Code Smells…

o Too many parameters

◦ Harder to read, call and test


◦ The purpose of the function is ill-conceived

◦ Refactor the responsibilities

o Long method
◦ A method that has grown too large

◦ Typically, written by a procedural programmer

o Excessively short / long identifiers

◦ The name of a variable should reflect its function unless the function is obvious

o Excessive return of data

◦ A method that returns more than what each of its callers needs

General Code Smells…

o Same name, different meaning

o Inconsistent names

◦ E.g., if you have open() then you should have close()

o Pointless comments

◦ The code should explain itself

o Lack of comments

◦ Where it is needed






































‬ ‫בית הספר למדעי המחשב‬


‫מרצה‪ :‬ד"ר אליהו חלסצ'י‬



‬ ‫‪14‬‬

2.2 SOLID Principles

ROBERT MARTIN, A.K.A “UNCLE BOB”

DR. ELIAHU KHALASTCHI

Solid principles of OO design

oS

◦ Single Responsibility Principle

oO

◦ Open / Closed Principle

oL

◦ Liskov Substitution Principle

oI

◦ Interface Segregation Principle

oD

◦ Dependency Inversion Principle

Solid principles of OO design

oS Car

◦ Single Responsibility Principle + gas(double): void

+ break(double): void

oO + steer(double): void

◦ Open / Closed Principle + planPath(Destination):Plan

oL

◦ Liskov Substitution Principle

oI

◦ Interface Segregation Principle

oD

◦ Dependency Inversion Principle

Solid principles of OO design

oS Car

◦ Single Responsibility Principle + gas(double): void

+ break(double): void

oO + steer(double): void

◦ Open / Closed Principle

oL RaceCar

◦ Liskov Substitution Principle + gas(double): void

+ break(double): void

oI + steer(double): void

◦ Interface Segregation Principle

oD

◦ Dependency Inversion Principle

Solid principles of OO design

oS <<Car>>

◦ Single Responsibility Principle + gas(double): void

+ break(double): void

oO + steer(double): void

◦ Open / Closed Principle

oL RaceCar FamilyCar AICar

◦ Liskov Substitution Principle

void drive(Car c){ void drive(Car c){

oI … …

◦ Interface Segregation Principle c.gas(40); c.gas(40);

… …

oD c.break(20); ((AICar)c) .autopilot();

◦ Dependency Inversion Principle c.steer(25); …


} }

Solid principles of OO design

oS <<Car>>

◦ Single Responsibility Principle + gas(double): void

+ break(double): void

oO + steer(double): void
+ boost(double): void

◦ Open / Closed Principle + deployParachute():void

oL

◦ Liskov Substitution Principle

RaceCar FamilyCar AICar

oI

◦ Interface Segregation Principle

oD

◦ Dependency Inversion Principle

Solid principles of OO design

oS <<Racer>> <<Car>>

◦ Single Responsibility Principle + gas(double): void

+ boost(double): void
+ break(double): void

oO + deployParachute():void
+ steer(double): void

◦ Open / Closed Principle

oL

◦ Liskov Substitution Principle

RaceCar

oI

◦ Interface Segregation Principle

oD

◦ Dependency Inversion Principle

Solid principles of OO design

oS <<Car>>

◦ Single Responsibility Principle + gas(double): void

+ break(double): void

oO + steer(double): void

◦ Open / Closed Principle

<<Racer>>
oL

◦ Liskov Substitution Principle + boost(double): void

+ deployParachute():void

oI

◦ Interface Segregation Principle RaceCar

oD

◦ Dependency Inversion Principle

Solid principles of OO design

oS

◦ Single Responsibility Principle

oO
Car V-engine

◦ Open / Closed Principle

oL

◦ Liskov Substitution Principle

oI

◦ Interface Segregation Principle

oD

◦ Dependency Inversion Principle

Solid principles of OO design

oS

◦ Single Responsibility Principle

oO
Car <<Engine>>

◦ Open / Closed Principle

oL

Turbo-
◦ Liskov Substitution Principle V-engine

engine

oI

◦ Interface Segregation Principle

oD

◦ Dependency Inversion Principle






































‬ ‫בית הספר למדעי המחשב‬


‫מרצה‪ :‬ד"ר אליהו חלסצ'י‬



‬ ‫‪25‬‬

2.3 GRASP Principles

DR. ELIAHU KHALASTCHI

GRASP

o General Responsibility Assignment Software Patterns

o SOLID and GRASP are not in conflict

◦ GRASP puts the focus on responsibility

o There are 9 ideas in GRASP:

◦ Creator, Controller, Pure Fabrication

◦ Information Expert, High Cohesion, Indirection

◦ Low Coupling, Polymorphism, Protected Variations

Information Expert

o Assign a responsibility to the class that has the information to fulfill it

o Which class should calculate the number of unread emails?

User Mailbox Email

Creator

o Who is responsible for creating an object?

o To assign a creator we need to answer these questions:

◦ Does the creator contain another object?

◦ Does the creator closely use another object?

◦ Does the creator know enough to create an object?

MazeGenerator Maze

Low Coupling / High Cohesion



o Coupling: the level of dependencies between objects


o Decoupling: the process of reducing these dependencies

o Cohesion: how focused is a class around a single responsibility


o We want high cohesion & low coupling

Low High Cohesion, Low Coupling



Cohesion, High Coupling

Controller

o Example: Decouple UI class from a Business class

Business Controller UI

o MVC – Model View Controller

o Is an example of using this idea as an architecture

Pure Fabrication

o If a behavior does not belong anywhere - Put it in a new class

o Instead of forcing it to another class

◦ And thus reduce its cohesion

o It is OK to have a class that represents pure functionality

◦ As long as you know why you are doing it

Indirection

o To reduce coupling, introduce an intermediate object

Indirection

o To reduce coupling, introduce an intermediate object

Indirection
Object

Polymorphism

o Automatically correct behavior based on type

o As opposed to typing <<Searcher>>

◦ Checking the type of a runtime-object

Common

Searcher

o Example:

◦ Searcher s = new Astar(); // or… Astar BFS DFS

◦ Searcher s = new BFS();

◦ The rest of the code is unchanged

◦ It applies the methods of Searcher

Protected Variations

o Protect the project from changes and variations

o Identify the most likely points of change

o And use what we have learned

◦ Encapsulation

◦ Interfaces

◦ Polymorphism / Liskov substitution principle

◦ Open / closed principle

◦ Etc.

o These OO principles allow us to write readable, maintainable, and flexible code.

The Design Patterns we will learn will help you to achieve these design principles and avoid code smells…






































‬ ‫בית הספר למדעי המחשב‬


‫מרצה‪ :‬ד"ר אליהו חלסצ'י‬



‬ ‫‪38‬‬

2.4 Static vs. Dynamic Design

AN EXAMPLE

Static Design – uses inheritance

sort(…){ BubbleSorter

compare(arr[i],arr[i+1]) sort(Employee[] arr): void Static design but

}
compare(Employee e1, Employee e2): int Dynamic binding…

AgeBubbleSorter SalBubbleSorter NameBubbleSorter

compare() // by age compare() // by salary compare() // by name

BubbleSorter s = new AgeBubbleSorter(); BubbleSorter s = new NameBubbleSorter();

s.sort(employees); s.sort(employees);

40

Static Design – problem…

BubbleSorter QuickSorter

sort(Employee[] arr): void


compare(Employee e1, Employee e2): int
sort(Employee[] arr): void
compare(Employee e1, Employee e2): int

AgeBubbleSorter SalBubbleSorter NameBubbleSorter AgeQuickSorter SalQuickSorter NameQuickSorter

compare() // by age compare() // by salary compare() // by name compare() // by age compare() // by salary compare() // by name

MergeSorter

sort(Employee[] arr): void

compare(Employee e1, Employee e2): int

AgeMergeSorter SalMergeSorter NameMergeSorter

compare() // by age compare() // by salary compare() // by name

41

Static Design – problem…

class AgeBubbleSorter extends BubbleSorter{ class AgeQuickSorter extends QuickSorter{

int compare(Employee e1, Employee e2){ int compare(Employee e1, Employee e2){

return e1.Age – e2.Age; return e1.Age – e2.Age;

} }

} }

42

Dynamic Design – uses composition

sort(…){
<<Sorter>> <<Comparator>>

} c.compare(arr[i],arr[i+1]) sort(Employee[] arr, Comparator c): void compare(Employee e1, Employee e2): int

BubbleSorter QuickSorter MergeSorter AgeComp SalComp NameComp

sort() sort() sort() compare() compare() compare()

L Sorter s = new BubbleSorter(); Sorter s = new QuickSorter();

I s.sort(employees, new AgeComp()); s.sort(employees, new AgeComp());

D s.sort(employees, new SalComp()); s.sort(employees, new SalComp());

43





































‬ ‫בית הספר למדעי המחשב‬


‫מרצה‪ :‬ד"ר אליהו חלסצ'י‬



‬ ‫‪1‬‬

3.1 Introduction to Java

DR. ELIAHU KHALASTCHI

Short History

First developed as an internal project in SUN in the early 90’s

The goal: use the same code in different platforms

Almost pure object oriented language

Similar syntax to C++ (why?)

A World Wide Web language

Java editions

Standard Edition (SE)

◦ For general purpose use on desktop PCs, servers and similar devices

Enterprise Edition (EE)

◦ Java SE plus various APIs useful for client–server enterprise applications (mainly server side)

Micro Edition (ME)

◦ A portion of the SE libraries, useful for cellular apps.

Why Java?

Widely used in the industry

Write software on one platform and run it on virtually any other platform

Create programs to run within a Web browser and Web services

Develop server-side applications

Write powerful and efficient applications for mobile phones (android)

5





































‬ ‫בית הספר למדעי המחשב‬


‫מרצה‪ :‬ד"ר אליהו חלסצ'י‬



‬ ‫‪6‬‬

3.2 Java – as a Cross Platform Language

DR. ELIAHU KHALASTCHI

Traditional Architecture – using compilers

Source Code: Machine Code:

Code Libs • Really hard to make a program portable

Compiled to intermediate code • Recompile with new system / user

C
libraries for a specific compiler

Machine Code:
• Harder to reuse code written in other

Code Libs languages

C++ Compiled to intermediate code

• Must implement your own infrastructure


• Memory management

Machine Code:
• Threading

Code Libs

Basic Compiled to intermediate code


• Or be highly dependent on the operating

system services

Compile Time Run Time

What is a JVM?

JVM – java virtual machine

The basic idea:

◦ Instead of compiling your code to native code

◦ The code is “compiled” to the JVM’s native code

◦ It can run on any machine with a JVM

Mainly used for the Java language

Today new languages are JVM based

(Scala, Groovy, Jython, JRuby)

JVM architecture

javac:

Compiler ByteCode

.class public HelloWorldApp

.super java/lang/Object

.method public static main : ([Ljava/lang/String;)V

JVM: Interpreter Interpreter Interpreter


.limit stack 10
.limit locals 10

getstatic java/lang/System out Ljava/io/PrintStream;

ldc “hello world!"


invokevirtual java/io/PrintStream println (Ljava/lang/Object;)V

return

.end method

10

The JVM Architecture – multiplatform

Source Code:

• A multiplatform architecture

javac Compiled JVM


Java • No need to change source code

bytecode
verifier Memory to run on a different system as

Python jython Bytecode


JIT
JRE
Interpreter
Interpreter
//
JIT compiler
compiler
manager,
Threading,
I/O
etc.
Native
long there is a JVM on it

Java Runtime
Code

Environment • Can load classes at runtime

• Regardless of their source code


scalac Operating System

Scala

• A managed environment
• E.g. a garbage collection

“Compile” Time Run Time

11

The .NET Architecture

12

JVM architecture

JRE – Java’s Runtime Environment

◦ This is the JVM (implemented for every machine)

◦ Contains the java interpreter (java command)

◦ The very basic libraries for java’s syntax JVM

JDK

JDK – Java’s Development kit JRE

◦ Contains all the edition’s libraries

◦ Contains the java compiler (javac command)

13

http://docs.oracle.com/javase/8/docs/

Java Files

.java – a java source code (usually contains one class)

.class – a java byte code (“compiled” source)

.jar – Java Archive - used for:

◦ A Java library that can be imported / exported

◦ A runnable file






































‬ ‫בית הספר למדעי המחשב‬


‫מרצה‪ :‬ד"ר אליהו חלסצ'י‬



‬ ‫‪16‬‬

3.3 Java – how does it run?

DR. ELIAHU KHALASTCHI

So how does it run?

We wrote the source code in “HelloWorld.java”

We compiled the code using: “javac HeloWorld.java”

The result is “HelloWorld.class”

◦ This is the byte code

We run the program using: “java HelloWorld” (without an extension)

The JVM loads the .class file and searches for an entry point

18

So, how does it run?

Each Java project has at least one entry point

An entry point is a static method with the following signature:

public static void main(String[] args)

Static members (methods and fields)

◦ are accessible from the class itself

◦ And not from the class’s instance = object

Why does the main needs to be static?

19


HelloWorldApp.Java HelloWorldApp.class

.class public HelloWorldApp
.super java/lang/Object

C:\> javac HelloWorldApp.java
.method public static main : ([Ljava/lang/String;)V

javac .limit stack 10 This file
.limit locals 10 represents

getstatic java/lang/System out Ljava/io/PrintStream; a class



ldc “hello world!"
invokevirtual java/io/PrintStream println (Ljava/lang/Object;)V

return
.end method


C:\> java HelloWorldApp


The argument is
The JVM finds the main

Loads the class into memory We run the
method according to its the class file as

signature, and starts running it. an input to the


• All we have is a class. JVM JVM

• There are no objects yet.

main creates objects.
The
• From a class we can only run
These object interact, and our

program runs.
static methods!

Thus the main has to be static

So, how does it work?

Now, the byte code (in the .class file) is being interpreted by the JVM

◦ Each line is interpreted and executed

Consider the following code

for(int i=0; i<n; i++){

a.method1();

a.method2();

a.method3();

What is the problem? Can be optimized?

21

JIT – Just In Time!

Introducing JIT!

Just In Time – compiler

◦ Runtime compilation! (yes, there is such a thing)

Until now, we knew pre-runtime compilation

JIT offers in runtime to compile parts of the code into native (machine) code

◦ only when it is worth while to do so

So why not compile the entire code before runtime?

◦ What are the benefits of runtime compilation?

22

JIT – Just In Time!

In runtime we have more information

For example, we know what n is (user’s input)

JIT can decide that it is better to compile the loop’s code and “inline” it n times

Also avoids asking i<n each iteration…

If n is to small JIT can decide it is faster to just interpret it

23





































‬ ‫בית הספר למדעי המחשב‬


‫מרצה‪ :‬ד"ר אליהו חלסצ'י‬



‬ ‫‪24‬‬

3.4 Java – Garbage Collector?

DR. ELIAHU KHALASTCHI

GC – Garbage Collector

Java introduced the garbage collector mechanism

The programmer is exempt from having to free allocated memory

(for obvious reasons)

The GC automatically frees objects that are not referenced by any pointer

Can be invoked by System.gc();

◦ Will free all unreferenced objects

26

GC – Garbage Collector

Each class can override the inherited finalize() method

When the GC frees an object it calls finalize()

Used for proper closer of an object before being freed

Remember, the programmer does not have control

when this method is being called by the GC

◦ Unless the programmer invoke it explicitly

27





































‬ ‫בית הספר למדעי המחשב‬


‫מרצה‪ :‬ד"ר אליהו חלסצ'י‬



‬ ‫‪1‬‬

4. JAVA for C++ Developers

DR. ELIAHU KHALASTCHI

4.1 Hello World!

DR. ELIAHU KHALASTCHI

Hello World

The simple example:

public class HelloWorld {

public static void main(String[] args) {

System.out.println("Hello World!");

Conventions:

◦ File name = class name, one class per file

◦ Class’s name starts with capital letter

◦ Object’s name start with lower case letter

◦ Case sensitive

Hello World

Will this work?

public class BadHelloWorld {

public void print(){

System.out.println("Hello World!");

public static void main(String[] args) {

print();

Hello World

Static methods can invoke only static members

public class BadHelloWorld {

public static void print(){

System.out.println("Hello World!");

public static void main(String[] args) {

print();

Hello World

The better, more object oriented example:

public class BetterHelloWorld {

public void print(){ How the main is able to

create an object of the same

System.out.println("Hello World!");
class the main is in??

public static void main(String[] args) {

BetterHelloWorld b=new BetterHelloWorld();

b.print();

7





































‬ ‫בית הספר למדעי המחשב‬


‫מרצה‪ :‬ד"ר אליהו חלסצ'י‬



‬ ‫‪8‬‬

4.2 Java Syntax

DR. ELIAHU KHALASTCHI

Data types

Type Size Min Max Wrapper Defaut

boolean - - - Boolean false


char 16-bit 0 216-1 Character ‘\u0000’

byte 8-bit -128 +127 Byte (byte)0

short 16-bit -215 +215-1 Short (short)0

int 32-bit -231 +231-1 Integer 0

long 64-bit -263 +263-1 Long 0L

float 32-bit Float 0.0f

double 64-bit Double 0.0d

void - Void

On declaration all types are initialized

The size of each type is fixed for every platform

boolean is not a number, only true or false

char is for letters while byte is numerical

Each primitive type has a wrapper class


Sometimes we have to work with objects

10

Variables

Variables must be declared before use

◦ Can be declared anyplace in a scope

Variable names must begin with a letter but can contain letters and digits

Variable names are case sensitive

Examples:
double myAge=29.5;

double herAge;

herAge=myAge-4;

char yes='Y';

Character c=new Character(yes);

Character c1=new Character('N');

11

Constant variables

In Java, the keyword final denotes a constant

Constant variables cannot be assigned more than once

final int max=5; // ok final A a=new A();

final int min; a.setValue(5); // ? ok

min=0; // ok a=new A(); // ? error

min=4; // error

12

Operators

Usual arithmetic operators + - * / are used in Java as in C

divide / and modulus % as in C

Increment ++ and decrement –

There is no operator overloading in Java(!)

int x,y,m; y=2*x+5;

x=20; y+=5;

x++; m=y%2;

13

Relational and Boolean operators

Java uses the same relational operators as C

◦ == (equal to)

◦ != (not equal to)

◦ <, >, <=, >= (less, greater, less or equal, greater or equal)

Java uses the same bitwise operators as C

◦ & (and)

◦ | (or)

◦ ^ (xor)

◦ ~ (not)

14

Boolean expressions

In Java the result of a Boolean expression is a Boolean type

(true or false)

This can’t be converted to an int (as in C)

◦ if (x == y) {…} // Result is a boolean

Java eliminates a common C programming bug

◦ if (x = y) {…} // Ok in C, won’t compile in Java

15

Control flow

Java uses the same control structures as in C

Selection (conditional) statements

◦ if (..) {…}

◦ if (..) {…} else if (..) {…} …. else {…}

◦ switch (..) { case 1: break; … default: break; }

Iteration statements

◦ for (..) {…}

◦ while (..) {…}

◦ do {…} while (..);

16





































‬ ‫בית הספר למדעי המחשב‬


‫מרצה‪ :‬ד"ר אליהו חלסצ'י‬



‬ ‫‪17‬‬

4.3 Java Arrays

DR. ELIAHU KHALASTCHI

Arrays

int[] array1=new int[20]; // 20 cells initialized to 0

int[] array2={1,2,3,4,5}; // 5 cells initialized 1-5

int[][] array3=new int[20][]; // an array of 20 un-initialized

int[] pointers

int[][] array4=new int[20][5];// a matrix of 20x5 cells,

its an array of 20 int[]

pointers that each points


to an array of 5 ints

int[][] array5={ {1,2,3} , {4,5,6} };// an initialized 2x3 matrix

19

Arrays as objects

In Java arrays are objects

For example they have the member length:

int[] array1=new int[20];

for(int i=0;i<array1.length;i++)

System.out.println(array1[i]);

int[][] array4=new int[20][5];

for(int i=0;i<array4.length;i++)

for(int j=0;j<array4[i].length;j++)

System.out.println(array4[i][j]);

20

Iterating an array

A nicer syntax:

int[] array1=new int[20];

for(int a : array1)

System.out.println(a);

int[][] array4=new int[20][5];

for(int[] ar : array4)

for(int a : ar)

System.out.println(a);

21

Copying arrays

As Objects, arrays inherited .clone() method

int [] numbers = { 2, 3, 4, 5};

int [] numbersCopy = (int[]) numbers.clone();

numbersCopy[0]=7;

System.out.println(numbersCopy[0]);

System.out.println(numbers[0]);

Output

22

Copying arrays

int[][] array5={ {1,2,3} , {4,5,6} };// an initialized 2x3 matrix

int[][] array6=array5; // points to the same allocated array

array6[0][0]=0; // changed also array5[0][0] to 0

array6=(int[][]) array5.clone(); // cloning array5…

array6[0][0]=6; // would array5[0][0] change to 6?

// creating a new copy the slow way:

array6=new int[array5.length][array5[0].length];

for(int i=0;i<array5.length;i++)

for(int j=0;j<array5[i].length;j++)

array6[i][j]=array5[i][j];

array6[0][0]=1;// won't affect array5

23

Copying arrays

More efficient way for copying arrays is

The function arraycopy

◦ Provided by the System class

◦ Implemented by native code, therefore faster. Defined as :

public static void arraycopy(Object src, int srcPos, Object dest,

int destPos, int length)

int [] numbers = { 2, 3, 4, 5};

int [] numbersCopy=new int[7] ;

System.arraycopy(numbers, 0, numbersCopy, 4, 3);

for(int i=0;i<7;i++)

Output
System.out.print(numbersCopy[i]+” ”);

0000234

24

Why is it more efficient?

JVM

Java Source
Java Byte Code input Interpret code that copies array

Code
Array copy compiled function

for(int i=0;i<array1.length;i++)

array2[i]=array1[i];

System.arraycopy(array1, 0, array2, 0, array1.length);






































‬ ‫בית הספר למדעי המחשב‬


‫מרצה‪ :‬ד"ר אליהו חלסצ'י‬



‬ ‫‪26‬‬

4.4.1 Java Strings

DR. ELIAHU KHALASTCHI

Strings

Strings are sequences of characters as in C

The standard Java library has a predefined class String

◦ String name = “Mike”;

Strings are immutable (unlike in C)

◦ individual characters in the string cannot be changed

◦ name[0] = ‘m’; // Not allowed!

28

String - concatenating

Strings can be concatenated using the “+” operator

String name1 = "Israel";

String name2 = "Israeli";

String myName=name1+name2;//we will get IsraelIsraeli

In Java, every object, even literals, can be automatically converted to a string

String p="people";

String loveJava="Java is "+4+" gr"+8+" "+p;

// Java is 4 gr8 people

29

Comparing Objects

The “==“ operator compares variables values

If the variable is of primitive type

◦ “==“ checks the equality of the two values

However, if the variables are objects

◦ Their value is an address

◦ “==“ checks the equality of the two addresses

◦ In other words, checks if they are pointing to the same location = referenced to the same

object

To check if two objects are identical use the .equals(Object) function

30

Comparing Strings

Strings are obviously Objects

String S1=new String("moshe");

Do not use “==“ to compare String S2=new String("moshe");


strings

if(S1==S2)

Use the “equals” function System.out.println("equal");

else

System.out.println("not equal");

moshe moshe

if(S1.equals(S2))

s1 s2 System.out.println("equal");

else

For strings with n characters, .equals System.out.println("not equal");

takes O(n), can it be done in O(1)?

31

Comparing Strings

The String Class has the method “intern”

◦ The string that invoked the method is saved in a special pool (hash table)

◦ The method returns the string from the pool

String s1=new String("david“);


O(n) s1 s2
String s2=new String(s1);

if(s1==s2)

System.out.println(“equal");
“david” “david”

else
System.out.println(“not equal"); intern() intern()

if(s1.intern()==s2.intern())

System.out.println(“equal"); O(1)

else
System.out.println(“not equal"); “david”

if(s1.intern()==s2.intern())

System.out.println(“equal");
String Pool

else
System.out.println(“not equal");

32

Comparing Strings

The String Class has the method “intern”

◦ The string that invoked the method is saved in a special pool (hash table)

◦ The method returns the string from the pool

String s1=new String(input); // “david” s1 s2


String s2=new String(s1);

if(s1==s2)

System.out.println(“equal");
“david” “david”

else
System.out.println(“not equal"); intern() intern()

if(s1.intern()==s2.intern())

System.out.println(“equal"); O(n)

else
System.out.println(“not equal"); “david”
??

if(s1.intern()==s2.intern())

System.out.println(“equal"); O(1) String Pool

else
System.out.println(“not equal");

33

Quiz…

String s1 = new String(“hello”);

String s2 = “hello”;

How many objects are in memory?

Does ?

◦ s1 == s2

◦ s1.intern() == s2.intern()

◦ s1.intern() == s2

◦ s2.intern() == s2

Intern in C#

A similar mechanism exists in C#

◦ It is called the “intern pool”

◦ With each string creation the pool is checked for storing the string and a reference is kept

◦ The Intern() is a static method of the String class that returns this reference

string s1 = "MyTest";
string s2 = new StringBuilder().Append("My").Append("Test").ToString();

string s3 = String.Intern(s2);

Console.WriteLine(s2==s1); // operator overloading for Equals – O(n)

Console.WriteLine((Object)s2==(Object)s1); // Different references -> false

Console.WriteLine((Object)s3==(Object)s1); // The same reference -> true O(1)

35





































‬ ‫בית הספר למדעי המחשב‬


‫מרצה‪ :‬ד"ר אליהו חלסצ'י‬



‬ ‫‪36‬‬

4.4.2 Java Strings

DR. ELIAHU KHALASTCHI

String useful methods

A substring() method is provided to access a substring of a larger string

String java="Java";

String s = java.substring(0,3);// Jav

A charAt(int n) method returns the character at position n in the string

String java="Java";

char c = java.charAt(2);// v

38

String useful methods

More than 50 methods were implemented

Here is a short list of some:

◦ int compareTo(String anotherString)

◦ int compareToIgnoreCase(String str)

◦ boolean startsWith(String prefix) / endWith

◦ int indexOf(int ch)

◦ String concat(String str)

◦ String replace(char oldChar,char newChar)

◦ String[] split(String regex)

◦ toLowerCase / toUpperCase

39

StringBuilder

StringBuilder objects are like String object

Except that they can be modified

Internally, these objects are treated like variable-length array of char

String s=new String();

for(int i=0;i<100;i++)

s+=i+",";// wasteful way! amortized O(n)

StringBuilder sb=new StringBuilder();

for(int i=0;i<100;i++)

sb.append(i+",");// efficient way! amortized O(1)

40

Without StringBuilder

String palindrome = "I love java";

int len = palindrome.length();


char[] tempCharArray = palindrome.toCharArray();

char[] charArray = new char[len];

// reverse array of chars

for (int j = 0; j < len; j++)

charArray[j] = tempCharArray[len - 1 - j];

String reversePalindrome = new String(charArray);

System.out.println(reversePalindrome);

Output

avaj evol I

41

With StringBuilder

*/

* second way: with StringBuilder

/*

String s1 = "Ali Babba";

StringBuilder sb = new StringBuilder(s1);

sb.reverse(); // reverse it

System.out.println(sb);

Output

abbaB ilA

42





































‬ ‫בית הספר למדעי המחשב‬


‫מרצה‪ :‬ד"ר אליהו חלסצ'י‬



‬ ‫‪43‬‬

4.5 Parameter Passing in Java

DR. ELIAHU KHALASTCHI

Parameter Passing – General Idea

In a programming language you may have

◦ Value types, and Reference types

Each can be passed by Value or by Reference

As C++ demonstrates well:

void func( Point x );

void func( Point* x );

void func( Point & x );

void func( Point* & x );

Passing Reference Types by Value

void main() {
RAM – Random Access Memory

Rectangle rect;

Point *p1 = new Point();


Address Content Point *p2 = new Point();

p1->Set(20, 45);

rect{
m_TopLeft,
p2->Set(50, 70);
rect.Set(p1, p2);

53 m_BottomRight, delete p1;

color delete p2;


}

}
70 p1 = 86

// inside Rectangle class

74 p2 = 92 void Set(Point* topLeft, Point* bottomRight){


m_TopLeft = *topLeft;

78 topLeft = 86 m_BottomRight = *bottomRight;

82 bottomRight = 92
}

86 { m_x=20, m_y=45 }

92 { m_x=50, m_y=70 }

Passing Reference Types by Value

void main() {
RAM – Random Access Memory

Rectangle rect;

Point *p1 = new Point();


Address Content Point *p2 = new Point();

p1->Set(20, 45);

rect{
m_TopLeft = { 20, 45 }
p2->Set(50, 70);
rect.Set(p1, p2);

53 m_BottomRight = { 50, 70 } delete p1;

color delete p2;


}

}
70 86
p1 = Null

// inside Rectangle class

74 p2 = Null
92 void Set(Point* topLeft, Point* bottomRight){
m_TopLeft = *topLeft;

78 topLeft = 86 m_BottomRight = *bottomRight;

82 bottomRight = 92
}

86 { m_x=20, m_y=45 }

92 { m_x=50, m_y=70 }

Parameter passing in Java

Recall, in Java a variable of a class type is automatically a reference type

◦ Java: Point p; ≡ C++: Point* p;

All parameters in Java are passed “by value”

If it is of primitive type, changes are local

If it is an object’s reference then

◦ Changing its state, has only local effect

◦ e.g., an assignment like “new”, “null” or another object

◦ Invoking members, has a global effect obviously

◦ e.g., calling some method, or setting a field

48

Quiz parameter passing in Java

Consider the following MyInt class:

public class MyInt{

int x;

public MyInt(int x) {

this.x=x;

public int getIntVal(){ return x;}

public void inc(){x+=1;}

49

Quiz parameter passing in Java

What would be the output of this code?

public static void add1(int x){x+=1;} public static void main(String[] args) {

int x=5;

public static void add2(MyInt x){ MyInt myX=new MyInt(5);

x=new MyInt(x.getIntVal() +1 ); add1(x);

} add2(myX);

add3(myX);

public static void add3(MyInt x){ System.out.println(x + "," + myX.getIntVal());

x.inc(); }

50

Quiz 2: which code initializes the array?

A[] as=new A[10];

for(int i=0;i<as.length;i++)

◦ as[i]=new A();

A[] as=new A[10];

for(A a : as)

◦ a=new A();






































‬ ‫בית הספר למדעי המחשב‬


‫מרצה‪ :‬ד"ר אליהו חלסצ'י‬



‬ ‫‪1‬‬

5. Object Orientation in Java

DR. ELIAHU KHALASTCHI

5.1 A quick recap…

DR. ELIAHU KHALASTCHI

Recap…

Java is an OOP language (almost pure)

OOP languages uses

◦ Objects as data structures (fields and methods)

◦ Data abstraction, encapsulation, modularity, polymorphism and inheritance

An object is an instance of a class

A class is loaded only once while its instances can be as many as we whish

Recap…

An instance is created with “new” command


“new” Calls the class’s constructor


Members are called from objects

Static members are called from the class

public

class HelloWorld { public class Run {

public void print() { public static void main(String[] args) {

System.out.println("Hello World!"); HelloWorld h=new HelloWorld();



} h.print();
}
}

Recap…

Given a class A with static method s() and a method m()

We define A a;

what of the following will work?

◦ a.s();

◦ a.m();

◦ A.s();

◦ A.m();






































‬ ‫בית הספר למדעי המחשב‬


‫מרצה‪ :‬ד"ר אליהו חלסצ'י‬



‬ ‫‪7‬‬

5.2 Inheritance

DR. ELIAHU KHALASTCHI

The Object class

Every class in Java inherited the class Object Object

Object is the most general class

Used for general purpose, e.g., Your class

◦ method(Object arg0) – arg0 can be any object

◦ Object array[] – can store any objects

Object’s methods:

Inheritance

In order to avoid the diamond of death

Java allows a class to inherit only 1 class

Inheritance keyword is extends Object

A sub-class extends a super-class


new B();

extends
O:

This refers to the current instance of a class A A:

super refers to the super-class’s instance B: this


this.super
extends

this.super.super

Inheritance

Class A is a super-class of B:

public class A { public class B extends A{ Every Ctor must

private int x,y; public B(int x, int y) {
initialize

the A part.
public A(int x,int y){ super(x, y); super(x,y) must

this.x=x; come first; it is like



}
a C++ initialization

a default
Not this.y=y; }
line…

constructor } A b=new B(10,10);



@Override B b1=new B(11,11);

What will
public String toString(){

System.out.println(b); be the
Why

do we return "implementad on class A\n"+ System.out.println(b1); output?
need this?

"called from "+getClass()+
implementad on class A

", x="+x+" y="+y+"\n";
called from class B, x=10 y=10

}

}
implementad on class A
called from class B, x=11 y=11

Inheritance

public class A { public class B extends A{


private int x,y; public B(int x, int y) {


public A(int x,int y){ Object super(x, y);



this.x=x; b.super.super }

this.y=y; }

} A A b=new B(10,10);
x=10, y=10

@Override b.super B b1=new B(11,11);


public String toString(){



System.out.println(b);
B

return "implementad on class A\n"+ b System.out.println(b1);

"called from "+getClass()+
implementad on class A

", x="+x+" y="+y+"\n";
called from class B, x=10 y=10

}
}

implementad on class A
called from class B, x=11 y=11

Inheritance

public class A { public class B extends A{


private int x,y; public B(int x, int y) {


public A(int x,int y){ Object super(x, y);



this.x=x; b.super.super }

this.y=y; }

} A A b=new B(10,10);
x=10, y=10

@Override
getClass ?
b.super toString ? B b1=new B(11,11);

public String toString(){



System.out.println(b);
B

return "implementad on class A\n"+ b System.out.println(b1);

"called from "+getClass()+
implementad on class A

", x="+x+" y="+y+"\n";
called from class B, x=10 y=10

}
}

implementad on class A
called from class B, x=11 y=11

Inheritance

A final class can’t be extended

public class B extends A{


public final class A {

public B(int x, int y) {

private int x,y;


super(x, y);

public A(int x,int y){


}

this.x=x; }

this.y=y;

Inheritance

A sub-class can override anything except:

◦ private, final or static methods

What methods can be overridden?


public class C { public class D extends C{

private void print1() { private void print1() {

System.out.println("1"); System.out.println("1d");

} }

public final void print2() { public void print2() {

System.out.println("2"); System.out.println("2d");

} }

public static void print3() { public void print3() {

System.out.println("3"); System.out.println("3d");

} }

} }

Dynamic Binding

All the methods in Java are like C++ virtual methods – dynamic binding!

public class Test { Java


class Test{ C++
public:

class A{
public class A {

public void print(){


public:

System.out.println("A"); void virtual print(){


cout<<"A"<<endl;

}
}
}

public class B extends A{ };

public void print(){ class B: public A{


public:
System.out.println("B");

} void virtual print(){

} cout<<"B"<<endl;
}

public void testMe() { };

A a=new B(); void testMe(){


A* a=new B();

a.print(); // B
a->print(); // B
}

} }

};






































‬ ‫בית הספר למדעי המחשב‬


‫מרצה‪ :‬ד"ר אליהו חלסצ'י‬



‬ ‫‪17‬‬

5.3 Abstract Classes & Interfaces

DR. ELIAHU KHALASTCHI

Abstract classes

Until now we’ve seen what can and cannot be extended

But what if we want to force an implementation of a subclass?

When abstract is attached to a method:

◦ It is left unimplemented

◦ The class becomes abstract, and cannot be instanced

◦ Only a subclass that implemented the abstract method can be instanced

Abstract classes

Abstract classes cannot be instanced

public abstract class MyAbstract {

String name;

public MyAbstract(String name){

this.name=name;

} MyAbstract a=new MyAbstract(); // error!

public void welcome(){

System.out.println("hello "+name);

Abstract classes

A concrete subclass can be instanced

◦ Inherit all implemented methods as usual

◦ But must implement all abstract methods

public abstract class MyAbstract public class MyConcrete extends MyAbstract{

{ public MyConcrete(String name) {

String name; super(name);

public MyAbstract(String name){


@Override

this.name=name;

public void welcome() {


}

System.out.println("wlcome "+name);

public abstract void welcome();


}

} }

Interfaces

Interfaces are pure abstract classes

<<I>>
<<I>>
<<I>>

<<I>>
interface
interface
Object interface
interface

Defined by the keyword interface

extends implements

Interfaces are implemented (not extended)

◦ by the keyword is implements A

Multiple implementation of interfaces is allowed in Java

Interfaces are the common language in which objects interact

Interfaces public interface GuitarPlayer {


public void playGuitar();
public interface Lecturer {
public void startTeaching();

public void stop(); public void checkExams();

}
//...
}
//...

public class MusicLecturer implements GuitarPlayer, Lecturer {

@Override
public void startTeaching() {

// TODO Auto-generated method stub

}
@Override

// we can't instantiate an interface public void checkExams() {

//GuitarPlayer guitarPlayer=new GuitarPlayer(); // TODO Auto-generated method stub


// this is OK:

GuitarPlayer guitarPlayer = new MusicLecturer(); }


@Override

guitarPlayer.playGuitar(); public void playGuitar() {


// without casting, we can only expect

// the functionality of a guitar player // TODO Auto-generated method stub


}

//guitarPlayer.startTeaching(); @Override

Lecturer lecturer=new MusicLecturer();


// this is OK: public void stop() {
// TODO Auto-generated method stub

lecturer.startTeaching(); }

How do we use it all?

We use inheritance when

◦ a subclass “is a” type of the super-class

◦ We want to change or extend the super-class’s implementation

Higher up on the hierarchy classes become more abstract

◦ They provide data and functionality common to all the derived classes

◦ They define how the concrete class should interact

◦ They are not suppose to “know” concrete classes

How do we use it all?

We use interfaces

◦ To define what functionality we expect from a given object

◦ When we want to allow another extension

We use static members when

◦ We don’t want an instance to use them

◦ We want them to load only once

◦ We want to define something that is the same for every object

Finally, design patterns provides common and very good solutions

for common problems… (next lessons)






































‬ ‫בית הספר למדעי המחשב‬


‫מרצה‪ :‬ד"ר אליהו חלסצ'י‬



‬ ‫‪26‬‬

5.4 Usage Example

DR. ELIAHU KHALASTCHI

Example

<<Sorter>> BubbleSort sorter=new BubbleSort();

sorter.sort(…);
sort(:Comparable[])

// and other methods specific for bubble sort


measureTime()

Sorter sorter=new BubbleSort();

sorter.sort(…);

// and other methods which apply to any sorter

Bubble Sort Quick Sort Merge Sort

Example

<<Sorter>> <<Comparable<T>>>

sort(:Comparable[])

compareTo(:T) : int
measureTime()

(T = String)
CommonSorter

String

sort(:Comparable[])
compareTo(:String) : int
measureTime()

Bubble Sort Quick Sort Merge Sort

Example

<<Sorter>> public interface Sorter<T>{

void sort(Comparable<T>[] comparables);


sort(:Comparable[])

long measureTime(Comparable<T>[] comparables);


measureTime()

CommonSorter

sort(:Comparable[])
measureTime()

Bubble Sort Quick Sort Merge Sort

Example

public abstract class CommonSorter<T> implements Sorter<T> {

<<Sorter>>
@Override
public long measureTime(Comparable<T>[] comparables) {

sort(:Comparable[]) long time0=System.currentTimeMillis();

sort(comparables);
measureTime()

return System.currentTimeMillis()-time0;

}
CommonSorter }

sort(:Comparable[])
measureTime() public class BubbleSort<T> extends CommonSorter<T>{

@Override

public void sort(Comparable<T>[] comparables) {

//...
Bubble Sort Quick
MergeSort
Sort

if(comparables[i].compareTo(comparables[i+1]))>0)
switchCells(comparables[i],comparables[i+1]);

//...

Example

<<Sorter>> <<Comparable<T>>>

sort(:Comparable[])

compareTo(:T) : int
measureTime()

(T = String)
CommonSorter

String

sort(:Comparable[])
compareTo(:String) : int
measureTime()

public static void main(String[] args) {


Bubble Sort Quick
MergeSort
Sort

String[] abc="B,D,A,F,E,C,G".split(",");

Sorter<String> sorter = new BubbleSort<String>();

sorter.sort(abc);
}






































‬ ‫בית הספר למדעי המחשב‬


‫מרצה‪ :‬ד"ר אליהו חלסצ'י‬



‬ ‫‪1‬‬

6. Java Generics, Lambdas, Containers

DR. ELIAHU KHALASTCHI

6.1 Java <Generics>

AND THE “ TYPE ENSURE” TECHNIQUE

C++ recap on templates

Source code: Complied code:

template<class T> class Holder{

class Holder{ Student* t;

T* t; public:
class Holder{
public: void set(Student
t; * t){ this->t = t; }

void set(T* t){ this->t = t; }


Employee*
Student* get(){ return t; }
public:

T* get(){ return t; } class Holder{


}; void set(Employee * t){ this->t = t; }
int* t;

}; Employee*
public: get(){ return t; }

}; void set(int * t){ this->t = t; }

void main(){ int* get(){ return t; }


Holder<Student> hs;

Holder<Employee> he;
};

Holder<int> hi;

cout << (typeid(hs)==typeid(he)) <<endl;

Java - before 1.5

public class Holder {


Object t;

public void set(Object t){ this.t=t;}

public Object get(){return t;}


h.set(new Employee());

} ((Employee)h.get()).work();

//...
public static void main(String[] args) {

Holder h=new Holder();


((Student)h.get()).study();

h.set(new Student());

((Student)h.get()).study();

h.set(new Employee());

((Employee)h.get()).work();

Java - before 1.5

Since 1.5 – generics!

public class Holder { public class Holder<T> {


Object t; T t;

public void set(Object t){ this.t=t;} public void set(T t){ this.t=t;}

public Object get(){return t;} public T get(){return t;}

} }

public static void main(String[] args) { public static void main(String[] args) {

Holder h=new Holder(); Holder<Student> hs=new Holder<Student>();

hs.set(new Student());

h.set(new Student()); hs.get().study();

((Student)h.get()).study();
Holder<Employee> he=new Holder<Employee>();

h.set(new Employee()); he.set(new Employee());

((Employee)h.get()).work(); he.get().work();

} }

Ensured type safety

public class Holder<T> {


T t;

public void set(T t){ this.t=t;}

public T get(){return t;}

public static void main(String[] args) {

Holder<Student> hs=new Holder<Student>();

hs.set(new Student());

hs.get().study();

Holder<Employee> he=new Holder<Employee>();

he.set(new Employee());

he.get().work();

Ensured type safety

public class Holder<T> {


T t;

public void set(T t){ this.t=t;}

public T get(){return t;} Holder<Student> hs=new Holder<Student>();

} hs.set(new Student());

hs.get().study();

//...
public static void main(String[] args) {

Holder<Student> hs=new Holder<Student>();

hs.set(new Student()); hs.set(new Employee());

hs.get().study();

Holder<Employee> he=new Holder<Employee>();

he.set(new Employee());

he.get().work();

“type ensure” - used by Java

Complied code:

public class Holder<T> { public class Holder {


T t; Object t;

public void set(T t){ this.t=t;} public void set(Object t){ this.t=t;}

public T get(){return t;} public Object get(){return t;}

} Syntax sugar }

Complied code:
public static void main(String[] args) { public static void main(String[] args) {

Holder<Student> hs=new Holder<Student>(); Holder hs=new Holder();

hs.set(new Student()); hs.set(new Student());

hs.get().study(); ((Student)h.get()).study();

Holder<Employee> he=new Holder<Employee>(); Holder he=new Holder();

he.set(new Employee()); he.set(new Employee());

he.get().work(); ((Employee)he.get()).work();

} }

“type ensure” - used by Java

Complied code:

public class Holder<T> { public class Holder {


T t; Object t;

public void set(T t){ this.t=t;} public void set(Object t){ this.t=t;}

public T get(){return t;} public Object get(){return t;}

} }

Implication: We can’t write generic code that requires runtime information

In addition:
• T t = new T();

// Holder<int> hi; - compilation error

• T[] array = new T[10]; Holder<Student> hs=new Holder<Student>();

Holder<Employee> he=new Holder<Employee>();

• t.doSomething(); System.out.println((he.getClass()==hs.getClass()));

Quiz: will this compile in Java?

public class GenericException<T> extends Exception {…}

try {
throw new GenericException<Integer>();

catch(GenericException<Integer> e) {

System.err.println("Integer");

catch(GenericException<String> e) {

System.err.println("String");






































‬ ‫בית הספר למדעי המחשב‬


‫מרצה‪ :‬ד"ר אליהו חלסצ'י‬



‬ ‫‪12‬‬

6.2 Java8

SOME OF THE NEW STUFF…

6.2.1 Default & Static Methods

IN INTERFACES(!)

Default & Static Interface Methods

public interface Recorder{ public interface Logger{

void record(InputStream in); default void log(String str){

System.out.println(str);

default void log(String str){ }


System.out.println(str); }

static void stdPrint(String str){


class MyRecorder implements Recorder, Logger{

System.out.println(str);
}

}
@Override
public void record(InputStream in) {/*...*/}

@Override

public void log(String str) {


// we must implement it here to avoid ambiguous code

Recorder.stdPrint(str);

}
}






































‬ ‫בית הספר למדעי המחשב‬


‫מרצה‪ :‬ד"ר אליהו חלסצ'י‬



‬ ‫‪16‬‬

6.2.2. Lambda Expressions

JAVA 8

Lambda Expressions

public interface FunctionalInterface{


String func(String str);

// Anonymous class...

FunctionalInterface f=new FunctionalInterface() {

@Override

public String func(String str) {

return new StringBuilder(str).reverse().toString();


}

};

System.out.println(f.func("Hello World!"));

Lambda Expressions

public interface FunctionalInterface{


String func(String str);

FunctionalInterface f;
f=(String str)->{return new StringBuilder(str).reverse().toString();};

System.out.println(f.func("Hello World!"));

Lambda Expressions

public interface FunctionalInterface{


String func(String str);

FunctionalInterface f;
f=str->new StringBuilder(str).reverse().toString();

System.out.println(f.func("Hello World!"));

Lambda Expressions

It’s not (just) about the syntax, it’s about the paradigm!

Separation of data and functionality

Functionality can be passed as data – more expressive APIs

Fluent (pipelined) operations – better readability

◦ Instead of nested loops…

Libraries are in control of computations

◦ e.g. internal iterators instead of external

◦ More opportunities for optimizations

◦ Laziness

◦ Parallelism

◦ out-of-order computations






































‬ ‫בית הספר למדעי המחשב‬


‫מרצה‪ :‬ד"ר אליהו חלסצ'י‬



‬ ‫‪22‬‬

6.3 Java Containers

JAVA.UTIL.*

Introduction

Java implemented some very useful data-structures in the java.util.*

library

◦ Called containers

They only handle objects, not primitive types

◦ Instead of int we need to use Integer

◦ Not very memory-efficient

ArrayList<Integer> x=new ArrayList<Integer>();

x.add(new Integer(1));// ok

x.add(2);// also ok

Useful Containers

Java has 2 types of containers:

◦ Collections – collect single values

◦ Lists – sequence is important

◦ Sets – each element appears only once

◦ Maps – map keys to values

The implementation is as you have learned in Data-Structures course

Use them wisely

Useful Containers - collections

Lists:

◦ ArrayList<E> – uses an array

◦ Fast random access: O(1)

◦ Slow addition / deletion from the middle: O(1) amortized

◦ LinkedList<E> – uses a linked list

◦ Slow random access: O(n)

◦ Fast addition / deletion from the middle: O(1)

Example:

List<String> strings=new ArrayList<String>();

strings.add(“hello world”);

Useful Containers - collections

Sets:

◦ HashSet<E> – uses a hash table

◦ Use when search time is important

◦ Object’s int HashCode() method needs to be overridden

◦ Usually we’ll use something ready as String’s hash code

◦ TreeSet<E> – uses a balanced tree

◦ O(log(n)) for random access

◦ Can easily extract a sorted list

Example:

Set<String> strings=new HashSet<String>();

strings.add(“hello world”);

Methods of collections <E>

boolean add(E e)

boolean addAll(Collection<? Extends E> c)

void clear()

boolean contains(Object o)

boolean containsAll(Collection<?> c)

boolean isEmpty()

Iterator<E> iterator()

boolean remove(Object o)

boolean removeAll(Collection<?> c) Example:

boolean retainAll(Collection<?> c) Set<String> names=new HashSet<String>();

int size() //…


List<String> members=new ArrayList<String>();

Object[] toArray() members.add("Moshe");

members.addAll(names);
<T> T[] toArray(T[] a)

Useful Containers

Maps example:

◦ HashMap – uses a hash table

◦ The key object needs to implement hashCode() method

◦ LinkedHashMap

◦ Also stores the order of entry

◦ TreeMap – uses a red-black tree Example:

Map<Integer, Employee> workers;


◦ Can easily extract a sorted list

workers=new HashMap<Integer, Employee>();

workers.put(123456789, new Employee());

Methods of maps <K,V>

V put(K key, V value)

void putAll(Map<? extends K, ? extends V > m)

V get(K key)

void clear()

boolean containsKey(Object key)

boolean containsValue(Object value)

boolean isEmpty()

V remove(Object key)

int size() Example:

Collection<V> values() Map<Integer, Employee> workers;


workers=new HashMap<Integer, Employee>();

Set<K> keySet() workers.put(123456789, new Employee());

Set<Map.Entry<K,V>> entrySet()






































‬ ‫בית הספר למדעי המחשב‬


‫מרצה‪ :‬ד"ר אליהו חלסצ'י‬



‬ ‫‪32‬‬

6.4 Sorting Example

ARRAYLIST & COMPARABLE & COMPARATOR …

Comparators

Java implemented two interfaces

◦ Comparator

◦ Comparable

They are used in a strategy pattern to sort various objects in the containers

interface Comparator { interface Comparable {

int compare(Object o1, Object o2); int compareTo(Object o) ;

} }

Comparators

Java implemented two interfaces

◦ Comparator

◦ Comparable

They are used in a strategy pattern to sort various objects in the containers

interface Comparator <T> { interface Comparable <T> {

int compare(T t1, T t2); int compareTo(T t) ;

} }

Comparable

public class Worker implements Comparable<Worker>{

private double age;

private int salary;

private String name;

@Override

public int compareTo(Worker arg0) {

return salary-arg0.getSalary();

}…

Comparable effect on an ArrayList

ArrayList<Worker> workers = new ArrayList<Worker>(); A dynamic size


array of Worker

workers.add( new Worker(29.5,3000,"Moshe") );

workers.add( new Worker(31.0,5500,"Yosef") ); We can add elements

workers.add( new Worker(25.5,2300,"David") ); using the method add

We can iterate the

for(Worker w : workers)
ArrayList with the

System.out.println(w); for-each syntax

Will sort the array


Collections.sort(workers);
using merge-sort

for(int i=0;i<workers.size(); i++) We can iterate the

System.out.println(workers.get(i)); ArrayList like an array

notice size and get

Comparable effect on an ArrayList

How did Collections.sort knew how to sort?

Because Worker is a Comparable object

◦ The sort algorithm used the compareTo method

◦ It was implemented to compare salaries, thus, the array was sorted by the

salary field

public class Worker implements Comparable<Worker>{

public int compareTo(Worker arg0) {

return salary-arg0.getSalary();

}…

Collections.sort(workers);

Comparable effect on an ArrayList

Why use merge sort and not quick sort?

Its an optimized merge sort

Always takes O(n·log(n)) time

◦ Quick sort might take O(n2) in worst case scenario

Works faster on almost sorted lists

A sorted group of elements is left alone…

Comparator

But what if we want to sort the workers in a different way?

Would we have to implement new code in each of the Worker classes?

No, we can use a comparator

interface Comparator <T> {

int compare(T t1, T t2);

Comparator

We can implement the class:

public class NameComparator implements Comparator<Worker>{

@Override

public int compare(Worker w0, Worker w1) {

return w0.getName().compareTo(w1.getName());

And use:
Collections.sort(workers, new NameComparator());

Comparator

We can do the same with an anonymous class, and lambda expression

Collections.sort(workers, new NameComparator() );

Collections.sort(workers, new
Comparator<Worker>(){

@Override

public int compare(Worker w0, Worker w1) {

return w0.getName().compareTo(w1.getName());

);

Collections.sort(workers,(w0,w1)->w0.getName().compareTo(w1.getName()));






































‬ ‫בית הספר למדעי המחשב‬


‫מרצה‪ :‬ד"ר אליהו חלסצ'י‬



‬ ‫‪43‬‬

6.5 Using iterators

EXAMPLES OF COLLECTIONS AND MAPS

Iterators

Earlier we saw the for-each loop

for(Worker w : workers)

System.out.println(w);

It is actually a shortcut for an Iterator

Iterator<Worker> it=workers.iterator();

while(it.hasNext())

System.out.println(it.next());

Iterators

An Iterator is used for:

◦ Providing access to a container’s elements without publishing its

implementation

◦ Letting the programmers decide how to Iterate

◦ They can extend an Iterator class

◦ Enabling the instancing of several itrators

◦ Some can go up a list

◦ Some can go down

◦ Some can skip every two elements

◦ Etc…

Iterators

A HashSet + Iterator example:

HashSet<Worker> hs=new HashSet<Worker>(); In the Worker class:

hs.add( new Worker(29.5,3000,"Moshe") ); @Override

hs.add( new Worker(31.0,5500,"Yosef") ); public int hashCode(){

hs.add( new Worker(25.5,2300,"David") ); return (name+salary+age).hashCode();

for(Worker w : hs)

System.out.println(w);

Iterator<Worker> it=hs.iterator();

while(it.hasNext())

System.out.println(it.next());

Iterators A HashMap + Iterator example:

HashMap<String,Worker> hm = new HashMap<String, Worker>();

hm.put("Moshe" , new Worker(29.5,3000,"Moshe") );

hm.put("Yosef" , new Worker(31.0,5500,"Yosef") );

hm.put("David" , new Worker(25.5,2300,"David") );

Iterator<String> it=hm.keySet().iterator();

while(it.hasNext()){

String k=it.next();

System.out.println(k+","+hm.get(k));
Moshe
Entry:

key
}

value Moshe

for(String k : hm.keySet()) 29.5

System.out.println(k+","+hm.get(k)); 3000

for(Entry<String,Worker> e : hm.entrySet())

System.out.println(e.getKey()+","+e.getValue());






































‬ ‫בית הספר למדעי המחשב‬


‫מרצה‪ :‬ד"ר אליהו חלסצ'י‬



‬ ‫‪49‬‬

6.6 Collection API

NEW IN JAVA 8

ForEach

<< Iterable<T> >>

List<Integer> list=Arrays.asList(10,12,35); forEach(Consumer<? super T> action): void

iterator(): Iterator<T>
spliterator(): Spliterator<T>

Consumer<? super Integer> action = new Consumer<Integer>() {

@Override for(T t : this)

Collection<E>
public void accept(Integer i) { action.accept(t);

System.out.println(i);

} List<E> Set<E>
};

list.forEach(action);
And many more interfaces & classes…

list.forEach(i->System.out.println(i));

list.forEach(System.out::println);

Common Java8 Functional Interfaces

Predicate<T> - tests the T

Consumer<T> - applies an action on the T

Function<T,U> - given a T, returns a U (transformation)

BiFunction<T,U,V> - transforms (T,U) into a V

Supplier<T> - provides an instance of a T

UnaryOperator<T> - a unary operator T T

BinaryOperator<T> - a binary oprator (T,T) T

java.util.function.*

ForEach for maps

Map<String,Point> points=new HashMap<>();

points.put("init", new Point(0,0));

points.put("max", new Point(10,10));

points.put("min", new Point(-10,-10));

for(Entry<String,Point> e : points.entrySet()){

System.out.println(e.getKey()+","+e.getValue());

points.forEach((K,V)->System.out.println(K+","+V));

points.keySet().forEach(K->System.out.println(K));

points.values().forEach(V->System.out.println(V));

RemoveIf

List<Double> list=new ArrayList(Arrays.asList(10.0,12.5,35.4));

for(Double d : list)

if(d>15)
list.remove(d);

Exception in thread "main" java.util.ConcurrentModificationException

at java.util.ArrayList$Itr.checkForComodification(Unknown Source)

at java.util.ArrayList$Itr.next(Unknown Source)

RemoveIf

List<Double> list=new ArrayList(Arrays.asList(10.0,12.5,35.4));

List<Double> toBeDeleted=new LinkedList<>();

for(Double d : list)

if(d>15)

toBeDeleted.add(d);

list.removeAll(toBeDeleted);

RemoveIf

List<Double> list=new ArrayList(Arrays.asList(10.0,12.5,35.4));

list.removeIf(d-> d>15);

default boolean removeIf(Predicate<? super E> filter)






































‬ ‫בית הספר למדעי המחשב‬


‫מרצה‪ :‬ד"ר אליהו חלסצ'י‬



‬ ‫‪1‬‬

7.1 Exceptions and Data Streams in Java (Files)

DR. ELIAHU KHALASTCHI

16

Exception Handling

All Java programs which deal with files and/or streams

◦ must include exception handling

Exceptions are error conditions encountered in executing class methods

◦ Attempting to read past an end of file

◦ Attempting to read a file that doesn’t exist

◦ Trying to open a malformed URL

◦ Divide by zero

◦ Taking the square root of a negative number

◦ Etc.

19

Exception Handling

Normal error handling (in C) would return an error code (eg. –1)

int func(){
//...
This is simple, and sometimes effective method, but:

if(y==0)

return -1; Sometimes impossible to return a valid error code


z=x/y;

//... Not object oriented!


}

no information about the error is contained in the error code

The code gets ‘polluted’ with error checking code

The client is not obligated to check the error code

It is nicer to have all of the error handling in one place

18

Throwing Exceptions

The method must declare the type of the thrown object

The thrown object should store information about the error

public class PersonalDetails {

String email;

public void setEmail(String email) throws Exception {

if(!email.contains("@"))

throw new Exception("not a valid address");

this.email=email;

//...
}

Handling Exceptions

The calling method should either catch the exception

Or throw it on…

public class Person {

PersonalDetails pd;

public void fillDetailsForm() throws Exception {

//...

String email="abc.gmail.com";

pd.setEmail(email);

// the following lines will be skipped

Handling Exceptions

The calling method should either catch the exception

Or throw it on… public void fillDetailsForm(){

//...

String email="abc.gmail.com";

try {
pd.setEmail(email);

// the following lines will be skipped

} catch (Exception e) {

// this is called

e.printStackTrace();

java.lang.Exception: not a valid address // and the code continues here...


at course.java.test.PersonalDetails.setEmail(PersonalDetails.java:8)

}
at course.java.test.Person.fillDetailsForm(Person.java:10)

course.java.test.Person.main(Person.java:19)
at

Finally block

Always executed… use it for safe exit

public void fillDetailsForm(){

String email="abc.gmail.com";

try {

pd.setEmail(email);

System.out.println("this will not be printed");


} catch (Exception e) {

System.out.println("catching...");

return; // exit the method

// but not before the finally code block!

} finally{

System.out.println("safe exit");

// and the code will not continue here...

System.out.println("this will not be printed");

} o

17

To

Exception inheritance hierarchy

Exceptions are objects encapsulating information

◦ about the type of error which caused the exception

All exception objects derive from Throwable

Two main types of exception object

◦ RuntimeException

◦ Usually a programmer error such as divide by zero


or trying to access an array beyond its limits

◦ IOException

◦ Not generally caused by programmer error and generally relating to I/O or network errors

Throwable

Exception Error

IOException RuntimeException LinkageError,


StackOverflowError,

EOFException, ArithmeticException, OutOfMemoryError,

FileNotFoundException, NullPointerException, …

UnknownHostException, ArrayIndexOutOfBoundException,

… …

Checked Exceptions: Unchecked Exceptions:

- are checked by the compiler to potentially occur - cannot be checked by the compiler to potentially occur

- you have to handle them in your code - you don’t have to handle them in your code






































‬ ‫בית הספר למדעי המחשב‬


‫מרצה‪ :‬ד"ר אליהו חלסצ'י‬



‬ ‫‪11‬‬

7.2 Data Streams in Java

READING AND WRITING

15

input & output streams

Most applications require data to be stored in files

◦ Spreadsheets

◦ Word processing

◦ Etc

Java has extensive facilities for handling files of various types

Associated with files is the general concept of streams

which can be applied to both files and networks

input & output streams

In Java, streams are simply sequences of bytes

We can read a byte stream from an input stream object

We can write a byte stream to an output stream object

Typically input and output stream objects can be files

but they also can be network connections

This generality means we can use the same functions for

accessing networks as well as reading files


14

Streams = sequence of data

Data Streams

Streams support many different kinds of data

◦ including simple bytes

◦ primitive data types

◦ localized characters

◦ and objects

Some streams simply pass on data

Others manipulate and transform the data in useful ways

◦ Decorator Design Pattern!


13

Byte Streams

All byte stream classes are descended of:

◦ InputStream (abstract class)

◦ OutputStream (abstract class)

◦ Derived must implement the function “int read()”

InputStream

PipedInputStream ObjectInputStream FileInputStream

File Streams Example

FileInputStream in = null;

FileOutputStream out = null;

out=new FileOutputStream("myFile.dat");

out.write("Hello World!".getBytes());

myFile.dat:
out.close(); Hello World!

in=new FileInputStream("myFile.dat");

int c;

while((c=in.read()) != -1)

System.out.print(c+",");

104,101,108,108,111,32,87,111,114,108,100,33,

in.close();


12

Important notes

Always close input/output streams (why?)

We got the method “close()” from the interface “closeable”

FileInputStream is very expansive, you should try to avoid using it

◦ it’s only good for low level I/O

Next we will learn efficient ways to read/write characters

Character Streams

All character stream classes are descended of:

◦ Reader (abstract class)

◦ Writer (abstract class)

◦ Derived must implement the methods

◦ read(char[], int, int)

◦ close()

Reader

FileReader InputStreamReader OutputStreamReader


no

File writer / reader Example

FileReader in = null;

FileWriter out = null;

out=new FileWriter("myFile.dat");

out.write("Hello World!"); myFile.dat:

out.close(); Hello World!

in=new FileReader("myFile.dat");

int c;

while((c=in.read()) != -1)

System.out.print(c+","); 104,101,108,108,111,32,87,111,114,108,100,33,

in.close();

FileReader v.s FileInputStream

They both read the file into int variable

FileReader holds the character value in the last 16 bits of the int

FileInputStream holds the character value in the last 8 bits of the int

FileInputStream: FileReader:

int x=in.read() int x=in.read()

Good for Unicode

characters!






































‬ ‫בית הספר למדעי המחשב‬


‫מרצה‪ :‬ד"ר אליהו חלסצ'י‬



‬ ‫‪23‬‬

7.3 Buffered Data Streams

READING AND WRITING

Line-Oriented I/O

Sometimes we would like to read an entire line

A line ends with the characters

◦ “\n” or “\r” or “\r\n”

◦ depends on the operating system

We would like to have a mechanism that supports all the variations

of “End Line”

More importantly, we want to save I/O actions

We need to learn about BufferedStreams

Buffered Streams

Until now we learned that each read and write request is handled

directly by the underlying OS

Very expensive…

Java platform implemented buffered I/O Streams

Read to buffer only when buffer is empty

Write, only when buffer is full

Without a buffer…

I/O source I/O Action I/O Block Source code

FileInputStream in=
new FileInputStream("myfile.txt");

int c;

while((c=in.read())!=-1){

Read Block //..

With a buffer…

I/O source I/O Action I/O Block A Buffer in the RAM

Read Block

Source code

BufferedInputStream in=

new BufferedInputStream(
new FileInputStream("myfile.txt"));

int c;

while((c=in.read())!=-1){

//..

With a buffer…

I/O source I/O Action I/O Block A Buffer in the RAM

Read Block

Source code

BufferedInputStream in=

new BufferedInputStream(
new FileInputStream("myfile.txt"));

int c;

while((c=in.read())!=-1){

//..

Buffered Streams Cont.

Two kind of Buffers, byte oriented and character oriented.

Byte Stream: Character Stream:

BufferedInputStream BufferedOutputStream BufferedReader BufferedWriter

Buffered Reader/Writer Example

BufferedReader reader = null;

PrintWriter writer = null;

reader = new BufferedReader(new FileReader("in.txt"));

writer = new PrintWriter(new FileWriter("out.txt"));

String line;

while ((line = reader.readLine()) != null) {

writer.println(line);

reader.close();

writer.close();

Flushing Buffered Streams

Sometimes it makes sense to write out, in a critical point,

what is inside the buffer without waiting for it to fill

We call this action “flushing”

If you want to flush content of the buffer just use the “flush()”

method (e.g bufferName.flush())






































‬ ‫בית הספר למדעי המחשב‬


‫מרצה‪ :‬ד"ר אליהו חלסצ'י‬



‬ ‫‪33‬‬

7.4 Decorator Design Pattern

Decorator Design Pattern

reader = new BufferedReader(new FileReader("in.txt"));

What does FileReader do inside the BufferedReader constructor?

This is a Decorator Design Pattern!

Reader

{abstract}

BufferedReader InputStreamReader String Reader

FileReader






































‬ ‫בית הספר למדעי המחשב‬


‫מרצה‪ :‬ד"ר אליהו חלסצ'י‬



‬ ‫‪36‬‬

7.5 Scanner

Scanning

Java provides an API that breaks input into tokens

◦ according to their data type

Introducing the class “Scanner”

A simple text scanner which can parse primitive type

◦ and strings using regular expressions

Scanning

A Scanner breaks its input into tokens

Using a delimiter pattern

Which by default matches white-space

The resulting tokens may then be converted into values of different types

Using the various next methods

It is like an iterator!!!

Scanner example

Scanner myScaner=null;

myScaner=new Scanner(

new BufferedReader(

new FileReader("in.txt")));

while(myScaner.hasNext()){

System.out.println(myScaner.next());

Scanner example

String input = "8.5 32,767 3.14159 1,000,000.1";

Scanner s = new Scanner(input);

double sum=0;

while(s.hasNextDouble())

sum+=s.nextDouble();

s.close();

System.out.println(sum);

1032778.74159

Change Delimiters

To use different token separator use:

useDelimiter(String pattern)

pattern – a string specifying a delimiting pattern

For example: String input="1 fish 2 fish red fish blue";

Scanner s=new Scanner(input);

Output:
s.useDelimiter(" fish ");

System.out.println(s.nextInt()); 2

System.out.println(s.nextInt());
red

blue
System.out.println(s.next());

System.out.println(s.next());






































‬ ‫בית הספר למדעי המחשב‬


‫מרצה‪ :‬ד"ר אליהו חלסצ'י‬



‬ ‫‪43‬‬

7.6 Standard Streams

I/O from command

A program is often run from the command line

and interacts with the user in the command line environment

The Java platform supports this kind of interaction

Standard Streams are a feature of many operating systems

By default,

◦ they read input from the keyboard

◦ and write output to the display

Standard streams

Standard input – System.in

Standard output – System.out

Standard error – System.err

These objects are defined automatically and do not need to be opened

Standard Streams are byte streams for historical reasons

But we like character streams, what can we do with System.in?

Wrapping System.in

We can wrap System.in with InputStreamReader and even

BufferedReader:

BufferedReader in = new BufferedReader(

new InputStreamReader(System.in));

String line = in.readLine();

What is this design pattern??

It is an Object Adapter Pattern!

Javadoc:

BufferedReader in = new BufferedReader(

new InputStreamReader(System.in));

String line = in.readLine();

Reader InputStream

{abstract} {abstract}

InputStreamReader






































‬ ‫בית הספר למדעי המחשב‬


‫מרצה‪ :‬ד"ר אליהו חלסצ'י‬



‬ ‫‪49‬‬

7.7 Object Streams

Object Streams

Object streams support I/O of objects

Most, but not all, standard classes support serialization of their

objects

Those that do, implement the Serializable interface

◦ Have a default CTOR

◦ Have setters and getters to all data members

The object stream classes are:

◦ ObjectInputStream and ObjectOutputStream

These classes implement

◦ ObjectInput and ObjectOutput

Object Streams

When you write your object all of it’s sub-objects

must implement Serializable interface

When you read a Serialized object from file

you must do casting to the returned value

because the returned value is “Object” type

Object Streams example

public class Point implements Serializable{

int x,y;

public Point(int x,int y){

this.x=x;

this.y=y;

public String toString(){

return "("+x+","+y+")";

// don’t forget default CTOR, setters & getters

Object Streams example

public class Line implements Serializable{

Point p1,p2;

public Line(Point p1,Point p2){

this.p1=p1;

this.p2=p2;

public String toString(){

return "p1= "+p1+" p2= "+p2;

// don’t forget default CTOR, setters & getters

Object Streams example

Line a=new Line(new Point(2, 3), new Point(4, 5));

System.out.println(a);

ObjectOutputStream out= new ObjectOutputStream(

new FileOutputStream("out.txt"));

out.writeObject(a);

ObjectInputStream in= new ObjectInputStream(

new FileInputStream("out.txt"));

Line b=(Line) in.readObject();

System.out.println(b);






































‬ ‫בית הספר למדעי המחשב‬


‫מרצה‪ :‬ד"ר אליהו חלסצ'י‬



‬ ‫‪1‬‬

8. Data Streams in Java (Sockets, Collection Data)

DR. ELIAHU KHALASTCHI

8.1 Streaming with sockets!

BASIC API…

CLIENT SIDE

Example

IP:127.0.0.1

TCP/IP
Server port: 6400

Internet

Client

Command Line Interface - TCP/IP Client

Let’s build a method that gets the user’s input and sends it somewhere

• We don’t want to define the source and destination

• this should be parameterized

public class CLIclient {


Any source Any destination Protocol dependent

private void readInputsAndSend(BufferedReader in, PrintWriter out,String exitStr){

try {

String line;

while(!(line=in.readLine()).equals(exitStr)){
out.println(line);

out.flush();

} catch (IOException e) { e.printStackTrace();}


public void start(String ip, int port){

try {

Socket theServer=new Socket(ip, port);

System.out.println("connected to server");

BufferedReader userInput=new BufferedReader(new InputStreamReader(System.in));

BufferedReader serverInput=new BufferedReader(new

InputStreamReader(theServer.getInputStream()));

PrintWriter outToServer=new PrintWriter(theServer.getOutputStream());

PrintWriter outToScreen=new PrintWriter(System.out);

// correspond according to a well-defined protocol

readInputsAndSend(userInput,outToServer,"exit");
readInputsAndSend(serverInput,outToScreen,"bye");

userInput.close();

serverInput.close(); public static void main(String[] args) {

outToServer.close(); String ip=args[0];


outToScreen.close(); int port = Integer.parseInt(args[1]);

theServer.close(); CLIclient client=new CLIclient();

client.start(ip, port);

} catch (UnknownHostException e) {/*...*/} }

catch (IOException e) {/*...*/}


}






































‬ ‫בית הספר למדעי המחשב‬


‫מרצה‪ :‬ד"ר אליהו חלסצ'י‬



‬ ‫‪7‬‬

8.2 Streaming with sockets!

BASIC API…

SERVER SIDE

Basic API – handle 1 client


ServerSocket server=new ServerSocket(port);



server.setSoTimeout(1000);

try{

Socket aClient=server.accept(); // blocking call

InputStream inFromClient=aClient.getInputStream();

OutputStream outToClient=aClient.getOutputStream();

Loop this

// interact (read & write) with the client according to protocol Thread

and be this
inFromClient.close(); We want to delegate this

able to outToClient.close();

stop aClient.close();

server.close();

}catch (SocketTimeoutException e) {/*...*/}

Let’s delegate via strategy pattern

public interface ClientHandler{

void handleClient(InputStream inFromClient, OutputStream outToClient);

public class MyServer {

private int port;

private ClientHandler ch;

MyServer <<Client Handler>>


private volatile boolean stop;

public MyServer(int port,ClientHandler ch) {


this.port=port;

this.ch=ch;

stop=false;

Let’s loop and handle multiple clients

private void runServer()throws Exception {


ServerSocket server=new ServerSocket(port);

server.setSoTimeout(1000);

while(!stop){

try{

Socket aClient=server.accept(); // blocking call


try {

ch.handleClient(aClient.getInputStream(), aClient.getOutputStream());

aClient.getInputStream().close();

aClient.getOutputStream().close();
aClient.close();

} catch (IOException e) {/*...*/}

}catch(SocketTimeoutException e) {/*...*/}

server.close();
}

Let’s enable stopping the server

public void start(){

runServer();
}

public void stop(){

stop=true;

// in main()

MyServer server=new MyServer(port, myClientHandler);

server.start(); // should be in a different thread…

// ... wait for administrator to close


server.stop();

Let’s enable stopping the server

public void start(){

new Thread(()->runServer()).start();

// we will learn about it the next semester


}

public void stop(){

stop=true;

// in main()

MyServer server=new MyServer(port, myClientHandler);

server.start(); // should be in a different thread…

// ... wait for administrator to close


server.stop();






































‬ ‫בית הספר למדעי המחשב‬


‫מרצה‪ :‬ד"ר אליהו חלסצ'י‬



‬ ‫‪14‬‬

8.3 Collection API - Streams

NEW IN JAVA 8

Pipes and Filters Architecture

The concept: a data stream is passed by pipes through filters

Each filter manipulates the data stream and passes it on to the next filter

Example:

File

reader Decrypt

Filter Unzip
Filter Tokenizer

Object

reader Object
list

16

Stream

Represents a sequence of elements form a given source

Does not store elements, but rather compute them on demand

Possible sources

◦ Collections, generating function, I/O, etc…

Pipelined usage (fluent)

Intermediate operations / terminal operations

Lazy: only terminal operations trigger a computation

Filter

List<Point> data=new LinkedList<>();

Random r=new Random();

for(int i=0;i<100;i++)

data.add(new Point(r.nextInt(200)-100,r.nextInt(200)-100)); A terminal

operation

data.stream().filter(p->p.getX()>0).forEach(System.out::println);

default Stream<E> stream()


Stream<T> filter(Predicate<? super T> predicate)

Returns a stream consisting of the elements of this stream that

Returns a sequential Stream with


match the given predicate.
this collection as its source.

This is an intermediate operation.

Stream

INTERMEDIATE TERMINAL

returns a Stream returns a result


collect()

distinct()

count()

map() forEach()

flatMap() min() , max()

limit() reduce()

toArray()
peek()

findAny() , findFirst()

sorted() allMatch() , andMatch() , noneMatch()

Map-Reduce Example

List<String> strings=Arrays.asList("the", "answer", "to", "life", "the", "universe",

"and", "everything", "=", "42");

int totalLength = strings.stream().map(String::length).reduce(0, (x,y)->x+y);

System.out.println(totalLength); // wow! its 42!!

Map-Reduce Example

List<String> strings=Arrays.asList("the", "answer", "to", "life", "the", "universe",

"and", "everything", "=", "42");

int totalLength = strings.stream().map(String::length).reduce(0, (x,y)->x+y);

System.out.println(totalLength); // wow! its 42!!

Filtering info from Files

BufferedReader in=new BufferedReader(new FileReader(fileName));

List<String> errors=new LinkedList<>();

String line;

while(errors.size()<10 && (line=in.readLine())!=null)


if(line.startsWith("ERROR:"))

errors.add(line);

also new to Java 8

in.close();

errors=Files.lines(Paths.get(fileName))

.filter(s->s.startsWith("ERROR:"))

.limit(10)
.collect(Collectors.toList());

Filtering info from Files

BufferedReader in=new BufferedReader(new FileReader(fileName));

List<String> errors=new LinkedList<>();

String line;

while(errors.size()<10 && (line=in.readLine())!=null)


if(line.startsWith("ERROR:"))

errors.add(line);

in.close();

Stream<String> s=Files.lines(Paths.get(fileName))

errors=s.filter(s->s.startsWith("ERROR:"))
.limit(10)

.collect(Collectors.toList());

s.close();

groupinBy https://docs.oracle.com/javase/8/docs/api/java/util/stream/Collectors.html

List<Employee> employees=new LinkedList<>();

employees.add(new Employee(18, "Moshe"));


employees.add(new Employee(18, "Tzipi"));

employees.add(new Employee(25, "Alon"));

employees.add(new Employee(22, "Tal"));

employees.add(new Employee(22, "Tomer"));

Map<Integer,List<Employee>> EmpByAge = employees.stream() output:

.filter(e->e.name.startsWith("T")) 18:

.collect(Collectors.groupingBy(e->e.age)); Tzipi

22:
EmpByAge.forEach((age,emps)->{ Tal

System.out.println(age+":"); Tomer

emps.forEach(e->System.out.println("\t"+e.name));

});

Parallel Streams
fork-join pool

long sum = employees.parallelStream()

.filter(e-> e.getClass().equals(Manager.class))

.map(Employee::getSalary)

.reduce(0, (x,y)->(x+y));

CPU1 1st chunk CPU2 2nd chunk

Stream 30 33 25 19 20 35 21 22

0 + 0 +

30 + 20 +

63 + 55 +

88 + 76 +

107 + 98

205 …






































‬ ‫בית הספר למדעי המחשב‬


‫מרצה‪ :‬ד"ר אליהו חלסצ'י‬



‬ ‫‪1‬‬

9. From Pseudo code to Object Oriented Java code

DR. ELIAHU KHALASTCHI

9.1 Computational Thinking

DR. ELIAHU KHALASTCHI

Let’s say we want to solve these problems

We refer to each problem setting as a domain

Unscramble Domain: Parking Lot Domain: Maze Domain:

LI oJe vvaa

I Love Java

- A state represents the current string - A state may represent the position of the mouse

- The cost to switch two letters can - The cost to move diagonally can be 15
be derived from their distance

- Which switches do we need?


- The cost to move directly can be 10
- What is the cheapest path?

- A state represents current car positions

- Each car may have a different “move” value


- How can we get the black car out?

We can use the Best First Search algorithm


Best First Search:



= [initial state] // a priority queue of states to be evaluated
OPEN A OPEN CLOSED

CLOSED = [] // a set of states already evaluated 10 20 A {0,null}



OPEN is not empty
while
B {10,A}
do 5

1. n dequeue(OPEN) // Remove the best node from OPEN


B C {20,A}
C {15,B}
2.
add(n,CLOSED) // so we won’t check n again 10 10 D {20,B}
3.
If n is the goal state,
E {25,C}

backtrace path to n (through recorded parents) and return path. D E
4. Create n's successors. G {35,E}

5. For each successor s do:


{120,D}

a. If s is not in CLOSED and s is not in OPEN: 100 10

i. update that we came to s from n Goal Goal E C B A

ii. add(s,OPEN)
b. Otherwise, if this new path is better than previous one

i. If it is not in OPEN add it to OPEN.

ii. Otherwise, adjust its priority in OPEN

done

5





































‬ ‫בית הספר למדעי המחשב‬


‫מרצה‪ :‬ד"ר אליהו חלסצ'י‬



‬ ‫‪6‬‬

9.2 Object Oriented Design for The Algorithm

DR. ELIAHU KHALASTCHI

We do not just implement it inside one class…

We need to think about the design!!!

We need to think how this algorithm is going to be used

◦ In different projects

◦ For different problems

Where to start?

It is probably a good idea to suppurate items which are

◦ Domain Specific - specific to a certain domain e.g., the cost to move the mouse

◦ Domain Independent - not specific to a certain domain

We want to create a domain independent implementation

of the BFS algorithm

Decouple the algorithm from the problem it solves!

We need to start by defining what we expect from

◦ A general search problem

◦ A general search algorithm

This expectation is the functionality of these entities

In other words, we should define their interfaces

Later, each entity can have different independent implementations

<<algorithm>> <<problem>>






































‬ ‫בית הספר למדעי המחשב‬


‫מרצה‪ :‬ד"ר אליהו חלסצ'י‬



‬ ‫‪10‬‬

10 20

5
B C

10 10

10

100
Goal

9.3 Design the Searchable Problem

DR. ELIAHU KHALASTCHI

We can start with a general State class

Since each node represents a “state” of the problem, we can create a State class

Inside, we can use whatever types that can describe states generally

public class State {


private String state; // the state represented by a string

private double cost; // cost to reach this state

private State cameFrom; // the state we came from to this state

public State(String state){ // CTOR


this.state = state;

@Override

public boolean equals(Object obj){ // we override Object's equals method


return state.equals(((State)obj).state);

// ...

12

We can start with a general State class

Since each node represents a “state” of the problem, we can create a State class

Inside, we can use whatever types that can describe states generally

public class State {


private String state; // the state represented by a string

private double cost; // cost to reach this state

private State cameFrom; // the state we came from to this state

Example of Use:

public State(String state){ // CTOR


this.state = state; State a, b, goal;

} a = new State("A");

b = new State("B");

goal=new State("B");

public boolean equals(State s){ // it’s easier to simply overload


return state.equals(s.state); System.out.println(b.equals(goal));

} // true

// ...

13

Now, let’s focus on the cost issue…

Who should calculate the cost to move from one state to another??

◦ Should it be a method of State?

◦ Should it be a static method of State?

No! the cost calculation is domain specific!

◦ i.e., relevant to a specific problem and not a general solution

It should not be implemented in the State class

But rather the cost calculation in a domain-specific class

14

Specific states can be represented by the String variable

State s1=new State();

Domain independent s1.setState(“8 6547231”); “ 12345678”

State

String state

Specific states can be overloaded in an extended class

EightPuzzleState s1=new EightPuzzleState();

Domain independent int[][] state={{8,0,6},{5,4,7},{2,3,1}}”;

s1.setState(state);
State

String state

EightPuzzleState

int[][] state

Domain specific

Specific states can be instantiated from a generic State class

Domain independent

State<String> s1=new State<String>(“8 6547231”);


State<T>

public class State<T> {

T state;

public State(T state) {

this.state=state;

...
}

What do we expect from a search problem?

Best First Search:


OPEN = [initial state] // a priority queue of states to be evaluated

CLOSED = [] // a set of states already evaluated

while OPEN is not empty

do

1. n dequeue(OPEN) // Remove the best node from OPEN


2. add(n,CLOSED) // so we won’t check n again

3. If n is the goal state,

backtrace path to n (through recorded parents) and return path.

4. Create n's successors.

5. For each successor s do:


a. If s is not in CLOSED and s is not in OPEN:

i. update that we came to s from n

ii. add(s,OPEN)

b. Otherwise, if this new path is better than previous one

i. If it is not in OPEN add it to OPEN.


ii. Otherwise, adjust its priority in OPEN

done

18

What do we need from the search domain?

To give us the start state and the goal state

Given a state, what are the possible states we can get to?

◦ This is actually a part of the graph…

public interface Searchable {

State getInitialState(); getAllPossibleStates of

boolean isGoalState(State s); State “8 6547231” Returns:


List<State> getAllPossibleStates(State s);

} “ 86547231”

“8465 7231”

EightPuzzle “86 547231”






































‬ ‫בית הספר למדעי המחשב‬


‫מרצה‪ :‬ד"ר אליהו חלסצ'י‬



‬ ‫‪20‬‬

Best First Search:

OPEN = [initial state]


CLOSED = []
// a priority queue of states to be evaluated
// a set of states already evaluated

while OPEN is not empty


do

1. n dequeue(OPEN) // Remove the best node from OPEN


2. add(n,CLOSED) // so we won’t check n again

3. If n is the goal state,

backtrace path to n (through recorded parents) and return path.


4. Create n's successors.

5. For each successor s do:


a. If s is not in CLOSED and s is not in OPEN:

i. update that we came to s from n


ii. add(s,OPEN)

b. Otherwise, if this new path is better than previous one


i. If it is not in OPEN add it to OPEN.

done
ii. Otherwise, adjust its priority in OPEN

9.4 Design the Search Algorithm

DR. ELIAHU KHALASTCHI

What did we gain?

The algorithm just knows Searchable (and State)

It does not know any specific searchable domains (and states)

we can switch searchable domains independently from the algorithm!!!

Algorithm

<<Searchable>>

search(Searchable s)

alg.search(new MazeDomain());
alg.search(new WordDomain());

alg.search(new EightPuzzle ()); EightPuzzle MazeDomain WordDomain

We call this design dependency injection

What more do we need to think about?

The BFS is a type of “searcher”

We may want to implement other searching algorithms in the future as well

◦ E.g., beam search, A*, hill climbing, etc.

We want our system to work with any type of “searcher”

◦ I.e., we can replace the searching algorithm without changing the system’s code

For that we need to define an Interface!

public interface Searcher {

// the search method

public Solution search(Searchable s);

// get how many nodes were evaluated by the algorithm


public int getNumberOfNodesEvaluated();

23

The client only needs to know the interface

The “client” is another programmer, that may use the searching algorithms

public void testSearcher(Searcher searcher, Searchable ){

<<Searcher>>
Solution sol=searcher.search( );

int n = searcher.getNumberOfNodesEvaluated();
implements

// ...
}

BFS Astar HillClimbing

Examples:

tester.testSearcher(new BFS(), new EightPuzzle());


tester.testSreacher(new Astar(), new EightPuzzle());

tester.testSearcher(new HillClimbing(), new MazeDomain());

24

What all searchers have in common?

Let’s assume that all searching algorithms have a priority queue of states

<<Searcher>>
It will be wasteful to implement it over and over again with each algorithm…

We can use an abstract class! implements

BFS Astar HillClimbing

25

What all searchers have in common?

Let’s assume that all searching algorithms have a priority queue of states

<<Searcher>>
It will be wasteful to implement it over and over again with each algorithm…

We can use an abstract class! implements

public abstract class CommonSearcher implements Searcher { CommonSearcher

{abstract}
protected PriorityQueue<State> openList;

private int evaluatedNodes; extends

public CommonSearcher() {
openList=new PriorityQueue<State>();
BFS Astar HillClimbing

evaluatedNodes=0;
@Override
public abstract Solution search(Searchable s);

final protected State popOpenList() {


@Override
public int getNumberOfNodesEvaluated() {

evaluatedNodes++;
return evaluatedNodes;
return openList.poll();

}
}

26

BFS – best first search

Best First Search:

OPEN = [initial state] // a priority queue of states to be evaluated

CLOSED = [] // a set of states already evaluated


while OPEN is not empty

do

1. n dequeue(OPEN) // Remove the best node from OPEN

2. add(n,CLOSED) // so we won’t check n again

3. If n is the goal state,


backtrace path to n (through recorded parents) and return path.

4. Create n's successors.

5. For each successor s do:

a. If s is not in CLOSED and s is not in OPEN:

i. update that we came to s from n


ii. add(s,OPEN)

b. Otherwise, if this new path is better than previous one

i. If it is not in OPEN add it to OPEN.

ii. Otherwise, adjust its priority in OPEN

done

27

The BFS search algorithm

public Solution search(Searchable s) {

addToOpenList(s.getInitialState());

HashSet<State> closedSet=new HashSet<State>();

while(openList.size()>0){

State n=popOpenList();// dequeue

closedSet.add(n);

if(s.isGoalState(n))

return backTrace(n, s.getInitialState());


// private method, back traces through the parents

List<State> successors=s.getAllPossibleStates(n) //however it is implemented

for(State state : successors){

if(!closedSet.contains(state) && ! openListContains(state)){

state.setCameFrom(n);
addToOpenList(state);

} else{

//...

28

Summary

Think of the abstract problem representation

◦ e.g., shortest path in a graph

Find or create an algorithm that solves the abstract problem

◦ e.g., Best First Search

The required domain-specific information defines the functionality of problem type

◦ Put in an interface, e.g., Searchable

Define the solver’s interface, e.g., Searcher

◦ Make sure to receive the abstract problem type via dependency injection

Define in abstract classes the common code for algorithm implementations

Extend these abstract classes to define a specific code for a specific algorithm






































‬ ‫בית הספר למדעי המחשב‬


‫מרצה‪ :‬ד"ר אליהו חלסצ'י‬



‬ ‫‪1‬‬

10. UML

DR. ELIAHU KHALASTCHI

Classification of UML Diagrams

UML specification defines two major kinds of UML diagrams:

◦ Structure diagrams

◦ show the static structure of the system

◦ its parts on different abstraction and implementation levels

◦ how they are related to each other

◦ Behavior diagrams

◦ show the dynamic behavior of the objects in a system,

◦ which can be described as a series of changes to the system over time

Classification of UML Diagrams

UML 2.5

Structure Behavior

Class Diagram Use Case Diagram

Object Diagram Activity Diagram

Package Diagram State Machine Diagram

Composite Structure Diagram Interaction Diagram

Deployment Diagram Sequence Diagram Timing Diagram

Profile Diagram Communication Diagram Interaction Overview Diagram

Class Diagram

Class Diagram – a class

Class Name

Attributes

Operations

Class Diagram – a class

Singular

Uppercase Maze

Attributes

Operations

Class Diagram – a class

Maze

name

entry, exit

data

isSolved

Operations

Class Diagram – a class

Maze

name: String = “new maze”

entry, exit: Position

data: Integer[][]

isSolved: Boolean

Operations

Class Diagram – a class

Maze

name: String = “new maze”

entry, exit: Position

data: Integer[][]

isSolved: Boolean

getName

getEntrey
setSolved

possibleMoves

formatMazeData

toString

Class Diagram – a class

Maze

name: String = “new maze”

entry, exit: Position

data: Integer[][]

isSolved: Boolean

getName ()

getEntrey ()
setSolved (Boolean)

possibleMoves (Position)

formatMazeData ()

toString ()

Class Diagram – a class

Maze

name: String = “new maze”

entry, exit: Position

data: Integer[][]

isSolved: Boolean

getName (): String

getEntrey () : Position
setSolved (Boolean)

possibleMoves (Position) : Position[]

formatMazeData () : String

toString ()

Class Diagram – a class

Maze

- name: String = “new maze”

- entry, exit: Position

- data: Integer[][]

- isSolved: Boolean
+ Public

+ getName (): String


- Private + getEntrey () : Position

# Protected + setSolved (Boolean)

+ possibleMoves (Position) : Position[]

/ Derived
- formatMazeData () : String

~ Package + toString ()

Class Diagram – a class

Maze

- name: String = “new maze”

- entry, exit: Position

- data: Integer[][]

- isSolved: Boolean

+ getName (): String

+ getEntrey () : Position
+ setSolved (Boolean)

This is a note
+ possibleMoves (Position) : Position[]

- formatMazeData () : String

+ toString ()

Class Diagram – association

MazeGenerator

creates Maze

generate(): Maze

Class Diagram – association

Composition Association

Person

phones: Cellphone uses 0..*

Heart Cellphone
heart: Heart

Class Diagram – association

Person

phones: Cellphone 0..* 0..*

Cellphone
heart: Heart

Class Diagram – Composition vs. Aggregation

Composition

Aggregation

Class Diagram – Generalization

<<Searcher>>

search(): Solution

CommonSearcher

# closedList: List

# openList: List

Astar BFS

Object Diagram

Example

Class diagram:

1..*

bob : Engineer Employee

name = “Bob”

alice : Manager age = 31


Manager Engineer Architect

name = “Alice”

age = 35 dave : Manager

employees ={bob, dave} name = “Dave”

age = 34

employees={charlie}

charlie : Architect

name = “Charlie”

age = 25

Package Diagram

Package diagrams

Depicts the dependencies between the packages that make up a model

Simplify complex class diagrams

model

algorithms searchables maze generators

Searcher EightPuzzle SimpleMazeGenerator

Searchable Maze DFSMazeGenerator

Astar Snake …

BFS …

Composite Structure

Diagram

Composite Structure Diagram

Shows the internal structure of a class

and the collaborations that this structure makes possible

Aircraft

Wing[2]

Cockpit Aileron[2]

Engine Throttle Stick

Tail

Pedals
RPM gauge Elevator[2]

Propeller

Rudder

Deployment Diagram

Deployment Diagram

Models the physical deployment of artifacts on nodes

◦ Device Nodes

◦ Execution Environment Nodes






































‬ ‫בית הספר למדעי המחשב‬


‫מרצה‪ :‬ד"ר אליהו חלסצ'י‬



‬ ‫‪29‬‬

Classification of UML Diagrams

UML 2.5

Behavior

Use Case Diagram

Activity Diagram

State Machine Diagram

Interaction Diagram

Sequence Diagram Timing Diagram

Communication Diagram Interaction Overview Diagram

Activity Diagram

Graphical representations of workflows

◦ of stepwise activities and actions

◦ with support for choice, iteration and concurrency

Activity Diagram Example

Client Maze Generation Service

Request a maze Receive request

Invalid request
3D

2D

Maze 2D

generation Maze 2D Maze 2D Maze 2D


generation generation generation

Receive maze Return maze

Connect 2D
layers

State Machine Diagram

Describes state transitions

Can describe many systems, from computer programs to business processes

State Machine Maze Generation Service:

Idle
generate(…)
In progress Complete

exit() pause()

resume() cancel()

Done Suspended

Canceled
cancel()

Sequence Diagrams

Assume the following use case

Purchase Items

Customer

Title: Purchase Items

Actor: Customer

Scenario:

1. Customer checkouts a shopping cart


2. System creates an order

3. System adds items from the shopping cart to the order

4. Shopping cart displays the total for each item

5. System calculates discount

6. System calculates the total sum for payment

7. Customer submits the payment

Title: Purchase Items

A Sequence Diagram Actor:


Scenario:
1.
Customer

Customer checkouts a shopping cart

2. System creates an order

3. System adds items from the shopping cart to the order


4. Shopping cart displays the total for each item

a Customer a Cart :ShoppingCart :Order


5. System calculates discount

checkout()
6. System calculates the total sum for payment

createNewOrder() 7. Customer submits the payment

Loop all items addItem(item, quantity)

itemTotal

calculateDisscount()

finalizeSale()

total
a Payment

submitPayment()
createPayment()

results

results
X

Timing Diagram

http://www.uml-diagrams.org/

Interaction Overview Diagram

http://www.altova.com/umodel/interaction-diagrams.html






































‬ ‫בית הספר למדעי המחשב‬


‫מרצה‪ :‬ד"ר אליהו חלסצ'י‬



‬ ‫‪1‬‬

Object Oriented Design Patterns

DR. ELIAHU KHALASTCHI

Introduction

o A design pattern is a general reusable solution

◦ to a commonly occurring problem

◦ within a given context in software design

o It is a description or template for how to solve different design problems

o Object-oriented design patterns

◦ typically show relationships and interactions between classes or objects

Introduction

oDesign patterns were learned from good and bad experience

◦ Similar design problems tend to have similar solutions

oDesign Patterns help to

◦ Reuse successful designs

◦ Separate things that change from things that do not change

◦ Maintain the code

◦ Achieve useful designs quickly

Introduction

oDesign Patterns are divided to four main groups:

oCreational Patterns

◦ deal with object creation mechanisms

oStructural Patterns

◦ realize relationships between entities

oBehavioral Patterns
◦ identify common communication patterns between objects

oConcurrency Patterns

◦ deal with the multi-threaded programming paradigm






































‬ ‫בית הספר למדעי המחשב‬


‫מרצה‪ :‬ד"ר אליהו חלסצ'י‬



‬ ‫‪6‬‬

Structural Design Patterns

DR. ELIAHU KHALASTCHI

Adapter Design Pattern

Strings database Stream

Files

‫תקשורת‬ Predicat

Problem: how to adapt a Sorter to a Task

<<Task>> Not good!


<<Sorter>> • A BubbleSorter is not a Task!

doTask()

implements
• It should stay a pure sorter…

• If each interface has 10 methods then


CommonSorter our class will have 20!

{abstract}

implements

BubbleSorter

void doTask(){ sort(workers); }

Builder Design pattern

obsorble

builder flyweight

mo

pl
um

Builder Builder Builder

me

mi


observable
proxy observable

proxy

Class Adapter Pattern

Class adapter
<<Task>> • The BubbleSorter stays a pure sorter…
<<Sorter>> doTask()
• BubbleSorterTask is a Task
implements • doTask calls the inherited sort method
CommonSorter
{abstract} new TaskManager().runInBackground(
new BubbleSorterTask());

• Our adapter works only for bubble sort


BubbleSorter • We should apply the same solution to each sorter…
implements

BubbleSorterTask void doTask(){ sort(workers); }


Object Adapter Pattern
Solution 3: object adapter
<<Task>>
doTask()

implements
mySorter
<<Sorter>> SorterTask void doTask(){ mySorter.sort(workers); }

implements

CommonSorter
{abstract}
• One adapter to every type of Sorter!
• Our solution is in a higher level
• So it applies to all lower levels!

BubbleSorter new TaskManager().runInBackground(


new SorterTask(
new BubbleSorter()));
‫בית הספר למדעי המחשב‬
‫מרצה‪ :‬ד"ר אליהו חלסצ'י‬

‫‪14‬‬
Bridge Design Pattern
DR. ELIAHU KHALASTCHI
Problem:
Abstraction: House

implementations: StrawHouse WoodHouse BrickHouse

Abstraction: BigHouse

implementations: StrawBigHouse WoodBigHouse BrickBigHouse

How can we extend abstractions independently of extending implementations?


The Bridge Pattern
The Bridge Pattern

HouseImp
House paintDoor()
paint() paintWindow()
paintRoof()

BigHouse SmallHouse RoundHouse StrawImp WoodImp BrickImp


The Bridge Pattern - consequences
oWe can switch abstractions and implementations in runtime!

oWe are encouraged to use layers of code


◦ A higher layer only knows the abstraction and the implementer

oWe can extend the abstractions independently of implementations

oWe can extend the implementations independently of abstractions

oImplementation is hidden from the client


‫בית הספר למדעי המחשב‬
‫מרצה‪ :‬ד"ר אליהו חלסצ'י‬

‫‪20‬‬
Composite Design Pattern
DR. ELIAHU KHALASTCHI
The Composite Design Pattern
oCreates a “Tree”

oSimple to create a recursive hierarchy

oComposite and Leaf are


◦ Interchangeable to the client
◦ Easy to be added
The Composite Design Pattern
Example
Class diagram:
bob : Engineer
1..*
name = “Bob” Employee
alice : Manager age = 31
name = “Alice” Manager Engineer Architect
age = 35 dave : Manager
employees ={bob, dave} name = “Dave”
age = 34
employees={charlie}

charlie : Architect
name = “Charlie”
age = 25
‫בית הספר למדעי המחשב‬
‫מרצה‪ :‬ד"ר אליהו חלסצ'י‬

‫‪25‬‬
Decorator Design Pattern
DR. ELIAHU KHALASTCHI
Problem:
TextView

Text View With Text View With Text View With


Text View With
Scrollbars and a Scrollbars and a Scrollbars and a
Scrollbars
border Title border and a Title

2𝑁 classes for N options…


The Decorator Design Pattern
The Decorator Design Pattern
GUIItem
paint()
addListener(:Listener)
item

Canvas TextView ListView Decorator


paint() item.paint()

Scrollbars Title Border super.paint();


N classes for N options… paint() paint() paint()
paintOver() paintOver() paintOver() paintOver();

GUIItem g1=new Scrollbars(new Border(new TextView()));


GUIItem g2=new Scrollbars(new Border(new Title(new Canvas())));
g1.paint();
g2.paint();
The Decorator Design Pattern
o N classes instead of 2𝑁 classes
o We can add and mix decorations, even add the same decorations twice
o With inheritance you create all the options in advance,
o With Decorators you create just what you need (in runtime)

o A lot of small classes


o Easy to maintain to those who understand it, not to others…
Differences in Design Patterns so far…

1..* i
<<J>> i <<I>>

Adapter Composite Decorator


‫בית הספר למדעי המחשב‬
‫מרצה‪ :‬ד"ר אליהו חלסצ'י‬

‫‪32‬‬
Façade
DR. ELIAHU KHALASTCHI
The Façade Design Pattern
o A client can be separated from a layer of code with the use of a façade
o A client can command a layer of code to do something
oThe client does not have to know about particulars in the layer

Façade
<<layer’s interface>>

Data
Base
Low Coupling / High Cohesion
oCoupling: the level of dependencies between objects
oDecoupling: the process of reducing these dependencies
oCohesion: how focused is a class around a single responsibility
oWe want high cohesion & low coupling

Façade

Façade Façade

Low Cohesion, High Coupling High Cohesion, Low Coupling


‫בית הספר למדעי המחשב‬
‫מרצה‪ :‬ד"ר אליהו חלסצ'י‬

‫‪36‬‬
Flyweight Design Pattern
DR. ELIAHU KHALASTCHI
Problem:
o How can we minimize the number of objects?
s s s s
r v v Character
r t s a p
col, row : int
r s s
paint()
s s s s s s
s f
Tank
r s p p f
Robot
r s p p
Soldier

Airplane
A solution
oA state becomes a parameter
s s s s Character
o row, col parameters of paint() r v v
r t s a p paint(row,col)
r s s
o Each type appears as one object
s s s s s s Tank
s f
Robot
o A lot of references r s p p f
◦ instead of a lot of objects r s p p Soldier

Airplane

o Time over Space… r s p v a f


The Flyweight Pattern
‫בית הספר למדעי המחשב‬
‫מרצה‪ :‬ד"ר אליהו חלסצ'י‬

‫‪41‬‬
Proxy Design Pattern
DR. ELIAHU KHALASTCHI
Proxy Design Pattern
o Governs the access for the real subject
o Remote proxy
◦ Applies caching
o Virtual proxy
◦ Create “expensive” objects by demand
o Protection proxy
◦ Manages access
o Smart reference
◦ Count references
◦ Manage memory
◦ Etc.
Exercise
1. Why use a façade?
2. Which design pattern separates abstractions from implementations?
3. What are the advantages and drawbacks of Decorator?
4. Does Composite patterns allows the creation of a graph?
5. Which design pattern allows us to manage cache?
‫בית הספר למדעי המחשב‬
‫מרצה‪ :‬ד"ר אליהו חלסצ'י‬

‫‪45‬‬
Creational Patterns
DR. ELIAHU KHALASTCHI
Factory Design Pattern
Factory Pattern – the problem
o The Application class knows when it is required to create a Document
o It does not know which type of Document should be created
Factory Pattern – the solution
o A concrete Application class creates a concrete Document
◦ MSword creates a wordDocument
◦ MSexcel creates an excelDocument
◦ …
Factory Pattern – the solution
o Generally:
Factory Design Pattern
<<Creator>> Product
Product create()

ProductACreator ProductA
Product create()

ProductBCreator ProductB
Product create()

ProductCCreator ProductC
Product create()
Quiz…
o Let’s say we have n types of workers Worker

o And when the user inputs the type,


the right object needs to be instanced
Lecturer

o Creating n “if” statements takes O(n) time


TA
o It is also not very object oriented…

o Utilize the factory pattern and a container Admin


to return the new worker in O(1)
public class WorkerFactory {
private interface Creator{
public Worker create();

Factory Pattern }
private class AdminCreator implements Creator{
public Worker create() {
o First, we implement the interface and
return new Admin();
the classes inside the factory:
}
}
private class TACreator implements Creator{
public Worker create() {
return new TA();
o For each type of Worker, we create
}
a Creator class
}
private class LecturerCreator implements Creator{
public Worker create() {
return new Lecturer();
}
}
...
Factory Pattern
HashMap<String,Creator> workersCreators;
oNext, we create a HashMap!
public WorkerFactory() {
oString Creator
workersCreators=new HashMap<String, Creator>();
oThe key is exactly the user’s parameter workersCreators.put("admin", new AdminCreator());
workersCreators.put("ta", new TACreator());
oThe value is a creator workersCreators.put("lecturer",new LecturerCreator());

oWe instantiate each class once, O(n) mem’ // notice, takes O(n) memory
}

oNotice how createWorker takes O(1)


to return a new instance of Worker
of the given type!

}
Factory Pattern HashMap<String,Creator> workersCreators;

public WorkerFactory() {
oNext, we create a HashMap! workersCreators=new HashMap<String, Creator>();

oString Creator workersCreators.put("admin", ()->new Admin());


workersCreators.put("ta", ()->new TA());
oThe key is exactly the user’s parameter workersCreators.put("lecturer",()->new Lecturer());
// notice, takes O(n) memory
oThe value is a creator
}

oWe instantiate each class once, O(n) mem’


public Worker createWorker(String type){
Creator c=workersCreators.get(type);
// takes O(1) time!
oNotice how createWorker takes O(1) if(c!=null) return c.create();
to return a new instance of Worker return null;
of the given type! }
}
Factory Pattern HashMap<String, Creator>
Admin
“admin”
o Usage example: creator
TA
“ta”
WorkerFactory fac=new WorkerFactory(); creator
String userInput; Lecturer
//...
“lecturer”
enter types of workers: creator
Worker w=fac.createWorker(userInput); admin

if(w!=null) class Admin was created!


ta public Worker createWorker(String type){
System.out.println(w.getClass()+" was created!");
class TA was created! Creator c=workersCreators.get(type);
else // takes O(1) time!
ceo
System.out.println("wrong type of worker!"); wrong type of worker!
if(c!=null) return c.create();

} return null;
exit
}
‫בית הספר למדעי המחשב‬
‫מרצה‪ :‬ד"ר אליהו חלסצ'י‬

‫‪57‬‬
Abstract Factory Design Pattern
DR. ELIAHU KHALASTCHI
Abstract Factory Pattern
o Provides a way to encapsulate a group of individual factories
o that have a common theme
o without specifying their concrete classes
Abstract Factory Pattern - Example
oThe star wars armory and plain armory are interchangeable
oEach can return a sword and a shield
◦ The star wars armory returns a light saber and a deflector shield
◦ The plain armory returns a plain sword and a plain shield

<<Armory>> Sword
+ createSword() : Sword
+ createShield() : Shield PlainSword Lightsaber

StarWarsArmory PlainArmory Shield


+ createSword() : Sword + createSword() : Sword
+ createShield() : Shield + createShield() : Shield PlainShield Deflector
Abstract Factory Pattern – consequences
oThe client does not have to know bout concrete classes
◦ The clients knows an abstract armory, a sword, and a shield

oThe abstract factory allows to define “families” of related objects


oThese families are interchangeable, yet unmixed

Armory a = new StarWarsArmory(); // or new PlainArmory();


Sword sword = a.createSword();
Shield shield = a.createShield();
‫בית הספר למדעי המחשב‬
‫מרצה‪ :‬ד"ר אליהו חלסצ'י‬

‫‪62‬‬
Prototype Design Pattern
DR. ELIAHU KHALASTCHI
Prototype Pattern – the problem
oWhat do you add?

class ShapesHolder{
ArrayList<Shape> list;
public void addAcopy(Shape s){
list.add(new ???);
}
}
Prototype Pattern
o Each concrete class implements its own close() method

class ShapesHolder{
ArrayList<Shape> list;
public void addAcopy(Shape s){
list.add(s.clone());
}
}
Prototype Pattern – consequences
o Advantages
◦ Independence of concrete types
◦ Quick – we do not have to query the type

o Disadvantages
◦ clone() cannot have (many) parameters
◦ Setters have to be used after the cloning
◦ Shallow vs. deep copy
‫בית הספר למדעי המחשב‬
‫מרצה‪ :‬ד"ר אליהו חלסצ'י‬

‫‪67‬‬
Builder Design Pattern
DR. ELIAHU KHALASTCHI
Builder Design Pattern
o The intent is to separate the construction of a complex object
o from its representation
o The same construction process can create different representations
Builder Design Pattern - problem
LevelDirector
+ construct()

for(int i=0;i<10;i++) Level


createPlatform(new Position(d[i].x,d[i].y),d[i].l);

createCharacter(new Position(d[0].x,d[0].y));
MarioLevel
Random r=new Random();
for(int i=0;i<100;i++)
createEnemy(new Position(r.nextInt(100), r.nextInt(100)));
AladdinLevel
Bad solution…
LevelDirector BossLevelDirector
# createPlatform(:Position,:Length) # createPlatform(:Position,:Length)
# createCharacter(:Position) # createCharacter(:Position)
# createEnemy(:Position) # createEnemy(:Position)
+ construct()
Level + construct()

MarioLevelDirector MarioLevel MarioBossLevelDirector

AladdinLevelDirector AladdinLevel AladdinBossLevelDirector


Bad solution…
for(int i=0;i<10;i++)
LevelDirector createPlatform(new Position(d[i].x,d[i].y),d[i].l);

+ createPlatform(:Position,:Length) createCharacter(new Position(d[0].x,d[0].y));


+ createCharacter(:Position)
Random r=new Random();
+ createEnemy(:Position) for(int i=0;i<100;i++)
+ getLevel() : Level createEnemy(new Position(r.nextInt(100), r.nextInt(100)));
+ construct()

NoviceLevelDirector ExpertLevelDirector MasterLevelDirector BossLevelDirector Level

MarioNoviceLevel MarioExpertLevel MarioMasterLevel MarioBossLevel MarioLevel

AladdinNoviceLevel AladdinExpertLevel AladdinMasterLevel AladdinBossLevel AladdinLevel


Builder Design Pattern - problem
LevelDirector
+ construct()

for(int i=0;i<10;i++) Level


createPlatform(new Position(d[i].x,d[i].y),d[i].l);

createCharacter(new Position(d[0].x,d[0].y));
MarioLevel
Random r=new Random();
for(int i=0;i<100;i++)
createEnemy(new Position(r.nextInt(100), r.nextInt(100)));
AladdinLevel
Builder Design Pattern - Solution
LevelDirector <<LevelBuilder>>
+ construct(builder :LevelBuilder) + createPlatform(:Position,:Length)
+ createCharacter(:Position)
+ createEnemy(:Position)
for(int i=0;i<10;i++) Level + getLevel() : Level
builder.createPlatform(new Position(d[i].x,d[i].y),d[i].l);

builder.createCharacter(new Position(d[0].x,d[0].y));
MarioLevel MarioLevelBuilder
Random r=new Random();
for(int i=0;i<100;i++)
builder.createEnemy(new Position(r.nextInt(100), r.nextInt(100)));
AladdinLevel AladdinLevelBuilder
Level level = builder.getLevel();
Builder Design Pattern - Extended
<<LevelDirector>> <<LevelBuilder>>
+ construct(builder :LevelBuilder) + createPlatform(:Position,:Length)
+ createCharacter(:Position)
+ createEnemy(:Position)
Level + getLevel() : Level
NoviceLevelDirector

MarioLevel MarioLevelBuilder
ExpertLevelDirector
AladdinLevel AladdinLevelBuilder
MasterLevelDirector

BossLevelDirector
Singleton Design Pattern
Exercise…
1. What is the difference between Builder, Factory, and Abstract Factory?
2. Think of 2 ways to avoid creating N classes in Factory.
3. Create an activity diagram for the Singleton Object.
4. How Builder is connected to immutable classes? Fluent programming?
1. Code example
‫בית הספר למדעי המחשב‬
‫מרצה‪ :‬ד"ר אליהו חלסצ'י‬

‫‪78‬‬
Builder Pattern Example
DR. ELIAHU KHALASTCHI
Builder Pattern with IOC - Example
// Java example
public class Robot {
// inside Robot class
public static class RobotBuilder{
final String name; // required
final String name;
final int id; // required
final int id;
final double mass;
double mass;
final boolean flyable;
boolean flyable;
final boolean autonomous;
boolean autonomous;
private Robot(RobotBuilder rb){
public RobotBuilder(String name, int id) {
name=rb.name;
this.name=name;
id=rb.id;
this.id=id;
mass=rb.mass;
}
flyable=rb.flyable;
autonomous=rb.autonomous;
}

80
Builder Pattern with IOC - Example
// inside Robot class
public static class RobotBuilder{
final String name;
final int id;
double mass;
boolean flyable;
boolean autonomous;

public RobotBuilder(String name, int id) {


this.name=name;
this.id=id;
}

81
Builder Pattern with IOC - Example
public RobotBuilder setMass(double mass){
// inside Robot class this.mass=mass;
public static class RobotBuilder{ return this;
final String name; }
final int id; public RobotBuilder setFlyable(boolean flyable){
double mass; this.flyable=flyable;
boolean flyable; return this;
boolean autonomous; }
public RobotBuilder setAutonmous(boolean automous){
public RobotBuilder(String name, int id) { this.autonomous=automous;
this.name=name; return this;
this.id=id; }
}
public Robot build(){
return new Robot(this);
}

82
Builder Pattern with IOC - Example

public static void main(String[] args) {


Robot r1=new Robot.RobotBuilder("RR1",1).build();
Robot r2=new Robot.RobotBuilder("RR2",2).setAutonmous(true).build();
Robot r3=new Robot.RobotBuilder("RR3",3).setMass(54.5).setFlyable(true).build();
}

83
‫בית הספר למדעי המחשב‬
‫מרצה‪ :‬ד"ר אליהו חלסצ'י‬

‫‪84‬‬
Behavioral Patterns
DR. ELIAHU KHALASTCHI
Command Pattern
Command Pattern
oEvery request is served in a command object
oCommands can inherit other commands
oCommand objects can be put into a queue, manage a log, support “undo” etc.
Invoker
oExample:

document
Receiver
Specific Command

Other invokers can invoke the same specific command; the command code appears only once
Command Pattern
oEvery request is served in a command object
oCommands can inherit other commands
oCommand objects can be put into a queue, manage a log, support “undo” etc.
oExample: Composite structure!
Command Pattern
Example of a general Controller mechanism
oThe Controller is a singleton and an observer
oUpon an update, a key is used to retrieve or create the Command object
oExisting Command objects are stored in a hash table (flyweight pattern)
oNew Command objects are created by a Command-Pool (builder pattern)
oThe Command object is inserted to a priority queue
oA different thread polls commands from the queue, if it is not empty
◦ And execute each Command in a different thread via a Thread Pool
‫בית הספר למדעי המחשב‬
‫מרצה‪ :‬ד"ר אליהו חלסצ'י‬

‫‪91‬‬
Interpreter Pattern
DR. ELIAHU KHALASTCHI
Interpreter Pattern
oComposite structure
oThe behavior of interpret() is changed
oCan define a grammar
Interpreter Pattern Example
11*a+5-b/3
-

+ /

AbstractTreeNode
AbstractTreeNode
* 5 b 3

11 a
‫בית הספר למדעי המחשב‬
‫מרצה‪ :‬ד"ר אליהו חלסצ'י‬

‫‪95‬‬
Iterator Pattern
DR. ELIAHU KHALASTCHI
Iterator Pattern
oEnables access to items of a complex object
owithout exposing its inner structure
oEach container should return its own type of iterator

oShould consider:
◦ Who defines the iteration alg’?
◦ How robust is the iterator?
◦ E.g., when deleting items
Iterator Pattern Example
‫בית הספר למדעי המחשב‬
‫מרצה‪ :‬ד"ר אליהו חלסצ'י‬

‫‪99‬‬
Observer Pattern
DR. ELIAHU KHALASTCHI
Observer Pattern
C++ Example

102
Observer & Observable
class Observable; class Observable{
class Observer{ list<Observer*> observers;
public: public:
virtual void update(Observable& o) = 0; void addObserver(Observer& o){
}; observers.push_back(&o);
}
void notify(){
list<Observer*>::iterator it = observers.begin();
while (it != observers.end()){
(*it)->update(*this);
it++;
}
}
};

103
Usage:
class A : public Observable{ class B :public Observer{
int x; // our observable data A* a;
public: public:
void set(int x){ B(A* a){
this->x = x; this->a = a;
notify(); a->addObserver(*this);
} }
int get(){ return x; } void update(Observable& o){
}; int x = a->get();
cout << "b is updated" << endl;
int main(){ }
A a; };
B b(&a);
a.set(5);// b is updated
return 0;
}

104
C# Example
OBSERVER PAT TERN
Delegate variable vs. Event variable
o public void f(){…};
o public void g(){…};
o public delegate void myFunc();

myFunc x; event myFunc x;


x=f; x+=f;
x(); // activate f() x+=g;
x=g; x(); // activate f() and g()
x(); // activate g() x-=f;
x(); // activate only g()
106
Observer Pattern - delegates & events in C#
o The Observable defines an event variable of some known delegate type
o The Observer registers its own delegates to the observable
o The observable activates all the registered delegates whenever it is needed

Observable theObservable
public void delegate update(Object sender, EventArgs args); Observer
public event update notify;

theObservable.notify +=
// when it is needed to notify all observers delegate(Object sender, EventArgs e){
notify(this, theEventArgs); // do something about the notification
}
An Alarm Clock Example
class AlarmClock {
public Boolean stop;

public delegate void whatToDo(String time);


public event whatToDo customEvent;

public void start() {


new Thread(
delegate() {
while (!stop) {
String time = DateTime.Now.ToString("HH:mm:ss tt");

customEvent(time);

Thread.Sleep(1000);
}
}
).Start();
}
}

108
An Alarm Clock Example
o Now we can use the event’s += operator to assign as many delegates as we wish
o The -= operator removes delegates from the event
static void Main(string[] args) {
AlarmClock ac = new AlarmClock();

ac.customEvent += delegate(String time) {


if (time.Equals("18:10:00 PM")) {
Console.WriteLine("hello world!");
} We have added
}; 2 event handlers
ac.customEvent += delegate(String time) {
Console.WriteLine(time);
};

ac.start();
Thread.Sleep(3*60*1000);
ac.stop = true;
Console.ReadKey();
}

109
‫בית הספר למדעי המחשב‬
‫מרצה‪ :‬ד"ר אליהו חלסצ'י‬

‫‪110‬‬
State Pattern
DR. ELIAHU KHALASTCHI
State Pattern
oThe object changes its behavior when its state is changed
oAll of the sate related behaviors are bound to the same class
oEasy to add new behaviors and maintain existing ones

oStates can become flyweights


◦ Sharing actions instead of data
State Example

Health
+ move()

Healthy Faulty
+ move() + move()
‫בית הספר למדעי המחשב‬
‫מרצה‪ :‬ד"ר אליהו חלסצ'י‬

‫‪114‬‬
Template Vs. Strategy
DR. ELIAHU KHALASTCHI
Template Method
Change the behavior of a (template) method by calling abstract methods

sort(…)
compare(…): int

What are the down sides of this design pattern?


Strategy Pattern

compare(t1:T,t2:T): int

T=Worker

You might also like