GPT 4 tentafrågor - Dependency injection & strategy pattern Flashcards

1
Q

Vad är huvudsyftet med Dependency Injection i mjukvarudesign?

a) Att öka prestanda under runtime.
b) Att tillåta objekt att skapa sina egna beroenden.
c) Att separera objekts skapande från deras användning, öka underhållbarheten och flexibiliteten.

A

Rätt svar: c

Förklaring: Genom att “injicera” beroenden istället för att “konstruera” dem i klasser, separerar Dependency Injection objekts skapande från deras användning. Detta ökar underhållbarheten och flexibiliteten i kodbasen, vilket gör det lättare att ändra beroenden utan att modifiera klasserna själva.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
2
Q

Hur skulle du använda Dependency Injection i kontexten av en spelkaraktär som kan utföra olika typer av hopp?

a) Skapa en Player-klass som själv beslutar vilket hoppbeteende som ska användas.
b) Använda en IJumpBehavior-interface och injicera konkreta beteenden i Player-klassen vid behov.
c) Låta spelet globalt bestämma vilket hoppbeteende alla spelare ska ha.

A

Rätt svar: b

Förklaring: Genom att använda ett IJumpBehavior-interface kan olika hoppbeteenden implementeras som separata klasser. Dessa beteenden kan sedan injiceras i Player-klassen, vilket gör det möjligt att enkelt byta hoppbeteende under spelets gång.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
3
Q

Vilken typ av Dependency Injection används i exemplet där en Player-klass tar emot ett IJumpBehavior-objekt genom sin konstruktor?

a) Constructor Injection
b) Method Injection
c) Property Injection

A

Rätt svar: a

Förklaring: Constructor Injection innebär att beroenden levereras via klassens konstruktor. Detta är lämpligt när ett beroende är obligatoriskt för klassens funktion, som i fallet med IJumpBehavior i Player-klassen.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
4
Q

Vilket påstående är sant om Dependency Injection?

a) Det minskar kodens flexibilitet eftersom det lägger till fler beroenden.
b) Det är endast användbart när objekt har många beroenden.
c) Det underlättar ändringar i beteende vid runtime genom att tillåta att beroenden kan bytas ut.

A

Rätt svar: c

Förklaring: Ett av de primära syftena med Dependency Injection är att öka kodens flexibilitet och underhållbarhet. Genom att injicera beroenden, som kan bytas ut vid behov, kan systemets beteende enkelt ändras vid runtime.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
5
Q

Betrakta följande kodsegment. Vilket är det bästa sättet att tillämpa Dependency Injection här?

class Player
{
    public void Jump()
    {
        // Antag att det här är standardhoppbeteendet.
        Console.WriteLine("Performing regular jump.");
    }
}

a) Ändra Jump-metoden i Player-klassen varje gång ett nytt hoppbeteende introduceras.

b) Skapa ett IJumpBehavior-interface och låt Player-klassen hålla en referens till ett IJumpBehavior-objekt som bestämmer hur man hoppar.

c) Låta en global inställning bestämma vilket hoppbeteende som ska användas i Jump-metoden.

A

Rätt svar: b

Förklaring: Att ha ett IJumpBehavior-interface tillåter Player-klassen att delegera hoppbeteendet till det objekt som implementerar interfacet. Detta separerar hopplogiken från Player-klassen och gör det enkelt att införa nya hoppbeteenden utan att ändra Player-klassen.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
6
Q

Which statement is correct regarding the Strategy pattern?

  1. The Strategy pattern requires using inheritance to switch behaviors at runtime.
  2. In the Strategy pattern, it’s impossible to add new strategies without modifying existing classes.
  3. The Strategy pattern encapsulates specific behaviors or algorithms into separate classes, making them interchangeable.
A

The correct answer is option 3: “The Strategy pattern encapsulates specific behaviors or algorithms into separate classes, making them interchangeable.”

The Strategy pattern is all about enabling an object, often known as the context, to vary its behavior based on its strategy object. Strategies are a set of algorithms that can be swapped at runtime as per the needs. The encapsulation of these algorithms (as individual strategies) avoids code duplication and promotes a high degree of cohesion and low coupling. The other options are incorrect because the Strategy pattern doesn’t rely on inheritance for swapping behaviors and is designed specifically to avoid having to modify existing code to add new behaviors.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
7
Q

