Studijní materiály
Detail souboru
Zdrojový kód
<?xml version="1.0" ?>
<!DOCTYPE book PUBLIC "-//KDE//DTD DocBook XML V4.2-Based Variant V1.1//EN" "dtd/kdex.dtd" [
<!-- Define an entity for your application if it is not part of KDE
CVS -->
<!--<!ENTITY kmyapplication "<application>
KMyApp</application>">-->
<!--<!ENTITY kappname "&kmyapplication;">
--><!-- replace kmyapplication here
do *not* replace kappname-->
<!--<!ENTITY package "kde-module">
--><!-- kdebase, kdeadmin, etc. Leave
this unchanged if your
application is not maintained in KDE CVS -->
<!--<!ENTITY % addindex "IGNORE">
-->
<!ENTITY % English "INCLUDE"> <!-- ONLY If you are writing non-English
original documentation, change
the language here -->
<!-- Do not define any other entities; instead, use the entities
from entities/general.entities and $LANG/user.entities. -->
]>
<!-- The language must NOT be changed here. -->
<!-- If you are writing original documentation in a language other -->
<!-- than English, change the language above ONLY, not here -->
<book>
<!-- This header contains all of the meta-information for the document such
as Authors, publish date, the abstract, and Keywords -->
<bookinfo>
<title>Design Patterns Overveiw</title>
<authorgroup>
<author><personname><firstname>Kamil</firstname><surname>Dudka</surname></personname><email>kamil@dudka.cz</email></author>
</authorgroup>
<date>2008-02-09</date>
<!-- Abstract about this handbook -->
<abstract>
<!-- TODO -->
</abstract>
<!-- This is a set of Keywords for indexing by search engines.
Please at least include KDE, the KDE package it is in, the name
of your application, and a few relevant keywords. -->
<!--<keywordset>
<keyword>KDE</keyword>
<keyword>kdeutils</keyword>
<keyword>Kapp</keyword>
<keyword>nothing</keyword>
<keyword>nothing else</keyword>
</keywordset>-->
</bookinfo>
<!--<chapter id="Definition">
</chapter>-->
<chapter id="creational-dp">
<title>Creational design patterns</title>
<sect1>
<sect3>
<title>Overview</title>
</sect3>
</sect1>
<sect1 id="singleton">
<title>Singleton</title>
<para>GoF: Ensures a class only has one instance, and provide a global point of access to it.</para>
</sect1>
<sect1 id="prototype">
<title>Prototype</title>
<para>GoF: Specify the kinds of objects to create using a protypical instance, and create new objects by copying this prototype.</para>
</sect1>
<sect1 id="factory-method">
<title>Factory method</title>
<para>GoF: Define an interface for creating an object, but let subclasses decide which class to instantiate. Factory Method lets a class defer instantiation to subclasses.</para>
</sect1>
<sect1 id="abstract-factory">
<title>Abstract factory</title>
<para>GoF: Provide an interface for creating families of related or dependent objects without specifying their concrete classes.</para>
</sect1>
<sect1 id="builder">
<title>Builder</title>
<para>GoF: Separate the construction of a complex object from its representation so that the same construction process can create different representations.</para>
</sect1>
</chapter>
<chapter id="structural-dp">
<title>Structural design patterns</title>
<sect1>
<sect3>
<title>Overview</title>
</sect3>
</sect1>
<sect1 id="flyweight">
<title>Flyweight</title>
<para>GoF: Use sharing to support large numbers of fine-grained objects efficiently.</para>
</sect1>
<sect1 id="proxy">
<title>Proxy</title>
<para>GoF: Provide a surrogate or placeholder for another object to control access to it.</para>
</sect1>
<sect1 id="facade">
<title>Facade</title>
<para>GoF: Provide a unified interface to a set of interfaces in a subsystem. Facade defines a higher-level interface that makes the subsystem easier to use.</para>
</sect1>
<sect1 id="adapter">
<title>Adapter</title>
<para>GoF: Convert the interface of a class into another interface clients expect. Adapter lets classes work together that couldn't otherwise because of incompatible interfaces.</para>
</sect1>
<sect1 id="composite">
<title>Composite</title>
<para>GoF: Compose objects into tree structures to represent whole-part hierarchies. Composite lets clients treat individual objects and compositions of objects uniformly.</para>
</sect1>
<sect1 id="decorator">
<title>Decorator</title>
<para>GoF: Attach additional responsibilities to an object dynamically. Decorators provide a flexible alternative to subclassing for extending functionality.</para>
</sect1>
<sect1 id="bridge">
<title>Bridge</title>
<para>GoF: Decouple an abstraction from its implementation so that the two can vary independently.</para>
</sect1>
</chapter>
<chapter id="behavioral-dp">
<title>Behavioral design patterns</title>
<sect1>
<sect3>
<title>Overview</title>
</sect3>
</sect1>
<sect1 id="command">
<title>Command</title>
<para>GoF: Encapsulate a request as an object, thereby letting you parameterize clients with different requests, queue or log requests, and support undoable operations.</para>
</sect1>
<sect1 id="iterator">
<title>Iterator</title>
<para>GoF: Provide a way to access the elements of an aggregate object sequentially without exposing its underlying representation.</para>
</sect1>
<sect1 id="state">
<title>State</title>
<para>GoF: Allow an object to alter its behavior when its internal state changes. The object will appear to change its class.</para>
</sect1>
<sect1 id="template-method">
<title>Template method</title>
<para>GoF: Define the skeleton of an algorithm in an operation, deferring some steps to client subclasses. Template Method lets subclasses redefine certain steps of an algorithm without changing the algorithm's structure.</para>
</sect1>
<sect1 id="chain-of-responsibility">
<title>Chain of Responsibility</title>
<para>GoF: Avoid coupling the sender of a request to its receiver by giving more than one object a chance to handle the request. Chain the receiving objects and pass the request along the chain until an object handles it.</para>
</sect1>
<sect1 id="observer">
<title>Observer</title>
<para>GoF: Define a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically.</para>
</sect1>
<sect1 id="mediator">
<title>Mediator</title>
<para>GoF: Define an object that encapsulates how a set of objects interact. Mediator promotes loose coupling by keeping objects from referring to each other explicitly, and it lets you vary their interaction independently.</para>
</sect1>
<sect1 id="strategy">
<title>Strategy</title>
<para>GoF: Define a family of algorithms, encapsulate each one, and make them interchangeable. Strategy lets the algorithm vary independently from the clients that use it.</para>
</sect1>
<sect1 id="visitor">
<title>Visitor</title>
<para>GoF: Represent an operation to be performed on the elements of an object structure. Visitor lets you define a new operation without changing the classes of the elements on which it operates.</para>
</sect1>
<sect1 id="memento">
<title>Memento</title>
<para>GoF: Without violating encapsulation, capture and externalize an object's internal state so that the object can be returned to this state later.</para>
</sect1>
<sect1 id="interpreter">
<title>Interpreter</title>
<para>GoF: Given a language, define a representation for its grammar along with an interpreter that uses the representation to interpret sentences in the language.</para>
</sect1>
</chapter>
<chapter id="non-GoF-dp">
<title>Non-GoF design patterns</title>
<sect1>
<sect3>
<sect4>
<title><link linkend="simple-factory-method">Simple Factory Method</link></title>
<blockquote>Simple (static) factory method is simplified version of <link linkend='factory-method'>factory method</link>. Its interface exports static method instead of constructor. This pattern is used in case we need reference to object, although direct usage of constructor is (due to some reason) not omptimal.</blockquote>
</sect4>
<sect4>
<title><link linkend="immutable-objects">Immutable objects</link></title>
<blockquote>Immutable object is value object, whose value can't be changed.</blockquote>
</sect4>
<sect4>
<title><link linkend="messenger">Messenger</link></title>
<blockquote>Messanger is used to merge a couple of standalone values into one object. Thus it can be easily transferred between methods. It is useful especially in Java.</blockquote>
</sect4>
<sect4>
<title><link linkend="servant">Servant</link></title>
<blockquote>Servant is class, which defines common functionality for a couple of classes. Its methods accept reference to served class as an parameter.</blockquote>
</sect4>
<sect4>
<title><link linkend="null-object">Null object</link></title>
<blockquote>Null object is valid object used instead of null-reference. It helps to avoid testing references on null.</blockquote>
</sect4>
<sect4>
<title><link linkend="library-class">Library class</link></title>
<blockquote>Library class is wrapper for a couple of static methods. Nobody needs to create its instance, so it is disabled.</blockquote>
</sect4>
<sect4>
<title><link linkend="original">Original</link></title>
<blockquote>Design pattern Original is used to share a small group of instances accros different places in program.</blockquote>
</sect4>
<sect4>
<title><link linkend="pool">Pool</link></title>
<blockquote>Pool helps to limit the count of instances, which are created. Instances can be reused for many times.</blockquote>
</sect4>
</sect3>
</sect1>
<sect1 id="simple-factory-method">
<title>Simple Factory Method</title>
<sect3>
<title>Definition</title>
<blockquote>Simple (static) factory method is simplified version of <link linkend='factory-method'>factory method</link>. Its interface exports static method instead of constructor. This pattern is used in case we need reference to object, although direct usage of constructor is (due to some reason) not omptimal.</blockquote>
</sect3>
<sect3>
<title>Problem</title>
<itemizedlist>
<listitem>Constructor can't return an value.</listitem>
<listitem>Constructor can't change type of object created.</listitem>
<listitem>It is not safe to call virtual methods inside object's constructor.</listitem>
</itemizedlist>
</sect3>
<sect3>
<title>Solution</title>
<itemizedlist>
<listitem>Static mehod, which returns instance of object's type.</listitem>
<listitem>It is not necessery to create new instance. It can just return instance of an existing object.</listitem>
<listitem>Method can return an instance of subclass.</listitem>
</itemizedlist>
</sect3>
<sect3>
<title>Example</title>
<programlisting language="cpp"><![CDATA[class ExampleClass {
private:
ExampleClass(...) {
// Private constructor
}
public:
static ExampleClass *getInstance(...) {
// Here can be created any subclass of type (determined in run-time)
ExampleClass *inst = new ExampleClass(...);
// Instance initialization
inst->foo(...);
// Return initialized object's instance
return inst;
}
};]]></programlisting>
</sect3>
</sect1>
<sect1 id="immutable-objects">
<title>Immutable objects</title>
<sect3>
<title>Definition</title>
<blockquote>Immutable object is value object, whose value can't be changed.</blockquote>
</sect3>
<sect3>
<title>Problem</title>
<itemizedlist>
<listitem>Value object types can be <emphasis>muttable</emphasis> and <emphasis>immutable</emphasis>.</listitem>
<listitem>Value of muttable object's instance can be changed during the object's life.</listitem>
<listitem>This can bring inconveniences in some cases (e.g. STL containers).</listitem>
</itemizedlist>
</sect3>
<sect3>
<title>Solution</title>
<itemizedlist>
<listitem>Immutalbe value objects should be preffered.</listitem>
<listitem>Attributes, which can influence relational operator's value, should be defined as constant.</listitem>
<listitem>Manipulating methods should return new instance of object with different value, instead of changing its own state.</listitem>
</itemizedlist>
</sect3>
</sect1>
<sect1 id="messenger">
<title>Messenger</title>
<sect3>
<title>Definition</title>
<blockquote>Messanger is used to merge a couple of standalone values into one object. Thus it can be easily transferred between methods. It is useful especially in Java.</blockquote>
</sect3>
<sect3>
<title>Problem</title>
<itemizedlist>
<listitem>Java methods can return only one value.</listitem>
<listitem>Sometimes more than one value is needed to be returned.</listitem>
<listitem>Sometimes more than one value is needed to be stored in container's item.</listitem>
</itemizedlist>
</sect3>
<sect3>
<title>Solution</title>
<itemizedlist>
<listitem>Create <classname>Messenger</classname> class with one attribute for each value.</listitem>
<listitem><classname>Messenger</classname> class is well-knowed for called and calling.</listitem>
<listitem>Attributes can be public or private (with corresponding access methods).</listitem>
</itemizedlist>
</sect3>
</sect1>
<sect1 id="servant">
<title>Servant</title>
<sect3>
<title>Definition</title>
<blockquote><classname>Servant</classname> is class, which defines common functionality for a couple of classes. Its methods accept reference to served class as an parameter.</blockquote>
</sect3>
<sect3>
<title>Problem</title>
<itemizedlist>
<listitem>Common functionality for a couple of classes has to be defined.</listitem>
<listitem>We don't want to implement the same functionality in each class.</listitem>
<listitem>It is good to have common algorithm at one place and class-specific behavior at another place.</listitem>
</itemizedlist>
</sect3>
<sect3>
<title>Solution</title>
<orderedlist>
<listitem>Analyze the set of served classes.</listitem>
<listitem>Create common interface for the set of served classes. Served classes have to implement this interface.</listitem>
<listitem>Define <classname>Servant</classname> class, which methods accepts instance of (served class) interface.</listitem>
<listitem><classname>Servant</classname> class can be knowed either to client, or to served classes (hidden to client).</listitem>
</orderedlist>
</sect3>
<sect3>
<title>Example</title>
<programlisting language="cpp"><![CDATA[// Served class interface
class IServed {
public:
virtual void tool1(...) = 0;
virtual bool tool2(...) = 0;
virtual int tool3(...) = 0;
// ...
};
class ServedClass1: public IServed {
// Interface implementation
// ...
};
class ServedClass2: public IServed {
// Interface implementation
// ...
};
class ServedClass3: public IServed {
// Interface implementation
// ...
};
// Servant uses IServed interface to perform defined actions
class Servant {
public:
void action1(IServed servedClass);
void action2(IServed servedClass);
// ...
};]]></programlisting>
</sect3>
</sect1>
<sect1 id="null-object">
<title>Null object</title>
<sect3>
<title>Definition</title>
<blockquote>Null object is valid object used instead of null-reference. It helps to avoid testing references on null.</blockquote>
</sect3>
<sect3>
<title>Problem</title>
<itemizedlist>
<listitem>Extensive testing reference on null at many places in program.</listitem>
<listitem>Using valid object instead of null-reference can help.</listitem>
</itemizedlist>
</sect3>
<sect3>
<title>Solution</title>
<orderedlist>
<listitem>Define null object's class as subclass of represented class.</listitem>
<listitem>Override default class behavoir as null object's behavior.</listitem>
<listitem>Consider using <link linkend="singleton">singleton</link> to obtain null object's instance.</listitem>
</orderedlist>
</sect3>
</sect1>
<sect1 id="library-class">
<title>Library class</title>
<sect3>
<title>Definition</title>
<blockquote>Library class is wrapper for a couple of static methods. Nobody needs to create its instance, so it is disabled.</blockquote>
</sect3>
<sect3>
<title>Problem</title>
<itemizedlist>
<listitem>Common group of static methods.</listitem>
<listitem>This methods should be encapsulated in a non-instantiable final class.</listitem>
</itemizedlist>
</sect3>
<sect3>
<title>Solution</title>
<itemizedlist>
<listitem>Class containg only static methods.</listitem>
<listitem>Private constructor - to avoid inheritance and instantiation of the class.</listitem>
</itemizedlist>
</sect3>
</sect1>
<!--<sect1 id="enumerated-type">
<title>Enumerated type</title>
<sect3>
<title>Definition</title>
<blockquote>Enumerated type is an object type used instead of language built-in enumerated type.</blockquote>
</sect3>
</sect1>-->
<sect1 id="original">
<title>Original</title>
<sect3>
<title>Definition</title>
<blockquote>Design pattern Original is used to share a small group of instances accros different places in program.</blockquote>
</sect3>
<sect3>
<title>Problem</title>
<itemizedlist>
<listitem>This pattern is used to avoid duplicity of equivalent instances in memory.</listitem>
<listitem>Instead of value can be compared just references to objects.</listitem>
<listitem>In some cases it can be useful to prevent collisions.</listitem>
</itemizedlist>
</sect3>
<sect3>
<title>Solution</title>
<itemizedlist>
<listitem>Leightweight variant of <link linkend="pool">pool</link>.</listitem>
<listitem>Instances are usually stored in map container to decrease latency.</listitem>
</itemizedlist>
</sect3>
</sect1>
<sect1 id="pool">
<title>Pool</title>
<sect3>
<title>Definition</title>
<blockquote>Pool helps to limit the count of instances, which are created. Instances can be reused for many times.</blockquote>
</sect3>
<sect3>
<title>Problem</title>
<itemizedlist>
<listitem>This pattern is useful when creating and destroying of an bojects are expensive operations.</listitem>
<listitem>With this pattern it is possible to reuse already created instances.</listitem>
<listitem>It can also help to reduce the count of created instances.</listitem>
<listitem>Pool can be defined with limited or unlimited capacity.</listitem>
</itemizedlist>
</sect3>
<sect3>
<title>Solution</title>
<orderedlist>
<listitem>Create pool interface (blocking, non-blocking or combined).</listitem>
<listitem>Consider using template to create more generic pool.</listitem>
<listitem>Use static or dynamic container for instances.</listitem>
</orderedlist>
</sect3>
<sect3>
<title>Example</title>
<programlisting language="cpp"><![CDATA[// Pool interface template
template <class T>
class IPool {
public:
virtual T* getIfAvailable() = 0; // Non-blocking variant
virtual T* getWait() = 0; // Blocking variant
virtual void returnBack(T*) = 0; // Return instance back to pool
};]]></programlisting>
</sect3>
</sect1>
</chapter>
</book>
<!--
Local Variables:
mode: xml
sgml-minimize-attributes:nil
sgml-general-insert-case:lower
sgml-indent-step:0
sgml-indent-data:nil
End:
vim:tabstop=2:shiftwidth=2:expandtab
-->