본문 바로가기
James Cooper - Python Programming with D

The Abstract Factory Pattern

by 자동매매 2023. 3. 23.

The Abstract Factory pattern is one level of abstraction higher than the Factory pattern. You use this pattern when you want to return one of several related classes of objects, each of which can return several different objects on request. In other words, the Abstract Factory is a factory object that returns one of several groups of classes. Determining which class from that group to use might even come from a Simple Factory.

One classic application of the abstract factory is the case where your system needs to support multiple “look-and-feel” user interfaces, such as Windows, Gnome, or OS/X. You tell the factory that you want your program to look like Windows, and it returns a GUI factory that returns Windows-like objects. Then when you request specific objects such as buttons, check boxes, and windows, the GUI factory returns Windows instances of these visual interface components.

 

A GardenMaker Factory

Let’s consider a simple example of when you might want to use an abstract factory in your application.

Suppose you are writing a program to plan the layout of gardens. These could be annual gardens, vegetable gardens, or perennial gardens. No matter which kind of garden you are planning, you want to ask the same questions:

  1. What are good border plants?
  2. What are good center plants?
  3. What plants do well in partial shade?

You probably have many other plant questions that we’ll omit in this simple example.

We want a base Garden class that can answer these questions:

# Abstract Garden class
class Garden:
    def getShade(): pass
    def getCenter(): pass
    def getBorder(): pass

 

where our simple Plant object just contains and returns the plant name:

# Plant class gives you its name
class Plant:
    def __init__(self, pname):
        self.name = pname     #save name
    def getName(self):
        return self.name

 

In a real system, each type of garden would probably consult an elaborate database of plant information. In our simple example, we’ll return one kind of each plant. So, for example, for the vegetable garden we simply write

# one of three Garden subclasses
class VeggieGarden (Garden):
    def getShade(self):
        return  Plant("Broccoli")
    def getCenter(self):
        return Plant("Corn")
    def getBorder(self):
        return  Plant("Peas")

 

In a similar way, we can create Garden classes for PerennialGarden and AnnualGarden. Now we have a series of Garden objects, each of which returns one of several Plant objects. The factory is really just the three ChoiceButtons, derived from the Radiobutton.

        ChoiceButton(lbframe, 'Vegetable', 0, VeggieGarden, self,  groupv)
        ChoiceButton(lbframe, 'Annual', 1, AnnualGarden, self, groupv)
        ChoiceButton(lbframe, 'Perennial', 2, PerennialGarden, self, groupv)

 

Each ChoiceButton has its own comd method that copies the correct instance of Garden into the main Gardener class:

    # clicks are sent here
    # The background is also cleared
    def comd(self):
        self.gardener.setGarden(self.garden)
        self.gardener.clearCanvas()

Then when you click the Center, Border, or Shade buttons, that button writes the name of the current shade plant onto the canvas.

For example:

    def setCenter(self):
        self.canv.create_text(100,120, text=self.garden.getCenter(self).getName())

This Simple Factory system can be used along with a more complex user interface to select the garden and begin planning it (see Figure 7-1).

Figure 7-1 Garden planner interface

 

How the User Interface Works

This simple interface consists of two parts: On the left side, you select the garden type; on the right side, you select the plant category. When you click one of the garden types, this actuates the Abstract Factory and copies the correct garden into the Gardener class. Then when a user clicks one of the plant type buttons, the plant type is returned and the name of that plant is displayed.

One of the great strengths of the Abstract Factory is that you can easily add new subclasses. For example, if you needed a GrassGarden or a WildFlowerGarden, you can subclass Garden and produce these classes. The

only real change you’d need to make in any existing code is to add some way to choose these new kinds of gardens.

 

Consequences of the Abstract Factory Pattern

One of the main purposes of the Abstract Factory is that it isolates the concrete classes that are generated. The actual class names of these classes are hidden in the factory and need not be known at the client level.

Because of this isolation of classes, you can freely change or interchange these product class families. Further, because you generate only one kind of concrete class, this system keeps you from inadvertently using classes from different families of products. However, adding new class families takes some effort because you need to define new, unambiguous conditions that cause such a new family of classes to be returned.

Although all the classes that the Abstract Factory generates have the same base class, there is nothing to prevent some subclasses from having additional methods that differ from the methods of other classes. For example, a BonsaiGarden class might have a Height or WateringFrequency

method that does not exist in other classes. This presents the same problem as occurs in any subclasses: you don’t know whether you can call a class method unless you know whether that subclass is one that allows those methods. This problem has the same two solutions as in any similar case: Either you can define all the methods in the base class, even if they don’t always have an actual function, or you can test to see which kind of class you have.

gardenPlanner2.py
0.00MB

 

 

Thought Questions

If you are writing a program to track investments, such as stocks, bonds, metal futures, and derivatives, how might you use an Abstract Factory?

 

Code on GitHub

The program Gardening.py launches the user interface shown in this chapter, along with exercises for the Abstract Factory and the various Garden classes.

Gardening.py
0.00MB
gardenPlanner.py
0.00MB

'James Cooper - Python Programming with D' 카테고리의 다른 글

The Prototype Pattern  (0) 2023.03.23
The Singleton Pattern  (0) 2023.03.23
The Factory Method Pattern  (0) 2023.03.23
The Factory Pattern  (0) 2023.03.23
What Are Design Patterns?  (0) 2023.03.23

댓글