In the context of the Strategy pattern, which class or interface is responsible for defining a family of algorithms?

  1. ConcreteStrategy classes
  2. Context class
  3. IStrategy interface (or similarly named interface)
A

The correct answer is option 3: “IStrategy interface (or similarly named interface).”

In the Strategy pattern, the “IStrategy” interface defines a common platform for all concrete strategies, ensuring each strategy conforms to a specific blueprint (i.e., having certain methods that need to be implemented). The “Context” class maintains a reference to a strategy object, which represents an interface common to all supported algorithms. ConcreteStrategy classes are merely the implementations of these algorithms. The interface is central because it makes the Context class and the concrete strategies loosely coupled.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
8
Q

Consider the following code snippet:

public class Character
{
    private IWeaponBehavior weapon;

    public Character(IWeaponBehavior weapon)
        => this.weapon = weapon;

    public void Attack()
        => weapon.UseWeapon();
}

Which principle is demonstrated in the code above?

  1. Inheritance over composition
  2. Composition over inheritance
  3. Static binding over dynamic binding
A

The correct answer is option 2: “Composition over inheritance.”

The provided code snippet demonstrates the “Composition over inheritance” principle. This principle suggests that a class should achieve polymorphic behavior and code reuse by containing instances of other classes that implement the desired functionality, rather than inheriting from a base or parent class. In this example, the Character class doesn’t inherit methods from the IWeaponBehavior classes. Instead, it has a weapon (IWeaponBehavior) property, allowing it to delegate the Attack method’s behavior to the encapsulated “weapon” object, leading to more flexibility and the possibility to change behaviors at runtime.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
9
Q

In the sample code where different weapons implement IWeaponBehavior, how does this design allow for flexibility?

  1. By allowing the Character class to directly instantiate each weapon it needs.
  2. By using a common interface, enabling the Character class to interact with different weapon strategies dynamically.
  3. By limiting each Character to a single type of weapon to avoid complexity.
A

The correct answer is option 2: “By using a common interface, enabling the Character class to interact with different weapon strategies dynamically.”

The design is flexible because the IWeaponBehavior interface allows the Character object to switch its weapon (strategy) at runtime, as it doesn’t instantiate weapon objects directly. This approach means that if we introduce new weapons (concrete strategies), the Character class doesn’t need to change. The Character can use any weapon (strategy) as long as the weapon adheres to the IWeaponBehavior interface, highlighting the interoperability and flexibility provided by using a common interface. The Character’s behavior with regards to its weapon can change dynamically because it’s based on the object’s composition (which weapon it’s composed with) rather than the class inheritance hierarchy.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
10
Q

Vad är sant om Strategy-mönstret?
1. En konkret strategi-klass kan ändra sitt beteende vid körtid.
2. Strategi-gränssnittet kan ändra beteende vid körtid.
3. Klassen som använder en strategi får ett beteende som beror på den valda
strategin.

A

Rätt svar: 3. Klassen som använder en strategi får ett beteende som beror på den valda strategin.

Förklaring:
Strategy pattern handlar om att en klass (ofta kallad “context”) delegerar sitt beteende till en annan klass som representerar en specifik strategi. Denna strategi kan ändras vid körtid, vilket innebär att klassen som använder strategin (context) kan ändra sitt beteende dynamiskt beroende på vilken strategi som väljs. Detta mönster ökar flexibiliteten och underlättar underhåll genom att separera beteenden och göra dem utbytbara. De andra alternativen är inte korrekta eftersom de inte korrekt beskriver hur Strategy-mönstret fungerar.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
11
Q
Dancer dancer = new Dancer { Style = new Breakdance() };
interface IDanceStyle { string Dance(); }
interface IDancer { string Dance(); }
class Breakdance : IDanceStyle {
}
public string Dance() => "Breakdancing!";
class Dancer : IDancer {
    public IDanceStyle Style { get; set; }
}
public string Dance() => Style.Dance();

Ovan är ett exempel på Strategy pattern. Vilket gränssnitt används för strategier?

  1. IDancer
  2. Style
  3. IDanceStyle
A

