📄 index.html
字号:
<ul>
<li>To sort by ascending salary:
<blockquote>
<pre>class SalaryComparator
{
public:
bool operator()(const Employee& a, const Employee& b)
{
return a.get_salary() < b.get_salary();
}
};</pre>
</blockquote>
</li>
<li>No state</li>
<li>Its sole purpose is to execute a function</li>
</ul>
</font>
<hr><h2><font color="#009999">26.5.1 Function Objects (cont.)</font></h2>
<font size="+1">
<ul>
<li>Client is ignorant of sort implementation</li>
<li>Sort compares using:
<blockquote>
<pre>if (!comp(x, y))
<i>rearrange x and y</i>;</pre>
</blockquote>
</li>
<li><tt>comp</tt> is the object we passed in</li>
<li><tt>comp(x, y)</tt> invokes <tt>SalaryComparator::operator()</tt></li>
<li>Any sense of comparison is now possible</li>
</ul>
</font>
<hr><h2><font color="#009999">26.5.1 Function Objects (cont.)</font></h2>
<font size="+1">
<ul>
<li>Add attributes to extend functionality:
<blockquote>
<pre>class SalaryComparator
{
public:
SalaryComparator(bool a) : ascending(a) {}
bool operator()(const Employee& a, const Employee& b)
{
if (ascending)
return a.get_salary() < b.get_salary();
else
return a.get_salary() > b.get_salary();
}
private:
bool ascending;
}</pre>
</blockquote>
</li>
</ul>
</font>
<hr><h2><font color="#009999">26.5.1 Function Objects (cont.)</font></h2>
<font size="+1">
<ul>
<li>Use
<blockquote><tt>
SalaryComparator reverse_comp(false);
</tt></blockquote>
to sort by decreasing salary
</li>
<li>When creating an unnamed object:
<blockquote><tt>
sort(staff.begin(), staff.end(), SalaryComparator() ):
</tt></blockquote>
</li>
<li>Note the parenthesis after <tt>SalaryComparator</tt></li>
<li>Creates an object using default c'tor</li>
<li>Must pass in an object, not a type</li>
</ul>
<hr><h2><font color="#009999">26.5.2 The STRATEGY Pattern</font></h2>
<font size="+1">
<ul>
<li>Comparator object provides a great deal of flexibility</li>
<li>This is an example of the STRATEGY pattern</li>
<li>Applies whenever you want to allow a client to supply an algorithm</li>
<li>Pattern places the essential steps in a strategy i/f</li>
<li>Vary algorithm by supplying different classes</li>
</ul>
</font>
<hr><h2><font color="#009999">Pattern STRATEGY</font></h2>
<font size="+1">
<hr color="#00ffff" size="6">
<h3><font color="#009999">Context</font></h3>
<ol>
<li>A class (the <i>context</i> class) can benefit from variants on an
algorithm</li>
<li>Clients of the context class can supply custom versions of the
algorithm</li>
</ol>
</font>
<hr><h2><font color="#009999">Pattern STRATEGY</font></h2>
<font size="+1">
<hr color="#00ffff" size="6">
<h3><font color="#009999">Solution</font></h3>
<table cellpadding='5'>
<tr>
<td valign='top'><font size='+1'>
<ol>
<li>Define the <i>strategy i/f</i>, an abstraction for the
algorithm</li>
<li>Concrete strategy classes implement the strategy i/f;
each class defines a version of the algorithm</li>
<li>Client supplies a concrete strategy object to the context class</li>
<li>The context class calls the appropriate functions of the strategy
object</li>
</ol>
</font>
</td>
<td>
<script><!--
image( "un06.png" )
//--></script>
</td>
</tr>
</table>
</font>
<hr><h2><font color='#009999'>26.5.2 The STRATEGY Pattern</font></h2>
<font size="+1">
<ul>
<table border='1' cellpadding='4'>
<tr bgcolor='#00ffff'>
<th width='50%'>Name in Design Pattern</th>
<th width='50%'>Actual Name (String Streams)</th>
</tr>
<tr>
<td align='center'><tt>Context</tt></td>
<td align='center'><tt>sort</tt> function</td>
</tr>
<tr>
<td align='center'><tt>Strategy</tt></td>
<td align='center'>The i/f that <tt>sort</tt> expects <tt>comparator</tt>
to have, i.e., <tt>operator()</tt></td>
</tr>
<tr>
<td align='center'><tt>ConcreteStrategy</tt></td>
<td align='center'>The <tt>comparator</tt> class</td>
</tr>
<tr>
<td align='center'><tt>do_work()</tt></td>
<td align='center'>The <tt>operator()</tt></td>
</tr>
</table>
</ul>
</font>
<hr><h2><font color='#009999'>26.6 The COMPOSITE Pattern</font></h2>
<font size='+1'>
<ul>
<li>Consider the invoice program (chptr 13)</li>
<li>Lists an item, quantity, and unit price</li>
<li>We'd like to add <i>bundles</i> of items</li>
<li>Sol'n: inherit <tt>Bundle</tt> from <tt>Item</tt>
<blockquote>
<pre>class Bundle : public Item
{
. . .
private:
vector<Item*> items;
};</pre>
</blockquote>
</li>
</ul>
</font>
<hr><h2><font color='#009999'>26.6 The COMPOSITE Pattern (cont.)</font></h2>
<font size='+1'>
<ul>
<li>Example of the COMPOSITE pattern</li>
<li>Pimitive objects can be grouped into composite objects</li>
<li>Composites are primitives</li>
<li>E.g., in an HTML editor, elements can be grouped in a table, and the
table is an element</li>
</ul>
</font>
<hr><h2><font color='#009999'>26.6 The COMPOSITE Pattern (cont.)</font></h2>
<font size='+1'>
<ul>
<li>Functions of the composite class must be applied to all primitives, then
combine the results</li>
<li>E.g., compute the price of a bundle:
<blockquote>
<pre>double Bundle::get_unit_price() const
{
double price = 0;
for (int i = 0; i < items.size(); i++)
{
price = price +
( items[i]->get_unit_price()
* items[i]->get_quantity() );
}
return price;
}</pre>
</blockquote>
</li>
</ul>
</font>
<hr><h2><font color="#009999">Pattern COMPOSITE</font></h2>
<font size="+1">
<hr color="#00ffff" size="6">
<h3><font color="#009999">Context</font></h3>
<ol>
<li>Primitive objects can be combined into composite objects</li>
<li>Clients treat a composite as a primitive</li>
</ol>
</font>
<hr><h2><font color="#009999">Pattern COMPOSITE</font></h2>
<font size="+1">
<hr color="#00ffff" size="6">
<h3><font color="#009999">Solution</font></h3>
<ol>
<li>Define a class that is an abstraction for the primitive objects</li>
<li>Both primitive and composite classes inherit from that class</li>
<li>A composite object contains a collection of primitives</li>
<li>An operation on a composite class is applied to its primitives,
results are combined</li>
</ol>
</font>
<hr><h2><font color="#009999">Pattern COMPOSITE</font></h2>
<font size="+1">
<hr color="#00ffff" size="6">
<h3><font color="#009999">Solution (cont.)</font></h3>
<script><!--
image( "un07.png" )
//--></script>
</font>
<hr><h2><font color='#009999'>26.6 The COMPOSITE Pattern (cont.)</font></h2>
<font size='+1'>
<ul>
<table border='1' cellpadding='4'>
<tr bgcolor='#00ffff'>
<th width='50%'>Name in Design Pattern</th>
<th width='50%'>Actual Name (String Streams)</th>
</tr>
<tr>
<td align='center'><tt>Primitive</tt></td>
<td align='center'><tt>Item</tt></td>
</tr>
<tr>
<td align='center'><tt>Composite</tt></td>
<td align='center'><tt>Bundle</tt></td>
</tr>
<tr>
<td align='center'><tt>op()</tt></td>
<td align='center'><tt>get_unit_price</tt></td>
</tr>
</table>
</ul>
</font>
<hr><h2><font color="#009999">26.7 Case Study: Putting Patterns to Work
</font></h2>
<font size="+1">
<ul>
<li>Refine the invoice printing program of Chptr 13</li>
<li>Include <tt>Bundle</tt>, from above</li>
<li>Make changes to employ several other patterns</li>
</ul>
</font>
<hr><h2><font color="#009999">26.7 Case Study: Putting Patterns to Work (cont.)
</font></h2>
<font size="+1">
<ul>
<li>General <tt>Item</tt> abstract base class:
<blockquote>
<pre>class Item
{
public:
virtual double get_unit_price() const = 0;
virtual int get_quantity() const = 0;
virtual string get_description() const = 0;
double get_total_price() const;
. . .
};</pre>
</blockquote>
</li>
</ul>
</font>
<hr><h2><font color="#009999">26.7 Case Study: Putting Patterns to Work (cont.)
</font></h2>
<font size="+1">
<ul>
<li>Derived classes implement the virtual functions</li>
<li><tt>get_total_price</tt> is defined in the <tt>Item</tt> class:
<blockquote>
<pre>double Item::get_total_price() const
{
return get_quantity() * get_unit_price();
}</pre>
</blockquote>
</li>
<li>A generic item can't compute quantity or unit price, but it knows that
the total price is their product - TEMPLATE METHOD pattern</li>
</ul>
</font>
<hr><h2><font color="#009999">26.7 Case Study: Putting Patterns to Work (cont.)
</font></h2>
<font size="+1">
<ul>
<li>We want to add simple products to an invoice</li>
<li>Invoice stores <tt>Item</tt>s, not <tt>Product</tt>s</li>
<li>Use ADAPTER pattern, define <tt>ProductItem</tt> that wraps a
<tt>Product</tt> in an <tt>Item</tt> i/f:
<script><!--
image( "fig04.png" )
//--></script>
</li>
</ul>
</font>
<hr><h2><font color="#009999">26.7 Case Study: Putting Patterns to Work (cont.)
</font></h2>
<font size="+1">
<ul>
<blockquote>
<pre>class ProductItem : public Item
{
public:
ProductItem(Product p);
virtual double get_unit_price() const;
virtual string get_description() const;
private:
Product prod;
};</pre>
</blockquote>
</ul>
</font>
<hr><h2><font color="#009999">26.7 Case Study: Putting Patterns to Work (cont.)
</font></h2>
<font size="+1">
<ul>
<li>Adapter methods call appropriate <tt>Product</tt> methods:
<blockquote>
<pre>double ProductItem::get_unit_price() const
{
return prod.get_price();
}</pre>
</blockquote>
</li>
</ul>
</font>
<hr><h2><font color="#009999">26.7 Case Study: Putting Patterns to Work (cont.)
</font></h2>
<font size="+1">
<ul>
<li><tt>Invoice</tt> holds a collection of items:
<blockquote>
<pre>class Invoice
{
public:
void add(Item* item)
{
items.push_back(item);
}
. . .
private:
vector<Item*> items;
};</pre>
</blockquote>
</li>
</ul>
</font>
<hr><h2><font color="#009999">26.7 Case Study: Putting Patterns to Work (cont.)
</font></h2>
<font size="+1">
<ul>
<li><tt>Invoice</tt> clients my want to inspect the items</li>
<li><tt>Invoice</tt> doesn't want to reveal its details - they may change</li>
<li>Sol'n - follow the ITERATOR pattern</li>
<li>Design an iterator class:</li>
</ul>
</font>
<hr><h2><font color="#009999">26.7 Case Study: Putting Patterns to Work (cont.)
</font></h2>
<font size="+1">
<ul>
<blockquote>
<pre>class ItemIterator
{
public:
. . .
bool is_done() const;
void next();
Item* get() const;
private:
vector<Item*>& items;
int pos;
};</pre>
</blockquote>
</ul>
</font>
<hr><h2><font color="#009999">26.7 Case Study: Putting Patterns to Work (cont.)
</font></h2>
<font size="+1">
<ul>
<li>These functions access a reference to the original vector:
<blockquote>
<pre>Item* ItemIterator::get() const
{
if (pos < items.size())
return items[pos];
else
return NULL;
}</pre>
</blockquote>
</ul>
</font>
<hr><h2><font color="#009999">26.7 Case Study: Putting Patterns to Work (cont.)
</font></h2>
<font size="+1">
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -