0% found this document useful (0 votes)
12 views13 pages

Abstract Factory Pattern Assignment

Uploaded by

Nazish Naseer049
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
Download as docx, pdf, or txt
0% found this document useful (0 votes)
12 views13 pages

Abstract Factory Pattern Assignment

Uploaded by

Nazish Naseer049
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
Download as docx, pdf, or txt
Download as docx, pdf, or txt
You are on page 1/ 13

Abstract Factory Pattern

Submitted by:
Nazish Naseer
CIIT/FA21-BSE-049/VEHARI

Subject:
Software Architecture

Submitted to:
Madam Komal Hassan
Abstract Factory Pattern
The Abstract Factory Pattern is a creational design pattern that provides an
interface for creating families of related or dependent objects without specifying their
concrete classes. It allows you to produce a set of related products (like different UI
components, vehicles, or shapes) while ensuring that the client code can work with these
products without needing to know the specific implementations.

The pattern works by defining an abstract factory interface that declares methods for creating
abstract products (like a button, checkbox, car, or bike). Then, concrete factories implement
this interface to create specific versions of the products. This is useful for creating objects
that are grouped together, such as all products for a specific operating system or brand.

For example, an abstract factory can create both Windows and Mac UI components,
ensuring that the application uses the correct set of components for a given platform.

Examples:

Automobile Car and Bike


Sample Code:

# Abstract Factory Interface: IAutomobileManufacture


class IAutomobileManufacture:
def getCar(self) -> 'ICar':
pass

def getBike(self) -> 'IBike':


pass

# Abstract Product Interfaces: ICar and IBike


class ICar:
def manufacture(self):
pass

class IBike:
def manufacture(self):
pass

# Concrete Products: Cars and Bikes


# Concrete Cars
class BajajCar(ICar):
def manufacture(self):
return "Bajaj Car is manufactured"

class MahindraQuanto(ICar):
def manufacture(self):
return "Mahindra Quanto is manufactured"

# Concrete Bikes
class Pulsar(IBike):
def manufacture(self):
return "Pulsar Bike is manufactured"

class MahindraScooty(IBike):
def manufacture(self):
return "Mahindra Scooty is manufactured"

# Concrete Factories: BajajMotors and MahindraMotors


# Bajaj Factory
class BajajMotors(IAutomobileManufacture):
def getCar(self) -> ICar:
return BajajCar()

def getBike(self) -> IBike:


return Pulsar()

# Mahindra Factory
class MahindraMotors(IAutomobileManufacture):
def getCar(self) -> ICar:
return MahindraQuanto()

def getBike(self) -> IBike:


return MahindraScooty()

# Client Code
def client(factory: IAutomobileManufacture):
car = factory.getCar()
bike = factory.getBike()

print(car.manufacture())
print(bike.manufacture())

# Example usage
bajaj_factory = BajajMotors()
mahindra_factory = MahindraMotors()

print("Bajaj Factory:")
client(bajaj_factory)

print("\nMahindra Factory:")
client(mahindra_factory)

Explanation of the Code:

 Abstract Factory Interface (IAutomobileManufacture):

 This interface defines two methods: getCar() and getBike().


 These methods return instances of ICar and IBike, respectively.

 Abstract Product Interfaces (ICar, IBike):

 These are abstract classes (or interfaces) for the products that factories produce: cars
and bikes.
 They declare the method manufacture() that will be implemented by the concrete
classes.

 Concrete Products:

 BajajCar and MahindraQuanto are concrete implementations of the ICar interface.


 Pulsar and MahindraScooty are concrete implementations of the IBike interface.

 Concrete Factories (BajajMotors, MahindraMotors):

 These factories implement the IAutomobileManufacture interface to create cars and


bikes specific to Bajaj and Mahindra.
 Each factory returns the appropriate car or bike based on its brand.

 Client Code:

 The client uses the factory to create cars and bikes without knowing the specific types
(concrete classes).
 The client() function interacts with the abstract factory interface, making it flexible
to work with different brands by simply switching the factory.

Output:

Bajaj Factory:
Bajaj Car is manufactured
Pulsar Bike is manufactured

Mahindra Factory:
Mahindra Quanto is manufactured
Mahindra Scooty is manufactured
operating systems (Windows and Mac)

Sample Code

from abc import ABC, abstractmethod

# Abstract Products: Button and Checkbox Interfaces


class Button(ABC):
@abstractmethod
def paint(self):
pass

class Checkbox(ABC):
@abstractmethod
def paint(self):
pass

# Concrete Products for Windows


class WinButton(Button):
def paint(self):
return "Rendering a Windows Button."
class WinCheckbox(Checkbox):
def paint(self):
return "Rendering a Windows Checkbox."

# Concrete Products for Mac


class MacButton(Button):
def paint(self):
return "Rendering a Mac Button."

class MacCheckbox(Checkbox):
def paint(self):
return "Rendering a Mac Checkbox."

# Abstract Factory Interface


class GUIFactory(ABC):
@abstractmethod
def createButton(self) -> Button:
pass

@abstractmethod
def createCheckbox(self) -> Checkbox:
pass

# Concrete Factory for Windows


class WinFactory(GUIFactory):
def createButton(self) -> Button:
return WinButton()

def createCheckbox(self) -> Checkbox:


return WinCheckbox()

# Concrete Factory for Mac


class MacFactory(GUIFactory):
def createButton(self) -> Button:
return MacButton()

def createCheckbox(self) -> Checkbox:


return MacCheckbox()

# Client: Application Class


class Application:
def __init__(self, factory: GUIFactory):
self.factory = factory
self.button = None
self.checkbox = None

def createUI(self):
self.button = self.factory.createButton()
self.checkbox = self.factory.createCheckbox()