Fråga 2:
Rätt svar: 3. IDanceStyle

Förklaring:
I Strategy pattern representerar gränssnittet (i det här fallet “IDanceStyle”) en familj av möjliga strategier eller beteenden. Konkreta strategier (som “Breakdance” i detta exempel) implementerar detta gränssnitt. “IDanceStyle” används för att definiera ett beteende som kan ändras dynamiskt av “Dancer” klassen vid körtid. “IDancer” är inte rätt svar eftersom det är ett gränssnitt som definierar beteendet för dansaren, inte strategierna de använder.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
12
Q

Vad blir output för följande kod?

Bird b1 = new Bird(new FlyWithWings());
Bird b2 = new Bird(new FlyWithRockets());
Console.WriteLine(b2.Fly());
    string Fly();
class FlyWithWings : IFlyBehavior {
interface IFlyBehavior {
} }
    public string Fly() => "Flying with wings!";
class FlyWithRockets : IFlyBehavior {
public string Fly() => "Flying with rockets!";
}
class Bird {
    private IFlyBehavior behavior;
    public Bird(IFlyBehavior b) => behavior = b;
    public string Fly() => behavior.Fly();
}

A

Rätt svar: Output är: “Flying with rockets!”

Förklaring:
I exemplet skapas två “Bird” objekt med olika flygbeteenden: “FlyWithWings” och “FlyWithRockets”. När Console.WriteLine(b2.Fly()); körs, anropar den “Fly” metoden på “b2” objektet, vilket har beteendet från “FlyWithRockets” klassen. Metoden returnerar strängen “Flying with rockets!” vilket är det beteende som definierats i “FlyWithRockets” klassen.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
13
Q

```

Console.WriteLine(newCar(newDriveFast()).Drive());
public interfaceIDriveBehavior{ string Drive(); }
public class DriveFast : IDriveBehavior {
public string Drive() => “Driving fast!”;

}

public class Car {
private IDriveBehavior behavior;
public Car(IDriveBehavior b) => behavior = b;
public string Drive() => BLANK;
}

```

Output: Driving fast!

Vad ska ersätta BLANK ?
1. new DriveFast()
2. behavior.Drive()
3. this.Drive()

A

Rätt svar: 2. behavior.Drive()

Förklaring:
I koden ovan har “Car” klassen en medlem variabel “behavior” av typen “IDriveBehavior”, vilket representerar ett körbeteende. Rätt sätt att initiera en operation på denna medlem variabel är genom att anropa metoden som definieras i gränssnittet, vilket är “Drive()”. Därför ska “behavior.Drive()” användas för att anropa det faktiska körbeteendet hos det beteende som “Car” objektet håller. Alternativ 1 är felaktigt eftersom det skapar en ny instans av “DriveFast” vilket inte är vad som krävs här. Alternativ 3 är också felaktigt eftersom “this.Drive()” skulle referera till en metod inom samma klass, vilket inte är fallet här.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
14
Q

Vad är huvudsyftet med dependency injection?

  1. Att direkt koppla ett objekts beroenden.
    2.Att invertera kontrollen av hur beroenden hanteras, där en klass mottar sina beroenden istället för att skapa dem.
  2. Att öka komplexiteten i kodbasen för bättre säkerhetspraxis.
A

Alternativ 1: Att tillåta att objekt får sina beroenden utan att skapa dem själva.

Förklaring: Detta är korrekt. Dependency injection handlar om att ge ett objekt dess nödvändiga beroenden utan att det behöver skapa dem, vilket främjar löskoppling och enklare kodhantering.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
15
Q

Hur relaterar principen om “separation of concerns” till dependency injection?

  1. Den har ingen direkt relation till dependency injection.
  2. Den möjliggör dependency injection genom att blanda flera beroenden.
  3. Den stödjer dependency injection genom att uppmuntra en klass att endast hantera en uppgift, där beroenden injiceras snarare än skapas inuti.
A

Option 3: It supports dependency injection by encouraging a class to handle only one task, with dependencies being injected rather than created internally.

Explanation: This is correct. SoC recommends that each class or module in a program should address only one part of the functionality. This concept goes hand in hand with dependency injection, which maintains that objects should not create their dependencies but rather have them supplied (injected). This way, each class focuses solely on its primary purpose, promoting cleaner, more readable, and maintainable code.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
16
Q

