CSC/ECE 517 Fall 2009/wiki2 13 StaticDynamic: Difference between revisions

From Expertiza_Wiki
Jump to navigation Jump to search
 
(22 intermediate revisions by 2 users not shown)
Line 1: Line 1:
'''Design Patterns from a Static/Dynamic Point of View'''
'''Design Patterns from a Static/Dynamic Point of View'''


Clearly, Ruby offers more concise realizations of certain design patterns than Java does. Is this typical of dynamic o-o languages? Are there design patterns that any dynamically typed language can realize better than a statically typed language? Are there instances when a <em>different</em> pattern should be used in a dynamic language than a static language?
Ruby provides more concise realizations of certain design patterns than Java does, especially when lots of declaration are involved for Java, Ruby needs none. There could be design patterns that dynamically typed language is able to realize better than a statically typed language. In some instances a different pattern may better suit dynamically typed language than a static typed one.


== Introduction ==
== Introduction ==
=== Design Pattern ===
=== Design Pattern ===
A design pattern is a general reusable solution to a commonly occurring problem in software design. A design pattern is not a finished design that can be transformed directly into code. It is a description or template for how to solve a problem that can be used in many different situations. Object-oriented design patterns typically show relationships and interactions between classes or objects, without specifying the final application classes or objects that are involved.
A design pattern is a description or template for solving a particular problem under different circumstances. It's a general reusable solution to a commonly occurring problem in software design. Object-oriented design pattern is not a finished product but rather an idea can be realized into code. It specifies the relationships and interactions between classes or objects, and leave the job of specifying the final application classes or objects to the implementer.


