You are on page 1of 16

Cap.

PRINCIPII DE BAZA IN APLICAREA


SABLOANELOR DE PROIECTARE
1.Principii care stau la baza
aplicarii sabloanelor de proiectare
 Program to an interface not an implementation
 the application should always use interfaces from other part of the application rather
than the concrete implementations; in other words, the client code should hold an
interface object, not a concrete one.
 “always design based on a contract rather than an implementation”

 Benefits:

 the behavior of a program could be changed at a run-time


 Better quality of a program – maintainability, extensibility, testability

 Favor object composition over inheritance


 classes should achieve polymorphic behavior and code reuse by their composition (by
containing instances of other classes that implement the desired functionality) rather
than inheritance from a base or parent class.
 this principle gives the design higher flexibility. (wikipedia.org)
1.1 Program to an interface, not an implementation
Exemplul 1 public interface PersonStore {
Person find(String name);
}

class DatabasePersonStore implements PersonStore {


...
}

class CsvFilePersonStore implements PersonStore {


...
}

A consumer/client can use the interface without even knowing about the concrete
implementations.

PersonStore store = PersonStoreFactoy.getPersonStore();


Person person = store.find("Jon Doe");
...
You should use an interface whenever you have multiple implementations. For example
if you use a different persistence in production as in development or if you have an
algorithm which is interchangeable.
Sursa: https://tuhrig.de/programming-to-an-interface/
1.1 Program to an interface not an implementation
Exemplul 2
public enum Language
{ public class GermanSpeaker : ISpeaker
English, German, Spanish {
} public GermanSpeaker() { }

public void Speak()


public interface ISpeaker {
{ Console.WriteLine("I speak German.");
void Speak(); }
}
}

public class EnglishSpeaker : ISpeaker public class SpanishSpeaker : ISpeaker


{ {
public EnglishSpeaker() { } public SpanishSpeaker() { }
public void Speak() public void Speak()
{ {
Console.WriteLine("I speak English."); Console.WriteLine("I speak Spanish.");
} }
} }

Exemplu preluat de la https://stackoverflow.com/questions/2697783/what-does-program-to-interfaces-not-implementations-mean


1.1 Program to an interface, not an implementation
Exemplul 2
public class SpeakerFactory
{
public static ISpeaker CreateSpeaker(Language language)
{
switch (language)
{
case Language.English:
return new EnglishSpeaker();
case Language.German:
return new GermanSpeaker();
case Language.Spanish:
return new SpanishSpeaker();
default:
throw new ApplicationException("No speaker can speak such language");
} } }

class Program
{
static void Main()
{
//This is your client code.
ISpeaker speaker = SpeakerFactory.CreateSpeaker(Language.English);
speaker.Speak();
Console.ReadLine();
}
}
1.1 Program to an interface not an implementation
Exemplul 2
Let suppose we need to add a feature to all Speakers to "Say Hello“. All speakers speak
"Hello World“, except SpanishSpeaker which cannot Say Hello.
An abstract Speaker base class has been added. The Speaker abstract class implements
ISpeaker interface and marks the Speak() as abstract which means that each Speaker
implementation is responsible for implementing the Speak method since it varies from
Speaker to Speaker. But all speakers say "Hello" unanimously. So in the abstract
Speaker class we define a method that says "Hello World" and each Speaker
implementation will derive the SayHello method. The SayHello method for Spanish
Speaker is overriden.

Please note that, we have not made any changes to Interface ISpeaker. And the
client code and SpeakerFactory also remain unchanged. And this is what we achieve
by Programming to an Interface not an implementation.
1.1 Program to an interface not an implementation
Exemplul 2
public enum Language
{ class Program
English, German, Spanish {
} static void Main()
{ //This is your client code.
public class SpeakerFactory ISpeaker speaker = SpeakerFactory.
{ CreateSpeaker(Language.English);
public static Ispeaker CreateSpeaker ( speaker.Speak();
Language language) Console.ReadLine();
{ }
switch (language) }
{
case Language.English: public interface ISpeaker
return new EnglishSpeaker(); {
case Language.German: void Speak();
return new GermanSpeaker(); }
case Language.Spanish:
return new SpanishSpeaker();
default:
throw new
ApplicationException("No speaker can
speak such language");
}
}}
1.1 Program to an interface, not an implementation
Exemplul 2
public abstract class Speaker : Ispeaker public class GermanSpeaker : Speaker
{ {
public abstract void Speak(); public GermanSpeaker() { }
public virtual void SayHello() public override void Speak()
{ {
Console.WriteLine("Hello world."); Console.WriteLine("I speak German.");
} this.SayHello();
} }
}

public class EnglishSpeaker : Speaker public class SpanishSpeaker : Speaker


{ {
public EnglishSpeaker() { } public SpanishSpeaker() { }
public override void Speak() public override void Speak()
{ {
this.SayHello(); Console.WriteLine("I speak Spanish.");
Console.WriteLine("I speak English."); this.SayHello();
} }
} public override void SayHello()
{
throw new ApplicationException("I
cannot say Hello World.");
}
}
1.3 Favor composition over inheritance.
Reuse implementation
Inheritance: An Apple is-a Fruit Composition: An Apple has-a Fruit
class Fruit { class Fruit {
public void peel() { public void peel() {
System.out.println(“Peeling a fruit”); //…
} }
} }
class Apple extends Fruit { class Apple {
public void peel() { private Fruit fruit = new Fruit();
System.out.println(“Peeling an Apple”); public void peel() {
} fruit.peel();
} }
}

Note!
An implementation of composition over inheritance typically begins with the creation of
various interfaces representing the behaviors that the system must exhibit. The use of
interfaces allows this technique to support the polymorphic behavior that is so valuable
in object-oriented programming.
1.3 Favor composition over inheritance.
Comparasion

Benefits of composition
 Loosely coupled- any change to Fruit class does not affect to Apple class. Similarly
also adding any method with same signature as Fruit class does not make any affect,
and the code will compile perfectly.
 Stronger Encapsulation- in composition if we change the return type of peel() in
Fruit class, there is no need to change anything in Apple class. Without changing
anything also the code will compile perfectly and run as well.

Choosing between Composition and Inheritance:


 If the relation between super and subclass is a pure “is a” relationship then better to
use Inheritance.
 If the interface of super class and subclass needs to or will change through the life
cycle of application then better to use composition than Inheritance.
1.3 Favor composition over inheritance.
Exemplu
For example, take a set of classes DynamicDataSet and SnapShotDataSet that require a
common functionality—say, sorting.
//Sorting.java
import java.awt.List;
public class Sorting {
public List sort(List list) {
// sort implementation
return list;
}
}
class DynamicDataSet extends Sorting {
// DynamicDataSet implementation
}
class SnapshotDataSet extends Sorting {
// SnapshotDataSet implementation
}

A challenging issue: what if one DataSet class wants to use one sorting algorithm (say,
MergeSort) and another data set class wants to use a different sorting algorithm (say,
QuickSort)? Will you inherit from two classes implementing two different sorting
algorithms? NO!
1.3 Favor composition over inheritance.
Examplu
In this case it is best to use composition - in other words, use a HAS-A relationship
instead of an IS-A relationship.
//Sorting.java class DynamicDataSet {
import java.awt.List; Sorting sorting;
interface Sorting { public DynamicDataSet() {
List sort(List list); sorting = new MergeSort();
} }
class MergeSort implements Sorting { // DynamicDataSet implementation
public List sort(List list) { }
// sort implementation class SnapshotDataSet {
return list; Sorting sorting;
} public SnapshotDataSet() {
} sorting = new QuickSort();
class QuickSort implements Sorting { }
public List sort(List list) { // SnapshotDataSet implementation
// sort implementation }
return list;
}
}

Urmariti cu atentie utilizarea interfetei Sorting!!!


Sursa: https://dzone.com/articles/composition-vs-inheritance
1.Şabloane de proiectare. Definire

 Each pattern describes a problem that occurs over and over again in our
environment, and then describes the core of the solution to that problem,
in such a way that you can use the solution a million times over, without
ever doing it the same way twice.- GoF (Gang of Four) - Design Patterns: Elements of
Reusable Object-Oriented Software by Gamma, Helm, Johnson, and Vlissides, 1994)

 Soluţie generală reutilizabilă la o problemă care apare în mod repetat în


proiectarea OO a software-ului

 nu este un element de proiectare aflat într-o formă finală, direct


transformabilă în cod

 Este o descrierea abstractă a modului de rezolvare a unei probleme ce


poate fi utilizată în situaţii diverse

 Este o formalizare a celor mai bune practici în programarea OO pe care


programatorul trebuie să le implementeze singur in aplicaţii
2.Şabloane de proiectare. Definire
 Why use design pattern
 Well-Described Solutions
 Shared Vocabulary
 Concise Language
 Stay in Design Mode Longer
 Encourage Other Developers

 Avantajele aplicării:

 creşterea calităţii codului

 facilitarea comunicării si lucrului in echipă prin stabilirea unei terminologii

comune

 Motivaţia studierii lor de catre studenti

 o mai buna intelegere a conceptelor si principiilor de lucru specifice APOO


1.Şabloane de proiectare. Definire
 Patru elemente esenţiale

 Numele şablonului

 Problema – descrie când trebuie aplicat un şablon şi contextul de

aplicare

 Exemplu – instanţierea unui singur obiect de către o clasă

 Soluţia – o descriere abstractă a elementelor proiectării, a relaţiilor

dintre ele, a responsabilităţilor şi colaborărilor

 Consecinţele – descrierea compromisurilor, a costurilor şi avantajelor


aplicării şablonului

 Exemple de beneficii – extensibilitate, flexibilitate

 Exemple de costuri – sporirea complexităţii codului


2.Şabloane de proiectare. Clasificare

 şabloane creaţionale – vizeaza mecanismele pentru controlul

instantierii/crearii de obiecte

 Singleton, Factory method

 şabloane structurale – ofera solutii simple pentru realizarea relatiilor

dintre clase

 Adaptor, Composite, Façade, Proxy

 şabloane de comportament – vizeaza comunicarea dintre obiecte

 Observer, Strategy, Chain of Responsibility

You might also like