Titta på följande kodsegment. Vad är fel med denna kod gällande principer för bra objektorienterad design?

```

class Player
{
bool hasDoubleJumpPowerUp = false;

public void MoveRight()
=> Console.WriteLine("Moving right.");

public void Jump()
{
    if (!hasDoubleJumpPowerUp) 
        Console.WriteLine("Jumping");
    else 
        Console.WriteLine("Double jumping");
} }

```

  1. Koden bryter mot DRY-principen (Don’t Repeat Yourself) eftersom metoden Jump har upprepande kodsegment.
  2. Koden bryter mot principen om dependency injection genom att direkt instansiera och hantera beroendet inom klassen.
  3. Det finns inget fel; koden följer alla bästa praxis för objektorienterad design.
A

Alternativ 2: Player-klassen använder dependency injection för att tilldela ett hoppbeteende.

Förklaring: Detta är korrekt. Genom konstruktorn injiceras ett hoppbeteende (som implementerar IJumpBehavior-gränssnittet), vilket gör att olika hoppbeteenden kan tillämpas. Detta är ett typiskt användningsfall för dependency injection.

17
Q

Vilken av följande kodändringar illustrerar korrekt användning av dependency injection?

  1. Skapa nya instanser av beroenden inom varje metod där de behövs.
  2. Skicka beroenden till klassens konstruktor eller via setters (metodinjektion) som implementerar bestämda gränssnitt.
  3. Använd globala statiska objekt för att tillhandahålla beroenden till klasser.
A

Korrekt svar: 2. Skicka beroenden till klassens konstruktor eller via setters (metodinjektion) som implementerar bestämda gränssnitt.

Förklaring:
Dependency injection handlar om att ge ett objekt dess beroenden istället för att låta det skapa dem själv. Detta uppnås oftast genom att skicka beroenden till objektets konstruktor eller genom att använda setters som tillåter att beroenden sätts vid en senare tidpunkt. Detta ökar modulär design och gör kod lättare att återanvända, testa och underhålla, eftersom det minimerar hårdkodade beroenden och tillåter att beroenden enkelt kan bytas ut (till exempel med mock-objekt vid testning).

18
Q

Vad är fördelen med att använda komposition över arv i kontexten av exempel med olika typer av “Duck”?

  1. Det gör det möjligt att alla Duck-objekt kan endast simma och kvacka, vilket begränsar deras beteenden.
  2. Det låter Duck-objekt ärva beteenden från en enda överordnad klass, vilket förenklar kodbasen.
  3. Det ger flexibilitet att dynamiskt tilldela och ändra beteenden vid körning, och underlättar underhåll genom att minska duplicering av kod.
A

Korrekt svar: 3. Det ger flexibilitet att dynamiskt tilldela och ändra beteenden vid körning, och underlättar underhåll genom att minska duplicering av kod.

Förklaring: I programmeringsmodeller, särskilt de som använder “Duck”-exempel, handlar komposition över arv om att bygga objekt med hjälp av andra objekt, snarare än att ärva all funktionalitet från en föräldraklass. Detta betyder att du kan ändra ett objekts beteende vid körning genom att komponera det av andra objekt. Till exempel, om du har olika beteenden för ‘flygning’ eller ‘kvackande’, kan du dynamiskt tilldela ett visst beteende till en ‘Duck’ istället för att vara bunden av de beteenden som definierats i dess föräldraklass. Detta gör systemet mer flexibelt och underlättar återanvändning av kod och underhåll, eftersom beteenden är kapslade i sina egna klasser och lätt kan bytas ut eller modifieras utan att påverka andra.

19
Q

Vilken typ av dependency injection används i koden nedan?

// ...
public void SetJumpBehavior(IJumpBehavior behavior)
{
    jumpBehavior = behavior;
}
// ...
  1. Konstruktor-injektion
  2. Metod-injektion
  3. Egenskaps-injektion
A

Alternativ 2: Metod-injektion

Förklaring: Detta är korrekt. Eftersom beroendet (i detta fall IJumpBehavior) sätts via en metod (SetJumpBehavior), är detta ett exempel på metod-injektion.

20
Q
A