[http://www.dofactory.com/Patterns/Patterns.aspx [1]]
{| border="1"
{| border="1"
|-
|-
!Name !! Description
!Name !! Description !! Ref.
|-
|-
| Creational Patterns
| <b>Creational Patterns</b> || <b>Deal with object creation mechanisms</b>
|-
|-
| Abstract Factory   || Creates an instance of several families of classes
| Abstract Factory   || Provide a way to create a families of related/dependent objects without specifying their concrete classes. || [http://en.wikipedia.org/wiki/Abstract_factory_pattern]
|-
|-
| Builder   || Separates object construction from its representation
| Builder   || Separate the construction of a complex object from its representation so different representations can be constructed by the same process. || [http://en.wikipedia.org/wiki/Builder_pattern]
|-
|-
| Factory Method   || Creates an instance of several derived classes
| Factory Method   || Defer instantiation to subclasses. || [http://en.wikipedia.org/wiki/Factory_method_pattern]
|-
|-
| Prototype   || A fully initialized instance to be copied or cloned
| Prototype   || Create new objects by copying a prototypical instance. || [http://en.wikipedia.org/wiki/Prototype_pattern]
|-
|-
| Singleton   || A class of which only a single instance can exist
| Singleton   || Ensure a class only have one single instance existing and accessible globally. || [http://en.wikipedia.org/wiki/Prototype_pattern]
|-
|-
| Structural Patterns
| <b>Structural Patterns</b> || <b>Realize relationships between entities</b>
|-
|-
| Adapter   || Match interfaces of different classes
| Adapter   || Convert an otherwise incompatible interface of a class into another that clients can work with. || [http://en.wikipedia.org/wiki/Adapter_pattern]
|-
|-
| Bridge   || Separates an object’s interface from its implementation
| Bridge   || Decouple an interface from its implementation so that the two can vary independently. || [http://en.wikipedia.org/wiki/Bridge_pattern]
|-
|-
| Composite   || A tree structure of simple and composite objects
| Composite   || Compose objects into tree structures to represent part-whole hierarchies so they can be treated uniformaly by clients. || [http://en.wikipedia.org/wiki/Composite_pattern]
|-
|-
| Decorator   || Add responsibilities to objects dynamically
| Decorator   || Attach additional responsibilities to an object dynamically for extending functionality, while keeping the same interface. || [http://en.wikipedia.org/wiki/Decorator_pattern]
|-
|-
| Facade   || A single class that represents an entire subsystem
| Facade   || Provide a higher level unified interface to a set of interfaces to make the subsystem easier to use. || [http://en.wikipedia.org/wiki/Facade_pattern]
|-
|-
| Flyweight   || A fine-grained instance used for efficient sharing
| Flyweight   || Support large numbers of fine-grained objects efficiently by sharing. || [http://en.wikipedia.org/wiki/Flyweight_pattern]
|-
|-
| Proxy   || An object representing another object
| Proxy   || Provide a surrogate or interface for another object to control access to it. || [http://en.wikipedia.org/wiki/Proxy_pattern]
|-
|-
|  Behavioral Patterns
<b>Behavioral Patterns</b> || <b>Common communication patterns between objects and its realization</b>
|-
|-
| Chain of Resp.   || A way of passing a request between a chain of objects
| Chain of Resp.   || Add more than one object to handle the request and pass along before the receiving objects to decouple the requester from the receiver objects. || [http://en.wikipedia.org/wiki/Chain_of_responsibility_pattern]
|-
|-
| Command   || Encapsulate a command request as an object
|-
|-
| Interpreter   || A way to include language elements in a program
| Command   || Encapsulate a command request as an object  || [http://en.wikipedia.org/wiki/Command_pattern]
|-
|-
| Iterator   || Sequentially access the elements of a collection
| Interpreter   || Given a language, specifies how to evaluate sentences using a defined grammar. || [http://en.wikipedia.org/wiki/Interpreter_pattern]
|-
|-
| Mediator   || Defines simplified communication between classes
| Iterator   || Iterators is used to access the elements of a collection sequentially without exposing its underlying representation. || [http://en.wikipedia.org/wiki/Iterator_pattern]
|-
|-
| Memento   || Capture and restore an object's internal state
| Mediator   || Define an object that encapsulates how a set of objects interact to keep objects from referring to each other explicitly. Promote de-coupling and let one vary their interaction independently. || [http://en.wikipedia.org/wiki/Mediator_pattern]
|-
|-
| Observer   || A way of notifying change to a number of classes
| Memento   || Capture and externalize an object's internal state for later restoration. || [http://en.wikipedia.org/wiki/Memento_pattern]
|-
|-
| State   || Alter an object's behavior when its state changes
| Observer   || When one object changes state, all its dependents are notified and updated automatically. || [http://en.wikipedia.org/wiki/Observer_pattern]
|-
|-
| Strategy   || Encapsulates an algorithm inside a class
| State   || Alter an object's behavior like change its class when its internal state changes. || [http://en.wikipedia.org/wiki/State_pattern]
|-
|-
| Template Method   || Defer the exact steps of an algorithm to a subclass
| Strategy   || Encapsulates a family of algorithms inside a class so they can vary independently from the client using them. || [http://en.wikipedia.org/wiki/Strategy_pattern]
|-
|-
| Visitor   || Defines a new operation to a class without change
| Template Method   || Allow the subclass to redefine the detailed steps without modifying algorithm's structure. || [http://en.wikipedia.org/wiki/Template_pattern]
|-
| Visitor   || Allow defining a new operation without changing the classes of the elements on which it operates. || [http://en.wikipedia.org/wiki/Visitor_pattern]
|}
|}


=== Static/Dynamic Type Languages ===
=== Static/Dynamic Type Languages ===
Types usually have associations either with values in memory or with objects such as variables. Because any value simply consists of a sequence of bits in a computer, hardware makes no distinction even between memory addresses, instruction code, characters, integers and floating-point numbers. Assignment to a type informs programs and programmers how those bit collections should be treated.
Types associates either with values or with objects such as variables. Any value simply consists of a sequence of bits in a computer, which are indistinguishable without knowing its boundary and structure. It's like taking out all the white spaces out of an article. Type informs users (program or programmer) of the information (bits) how those bit collections should be treated.


Major functions provided by type systems include:
Major functions provided by type systems include:


* Safety - Use of types may allow a compiler to detect meaningless or probably invalid code. For example, we can identify an expression "Hello, World" as invalid because the rules of arithmetic do not specify how to divide an integer by a string. As discussed below, strong typing offers more safety, but generally does not guarantee complete safety (see type-safety for more information).
* Safety - Use of types may allow a compiler to detect meaningless or probably invalid code. For example, we can identify an expression 100/"Hello, World" as invalid because the rules of arithmetic do not specify how to divide an integer by a string. Take caution though strong typing offers more safety, but generally does not guarantee complete safety.
* Optimization - Static type-checking may provide useful compile-time information. For example, if a type requires that a value must align in memory at a multiple of 4 bytes, the compiler may be able to use more efficient machine instructions.
* Optimization - Static type-checking may provide useful compile-time information. For example, if a type requires that a value must align in memory at a multiple of 4 bytes, the compiler may be able to use more efficient machine instructions.
* Documentation - In more expressive type systems, types can serve as a form of documentation, since they can illustrate the intent of the programmer. For instance, timestamps may be represented as integers—but if a programmer declares a function as returning a timestamp type rather than merely an integer type, this documents part of the meaning of the function.
* Document - In more expressive type systems, type can explicitly illustrate the intent of the programmer. For instance, timestamps may be represented as integers—but if a programmer declares a function as returning a timestamp type rather than merely an integer type, this documents part of the purpose of the function.
* Abstraction (or modularity) - Types allow programmers to think about programs at a higher level than the bit or byte, not bothering with low-level implementation. For example, programmers can think of a string as a collection of character values instead of as a mere array of bytes. Or, types can allow programmers to express the interface between two subsystems. This helps localize the definitions required for interoperability of the subsystems and prevents inconsistencies when those subsystems communicate.
* Abstraction (or modularity) - Types allow programmers to think about programs at a higher level than the bit or byte, not bothering with low-level implementation. It gives programmers a concept, a scope, of what he deals with. Type allows programmers to express the interface between two subsystems. This helps localize the definitions required for interoperability, and prevents inconsistencies among those subsystems when they communicate.


==== Static Type Languages ====
==== Static Type Languages ====
Line 88: Line 88:




[http://i.cmpnet.com/ddj/ddj/images/ddj9708d/9708df6.gif [2]]
Many software designers view patterns as a form of language-independent design. Pattern-Oriented Software Architectures: A System of Patterns, edited by Frank Buschmann (John Wiley & Sons, 1996), for instance, divides patterns into three main groups -- architectural patterns, design patterns, and idioms. Only the idioms (defined as "low-level patterns specific to a program language") are language dependent -- the other patterns (and the implicit pattern language) rise above the level of programming language, much as the unified modeling language (UML) provides a common way to express designs.
Many software designers view patterns as a form of language-independent design. Pattern-Oriented Software Architectures: A System of Patterns, edited by Frank Buschmann (John Wiley & Sons, 1996), for instance, divides patterns into three main groups -- architectural patterns, design patterns, and idioms. Only the idioms (defined as "low-level patterns specific to a program language") are language dependent -- the other patterns (and the implicit pattern language) rise above the level of programming language, much as the unified modeling language (UML) provides a common way to express designs.


This idea of language independence is seductive. It is also misleading. While patterns are language independent, language choice limits the patterns that are possible, easily supported, and useful. Language also affects how applications are structured.
This idea of language independence is seductive. It is also misleading. While patterns are language independent, language choice limits the patterns that are possible, easily supported, and useful. Language also affects how applications are structured.


To illustrate, I'll examine some patterns often used with Objective-C, but not usually used (or used differently) with C++. Both languages are object-oriented extensions of C. The main difference between them is that C++ has compile-time binding and fairly strong typing while Objective-C uses the Smalltalk object model of dynamic binding and weak typing. I'll start by examining two idioms commonly found in Objective-C programming. While simple, these idioms illustrate some of the key Objective-C programming techniques (although I use NextStep classes and frameworks to illustrate points, what I say also holds true for more generic Objective-C environments). I'll also examine how three standard design patterns -- Visitor, Command, and Facade -- are implemented in Objective-C.
=== Where dynamically typed language is more concise ===
====Lazy Initialization Pattern====
Here is an example of Lazy Initialization Pattern for a Pizza class in C++ (From [http://en.wikipedia.org/wiki/Lazy_initialization Lazy initialization Wiki] with minor modifications):
 
<pre>
#include <iostream>
#include <string>
#include <map>
using namespace std;
class Pizza {
    private:
        static map<string,Pizza*> types;
        string type;
 
        // note: constructor private forcing one to use static getPizza()
        Pizza(const string& t) : type( t ) {}
 
    public:
        static Pizza* getPizza(const string& type);
        static void printCurrentTypes();
};
 
//static member variable
map<string,Pizza*> Pizza::types;       
/*
* Lazy Factory method, gets the instance associated with a
* certain type. Instantiates new ones as needed.
*/
Pizza* Pizza::getPizza(const string& type) {
    Pizza *& f = types[type];  //find a pre-existing instance
    if (!f) {
        // couldn't find one, then make a new one
        f = new Pizza(type); // lazy initialization
        types.insert(pair<string,Pizza*>(type, f)); // insert new instance into map
    }
    return f;
}
 
</pre>


====Objective- C Idiom 1====
Here is the same pattern realized in Python:


Use Weakly Typed Delegation to Implement Secondary Roles of Framework Objects. A framework is a set of objects designed to help users create a specific type of application or a specific part of an application. For most problem domains, there is a set of core abstractions that are independent of the framework. For example, consider a framework that helps you create a GUI. Almost every such framework includes an "Application" object. In NextStep and it is an Application, in Delphi's VCL it is TApplication, but the basic abstraction is the same. Similarly, all such frameworks contain some form of "Window," "Subview," "Button," and "Textfield." These framework objects are often the leaves on the framework's object graph.
<pre>
class Pizza:
    def __init__(self, type):
        self.type = type
   
class Pizzas:
    def __init__(self):
        self.types = {}
   
    def get_pizza(self, type):
        if type not in self.types:
            self.types[type] = Pizza(type)
       
        return self.types[type]


Framework objects have a clearly defined role within any application. Application objects route events, and Window objects provide a place to draw. However, programmers often subclass objects to allow them to play a secondary role within an application. For example, Textfields are often subclassed within an application, giving them the ability to validate user input.


Standard object-oriented design principles suggest that secondary roles be implemented via the Strategy pattern. Since frameworks are usually developed separately and implemented as shared libraries, using a strongly typed language results in Figure 1[http://i.cmpnet.com/ddj/ddj/images/ddj9708d/9708df1.gif [3]]. However, Figure 1[http://i.cmpnet.com/ddj/ddj/images/ddj9708d/9708df1.gif [3]] can cause problems over the application life cycle. NextStep's Application object, for example, acquired nine new delegate methods between versions 2.0 and 3.3 of the framework. These were gradual modifications brought about by changes in how people use computers, as well as changes made to remedy oversights in the original design. In Figure 1[http://i.cmpnet.com/ddj/ddj/images/ddj9708d/9708df1.gif [3]], each of these changes would have required a recompilation of the application and a new release. Moreover, existing copies of the application installed on users' machines would need to be updated.
</pre>


One solution to this problem is to implement a strict versioning system. For example, the Windows machine I use has three distinct versions of MSVCRT**.DLL, and five versions of MFC**.DLL. If I try to launch my copy of Visual Eiffel, an alert dialog tells me I have the wrong version of CT13D32.DLL.
=== Where dynamically typed language is able to realize better than a statically typed language ===


At best, strict versioning is a stop-gap solution. Depending on my applications, I might load all five versions of MFC**.DLL into memory, defeating the point of shared libraries. Additionally, older applications won't automatically inherit new functionality (or have bugs repaired) -- they still use the older version of the framework. Moreover, minor updates to an application can become complex; if you want to use a feature found in the new version of the framework, you must update every object that depends on the framework (including all the strategy objects).
To illustrate, we'll examine a pattern often used with Objective-C, but not usually used (or used differently) with C++. Both languages are object-oriented extensions of C. The main difference between them is that C++ has compile-time binding and fairly strong typing while Objective-C uses the Smalltalk object model of dynamic binding and weak typing. We'll be examining facade, commonly found in Objective-C programming. While simple, facade illustrates some of the key Objective-C programming techniques


The Objective-C approach removes the abstract base class, giving the framework object a more complex setDelegate method. The framework object defines a set of strategic methods it will call if they are defined. Then, inside the setDelegate method, run-time type information (RTTI) determines which methods the delegate has implemented. If the delegate doesn't implement the strategic method, the framework object doesn't call it. This is illustrated in Listing One where the new delegate object is queried about each function. If the new delegate implements the function, the method pointer is obtained.
====The Facade Pattern====


This approach eliminates the versioning problem -- older applications work with new frameworks. For example, most applications compiled under NextStep 2.0 can run using the shared libraries of NextStep 3.3. If the application needs to be updated to take advantage of a new feature in the framework, the necessary code change is minimal because only the object getting updated needs to be modified.
Lets examine a commonly used architectural pattern that describes a way to structure applications to take advantage of this flexibility.


The essence of this idiom is the principle that the framework and application should evolve independently. It is not easy to see how to do this in a statically typed language.
Previously with structured programming, saving an application's state was simple. Programs were divided into data and functions, and saving consisted of calling the function that wrote the data to some storage area. In object-oriented applications, things become a little more difficult. To the extent that you practice information hiding, object serialization is the natural approach to take.
 
Unfortunately, if m is the number of object references and n is the number of objects, serialization is O(mlog(n)). This is far too slow for serialization to be the saving mechanism in many applications.
 
But an Objective-C program that uses the four previous patterns will almost certainly use lots of facades as well. Notice here[http://i.cmpnet.com/ddj/ddj/images/ddj9708d/9708df6.gif [3]]that Facades look a lot like cut points in the object graph. This leads to the natural Objective-C solution to the speed problem for object serialization: Serialize each facade to a separate Serializer (make each facade responsible for serializing the subsystem it abstracts).
 
This can get complicated. If an object outside a subsystem bypasses a facade (and messages an object in a subsystem directly), then extra care must be taken during serialization (to avoid serializing objects to more than one location). And, deserializing (opening) becomes trickier as well -- objects that bypass a facade will need to find objects within the subsystem. In practice, this comes down to making the facades used in serialization Singletons and making certain that all connections to objects in the subsystem are mediated by the facade (so that, during deserialization, the connection can be restored).


== Conclusion ==
== Conclusion ==
Line 117: Line 176:
There are various levels of design recognition for generating repeatable solutions to commonly occurring programming problems in software design.  Design patterns in this case have been met with criticism in whether it negates the agile product development process.  From our example above we have shown that when implementing patterns across various languages of varying type systems a design pattern may not always resolve common problems efficiently.  Thus, the idea of a language independent pattern recognition solution must be evaluated thoroughly when in considering from a static and dynamic point of view.
There are various levels of design recognition for generating repeatable solutions to commonly occurring programming problems in software design.  Design patterns in this case have been met with criticism in whether it negates the agile product development process.  From our example above we have shown that when implementing patterns across various languages of varying type systems a design pattern may not always resolve common problems efficiently.  Thus, the idea of a language independent pattern recognition solution must be evaluated thoroughly when in considering from a static and dynamic point of view.


== References ==
== Useful Links ==
 
* http://en.wikipedia.org/wiki/Type_system
* http://en.wikipedia.org/wiki/Design_pattern_(computer_science)
* http://www.dofactory.com/Patterns/Patterns.aspx

Latest revision as of 22:53, 12 October 2009

Design Patterns from a Static/Dynamic Point of View

Ruby provides more concise realizations of certain design patterns than Java does, especially when lots of declaration are involved for Java, Ruby needs none. There could be design patterns that dynamically typed language is able to realize better than a statically typed language. In some instances a different pattern may better suit dynamically typed language than a static typed one.

Introduction

Design Pattern

A design pattern is a description or template for solving a particular problem under different circumstances. It's a general reusable solution to a commonly occurring problem in software design. Object-oriented design pattern is not a finished product but rather an idea can be realized into code. It specifies the relationships and interactions between classes or objects, and leave the job of specifying the final application classes or objects to the implementer.

Name Description Ref.
Creational Patterns Deal with object creation mechanisms
Abstract Factory Provide a way to create a families of related/dependent objects without specifying their concrete classes. [1]
Builder Separate the construction of a complex object from its representation so different representations can be constructed by the same process. [2]
Factory Method Defer instantiation to subclasses. [3]
Prototype Create new objects by copying a prototypical instance. [4]
Singleton Ensure a class only have one single instance existing and accessible globally. [5]
Structural Patterns Realize relationships between entities
Adapter Convert an otherwise incompatible interface of a class into another that clients can work with. [6]
Bridge Decouple an interface from its implementation so that the two can vary independently. [7]
Composite Compose objects into tree structures to represent part-whole hierarchies so they can be treated uniformaly by clients. [8]
Decorator Attach additional responsibilities to an object dynamically for extending functionality, while keeping the same interface. [9]
Facade Provide a higher level unified interface to a set of interfaces to make the subsystem easier to use. [10]
Flyweight Support large numbers of fine-grained objects efficiently by sharing. [11]
Proxy Provide a surrogate or interface for another object to control access to it. [12]
Behavioral Patterns Common communication patterns between objects and its realization
Chain of Resp. Add more than one object to handle the request and pass along before the receiving objects to decouple the requester from the receiver objects. [13]
Command Encapsulate a command request as an object [14]
Interpreter Given a language, specifies how to evaluate sentences using a defined grammar. [15]
Iterator Iterators is used to access the elements of a collection sequentially without exposing its underlying representation. [16]
Mediator Define an object that encapsulates how a set of objects interact to keep objects from referring to each other explicitly. Promote de-coupling and let one vary their interaction independently. [17]
Memento Capture and externalize an object's internal state for later restoration. [18]
Observer When one object changes state, all its dependents are notified and updated automatically. [19]
State Alter an object's behavior like change its class when its internal state changes. [20]
Strategy Encapsulates a family of algorithms inside a class so they can vary independently from the client using them. [21]
Template Method Allow the subclass to redefine the detailed steps without modifying algorithm's structure. [22]
Visitor Allow defining a new operation without changing the classes of the elements on which it operates. [23]

Static/Dynamic Type Languages

Types associates either with values or with objects such as variables. Any value simply consists of a sequence of bits in a computer, which are indistinguishable without knowing its boundary and structure. It's like taking out all the white spaces out of an article. Type informs users (program or programmer) of the information (bits) how those bit collections should be treated.

Major functions provided by type systems include:

  • Safety - Use of types may allow a compiler to detect meaningless or probably invalid code. For example, we can identify an expression 100/"Hello, World" as invalid because the rules of arithmetic do not specify how to divide an integer by a string. Take caution though strong typing offers more safety, but generally does not guarantee complete safety.
  • Optimization - Static type-checking may provide useful compile-time information. For example, if a type requires that a value must align in memory at a multiple of 4 bytes, the compiler may be able to use more efficient machine instructions.
  • Document - In more expressive type systems, type can explicitly illustrate the intent of the programmer. For instance, timestamps may be represented as integers—but if a programmer declares a function as returning a timestamp type rather than merely an integer type, this documents part of the purpose of the function.
  • Abstraction (or modularity) - Types allow programmers to think about programs at a higher level than the bit or byte, not bothering with low-level implementation. It gives programmers a concept, a scope, of what he deals with. Type allows programmers to express the interface between two subsystems. This helps localize the definitions required for interoperability, and prevents inconsistencies among those subsystems when they communicate.

Static Type Languages

A programming language is said to use static typing when type checking is performed during compile-time as opposed to run-time.

C++, C#, Java

Dynamic Type Languages

A programming language is said to be dynamically typed, or just 'dynamic', when the majority of its type checking is performed at run-time as opposed to at compile-time.

Ruby, Python

Example

Many software designers view patterns as a form of language-independent design. Pattern-Oriented Software Architectures: A System of Patterns, edited by Frank Buschmann (John Wiley & Sons, 1996), for instance, divides patterns into three main groups -- architectural patterns, design patterns, and idioms. Only the idioms (defined as "low-level patterns specific to a program language") are language dependent -- the other patterns (and the implicit pattern language) rise above the level of programming language, much as the unified modeling language (UML) provides a common way to express designs.

This idea of language independence is seductive. It is also misleading. While patterns are language independent, language choice limits the patterns that are possible, easily supported, and useful. Language also affects how applications are structured.

Where dynamically typed language is more concise

Lazy Initialization Pattern

Here is an example of Lazy Initialization Pattern for a Pizza class in C++ (From Lazy initialization Wiki with minor modifications):

#include <iostream>
#include <string>
#include <map>
 
using namespace std;
 
class Pizza {
    private:
        static map<string,Pizza*> types;
        string type;

        // note: constructor private forcing one to use static getPizza()
        Pizza(const string& t) : type( t ) {}

    public:
        static Pizza* getPizza(const string& type);
        static void printCurrentTypes();
};

//static member variable
map<string,Pizza*> Pizza::types;        
 
/*
 * Lazy Factory method, gets the instance associated with a
 * certain type. Instantiates new ones as needed.
 */
Pizza* Pizza::getPizza(const string& type) {
    Pizza *& f = types[type];   //find a pre-existing instance
 
    if (!f) {
        // couldn't find one, then make a new one
        f = new Pizza(type); // lazy initialization
        types.insert(pair<string,Pizza*>(type, f)); // insert new instance into map
    }
    return f;
}

Here is the same pattern realized in Python:

class Pizza:
    def __init__(self, type):
        self.type = type
    
class Pizzas:
    def __init__(self):
        self.types = {}
    
    def get_pizza(self, type):
        if type not in self.types:
            self.types[type] = Pizza(type)
        
        return self.types[type]


Where dynamically typed language is able to realize better than a statically typed language

To illustrate, we'll examine a pattern often used with Objective-C, but not usually used (or used differently) with C++. Both languages are object-oriented extensions of C. The main difference between them is that C++ has compile-time binding and fairly strong typing while Objective-C uses the Smalltalk object model of dynamic binding and weak typing. We'll be examining facade, commonly found in Objective-C programming. While simple, facade illustrates some of the key Objective-C programming techniques

The Facade Pattern

Lets examine a commonly used architectural pattern that describes a way to structure applications to take advantage of this flexibility.

Previously with structured programming, saving an application's state was simple. Programs were divided into data and functions, and saving consisted of calling the function that wrote the data to some storage area. In object-oriented applications, things become a little more difficult. To the extent that you practice information hiding, object serialization is the natural approach to take.

Unfortunately, if m is the number of object references and n is the number of objects, serialization is O(mlog(n)). This is far too slow for serialization to be the saving mechanism in many applications.

But an Objective-C program that uses the four previous patterns will almost certainly use lots of facades as well. Notice here[3]that Facades look a lot like cut points in the object graph. This leads to the natural Objective-C solution to the speed problem for object serialization: Serialize each facade to a separate Serializer (make each facade responsible for serializing the subsystem it abstracts).

This can get complicated. If an object outside a subsystem bypasses a facade (and messages an object in a subsystem directly), then extra care must be taken during serialization (to avoid serializing objects to more than one location). And, deserializing (opening) becomes trickier as well -- objects that bypass a facade will need to find objects within the subsystem. In practice, this comes down to making the facades used in serialization Singletons and making certain that all connections to objects in the subsystem are mediated by the facade (so that, during deserialization, the connection can be restored).

Conclusion

There are various levels of design recognition for generating repeatable solutions to commonly occurring programming problems in software design. Design patterns in this case have been met with criticism in whether it negates the agile product development process. From our example above we have shown that when implementing patterns across various languages of varying type systems a design pattern may not always resolve common problems efficiently. Thus, the idea of a language independent pattern recognition solution must be evaluated thoroughly when in considering from a static and dynamic point of view.

Useful Links