def paint(self):
print(self.button.paint())
print(self.checkbox.paint())

# Example Usage
def configure_application(os_type: str):
if os_type == "Windows":
factory = WinFactory()
elif os_type == "Mac":
factory = MacFactory()
else:
raise ValueError("Unknown operating system.")

app = Application(factory)
app.createUI()
app.paint()

# Simulating different environments


print("Windows Environment:")
configure_application("Windows")

print("\nMac Environment:")
configure_application("Mac")

Explanation of code:

 Abstract Products (Button, Checkbox):

 These are interfaces (abstract classes in Python) for the products that the factories will
produce.
 Each of these defines the paint() method that concrete products must implement.

 Concrete Products (WinButton, WinCheckbox, MacButton, MacCheckbox):

 These are the concrete implementations of the Button and Checkbox interfaces.
 For each operating system (Windows and Mac), there are corresponding classes for
buttons and checkboxes that implement the paint() method.
 Abstract Factory (GUIFactory):

 This is the interface for creating related products (buttons and checkboxes).
 It declares methods createButton() and createCheckbox() which return instances
of Button and Checkbox.

 Concrete Factories (WinFactory, MacFactory):

 These concrete factories implement the GUIFactory interface and create specific
button and checkbox objects depending on the operating system.

 Client (Application):

 The Application class uses the factory to get instances of buttons and checkboxes.
 The method createUI() creates the button and checkbox, and the paint() method
renders them.

Output:
Windows Environment:
Rendering a Windows Button.
Rendering a Windows Checkbox.

Mac Environment:
Rendering a Mac Button.
Rendering a Mac Checkbox.

Game Enemy Generation

Sample Code:
from abc import ABC, abstractmethod

# Abstract Enemy Classes


class Enemy(ABC):
@abstractmethod
def attack(self):
pass

class UndeadEnemy(Enemy):
def attack(self):
return "The undead enemy attacks with dark magic!"

class AlienEnemy(Enemy):
def attack(self):
return "The alien enemy attacks with plasma beams!"

class RobotEnemy(Enemy):
def attack(self):
return "The robot enemy attacks with lasers!"

# Abstract Factory
class AbstractEnemyFactory(ABC):
@abstractmethod
def createEnemy(self, type: str) -> Enemy:
pass

# Concrete Factories
class UndeadFactory(AbstractEnemyFactory):
def createEnemy(self, type: str) -> Enemy:
if type == "Zombie":
return Zombie()
elif type == "Vampire":
return Vampire()
else:
raise ValueError(f"Unknown undead enemy type: {type}")

class AlienFactory(AbstractEnemyFactory):
def createEnemy(self, type: str) -> Enemy:
if type == "Martian":
return Martian()
elif type == "Predator":
return Predator()
else:
raise ValueError(f"Unknown alien enemy type: {type}")

class RobotFactory(AbstractEnemyFactory):
def createEnemy(self, type: str) -> Enemy:
if type == "Android":
return Android()
elif type == "Cyborg":
return Cyborg()
else:
raise ValueError(f"Unknown robot enemy type: {type}")
# Concrete Enemy Types for Undead
class Zombie(UndeadEnemy):
def attack(self):
return "Zombie lumbers towards you!"

class Vampire(UndeadEnemy):
def attack(self):
return "Vampire swoops in for a bite!"

# Concrete Enemy Types for Alien


class Martian(AlienEnemy):
def attack(self):
return "Martian fires energy beams!"

class Predator(AlienEnemy):
def attack(self):
return "Predator hunts you down silently!"

# Concrete Enemy Types for Robot


class Android(RobotEnemy):
def attack(self):
return "Android calculates a precise attack!"

class Cyborg(RobotEnemy):
def attack(self):
return "Cyborg strikes with enhanced strength!"

# Client Code
def client_code(factory: AbstractEnemyFactory, enemy_type: str):
enemy = factory.createEnemy(enemy_type)
print(enemy.attack())

# Example Usage
if __name__ == "__main__":
print("Creating Undead Enemies:")
undead_factory = UndeadFactory()
client_code(undead_factory, "Zombie")
client_code(undead_factory, "Vampire")

print("\nCreating Alien Enemies:")


alien_factory = AlienFactory()
client_code(alien_factory, "Martian")
client_code(alien_factory, "Predator")

print("\nCreating Robot Enemies:")


robot_factory = RobotFactory()
client_code(robot_factory, "Android")
client_code(robot_factory, "Cyborg")
Explanation of Code:

 Abstract Classes (Enemy):

 This defines the common interface for all enemies, including the attack() method
that each concrete enemy must implement.

 Concrete Enemies (Zombie, Vampire, Martian, Predator, Android, Cyborg):

 Each concrete enemy class implements the attack() method to define how the
enemy attacks.

 Abstract Factory (AbstractEnemyFactory):

 This defines the method createEnemy() which is responsible for creating different
types of enemies.

 Concrete Factories (UndeadFactory, AlienFactory, RobotFactory):

 These factories implement the AbstractEnemyFactory and are responsible for


creating specific enemies (like zombies or vampires for the UndeadFactory).

 Client Code:

 The client code interacts with the abstract factory to create specific types of enemies.
It doesn't need to know the exact class of the enemy, only that it is creating one.

Output:
Creating Undead Enemies:
Zombie lumbers towards you!
Vampire swoops in for a bite!

Creating Alien Enemies:


Martian fires energy beams!
Predator hunts you down silently!

Creating Robot Enemies:


Android calculates a precise attack!
Cyborg strikes with enhanced strength!

Conclusion:

The Abstract Factory Pattern provides a powerful way to create families of related
or dependent objects without specifying their concrete classes. This pattern ensures that the
client code remains decoupled from the creation process, making it easier to introduce new
enemy types or families without modifying existing code.

You might also like