⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 chap11.htm

📁 This is the second part of that lab manual to teach you how to make real-time programme and how to d
💻 HTM
📖 第 1 页 / 共 5 页
字号:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<!--
This document was converted from RTF source: 
By rtftohtml 4.19
See http://www.sunpack.com/RTF
Filename:C:\TEMP\TicV2\html\TicV2.rtf
Application Directory:C:\TOOLS\RTF2HTML\
Subject:
Author:Bruce Eckel
Operator:Bruce Eckel
Document Comments:
Version Comments:
Comments:
Keywords:
Translation Date:09/26/2001
Translation Time:08:32:36
Translation Platform:Win32
Number of Output files:19
This File:C:\TEMP\TicV2\html\Chap11.htm
SplitDepth=1
SkipNavPanel=1
SkipLeadingToc=1
SkipTrailingToc=1
GenContents=1
GenFrames=1
GenIndex=1
-->
<HEAD lang="en"><META http-equiv="Content-Type" content="text/html">
<TITLE>11: Design patterns</TITLE>
</HEAD>

<BODY  BGCOLOR="#FFFFFF"><DIV ALIGN="CENTER">
  <a href="http://www.MindView.net">
  <img src="mindview.gif" alt="MindView Inc." BORDER = "0"></a>
  <CENTER>
    <FONT FACE="Verdana, Tahoma, Arial, Helvetica, Sans" size = "-1">
    [ <a href="README.txt">Viewing Hints</a> ]
    [ <a href="RevisionHistory.htm">Revision History</a> ]
    [ <a href="http://www.mindview.net/Books/TICPP/ThinkingInCPP2e.html">Book Home Page</a> ]
    [ <a href="http://www.mindview.net/Etc/MailingList.html">Free Newsletter</a> ] <br>
    [ <a href="http://www.mindview.net/Seminars">Seminars</a> ]
    [ <a href="http://www.mindview.net/CDs">Seminars on CD ROM</a> ]
    [ <a href="http://www.mindview.net/Services">Consulting</a> ]
    </FONT>
  <H2><FONT FACE="Verdana, Tahoma, Arial, Helvetica, Sans">
  Thinking in C++, 2nd edition, Volume 2<br>
  <small>Revision 4.0</small></FONT></H2>
  <H3><FONT FACE="Verdana, Tahoma, Arial, Helvetica, Sans">
  by Bruce Eckel &amp; Chuck Allison<br>&copy;2001 MindView, Inc.</FONT></H3>
  
    <FONT FACE="Verdana, Tahoma, Arial, Helvetica, Sans" size = "-1">
     [ <a href="Chap10.htm">Previous Chapter</a> ] 
    
    [ <a href="SimpCont.htm">Short TOC</a> ] 
    [ <a href="Contents.htm">Table of Contents</a> ] 
  
        [ <a href="DocIdx.htm">Index</a> ]
        
     [ <a href="AppendA.htm">Next Chapter</a> ] 
    </FONT>
    
  </CENTER>
  </P></DIV><A NAME="_Toc312374156"></A><A NAME="_Toc375545412"></A><A NAME="_Toc407441460"></A><A NAME="_Toc408018793"></A><A NAME="DesignPatterns"></A><A NAME="_Toc519042116"></A><A NAME="Heading325"></A><FONT FACE = "Verdana, Tahoma, Arial, Helvetica, Sans"><H1 ALIGN="LEFT">
11: Design patterns</H1></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Verdana" SIZE=4> &#8220;... describes a problem
which occurs over and over again in our environment, and then describes the core
of the solution to that problem, in such a way that you can use this solution a
million times over, without ever doing it the same way twice&#8221;  &#8211;
Christopher Alexander</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Verdana" SIZE=4>This chapter introduces the
important and yet non-traditional &#8220;patterns&#8221; approach to program
design. </FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">[[ Much of the prose in this chapter
still needs work, but the examples all compile. Also, more patterns and examples
are forthcoming ]]</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Probably the most important step forward
in object-oriented design is the &#8220;design patterns&#8221; movement,
chronicled in <A NAME="Index642"></A><A NAME="Index643"></A><I>Design
Patterns</I>, by Gamma, Helm, Johnson &amp; Vlissides (Addison-Wesley
1995).</FONT><A NAME="fnB28" HREF="#fn28">[28]</A><FONT FACE="Georgia"> That
book shows 23 different solutions to particular classes of problems. In this
chapter, the basic concepts of design patterns will be introduced along with
examples. This should whet your appetite to read <I>Design Patterns</I> (a
source of what has now become an essential, almost mandatory, vocabulary for OOP
programmers).</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The latter part of this chapter contains
an example of the design evolution process, starting with an initial solution
and moving through the logic and process of evolving the solution to more
appropriate designs. The program shown (a trash recycling simulation) has
evolved over time, and you can look at that evolution as a prototype for the way
your own design can start as an adequate solution to a particular problem and
evolve into a flexible approach to a class of
problems.</FONT><A NAME="_Toc408018794"></A><A NAME="_Toc519042117"></A><BR></P></DIV>
<A NAME="Heading326"></A><FONT FACE = "Verdana, Tahoma, Arial, Helvetica, Sans"><H2 ALIGN="LEFT">
The pattern concept</H2></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Initially, you can think of a pattern as
an especially clever and insightful way of solving a particular class of
problems. That is, it looks like a lot of people have worked out all the angles
of a problem and have come up with the most general, flexible solution for it.
The problem could be one you have seen and solved before, but your solution
probably didn&#8217;t have the kind of completeness you&#8217;ll see embodied in
a pattern.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Although they&#8217;re called
&#8220;design patterns,&#8221; they really aren&#8217;t tied to the realm of
design. A pattern seems to stand apart from the traditional way of thinking
about analysis, design, and implementation. Instead, a pattern embodies a
complete idea within a program, and thus it can sometimes appear at the analysis
phase or high-level design phase. This is interesting because a pattern has a
direct implementation in code and so you might not expect it to show up before
low-level design or implementation (and in fact you might not realize that you
need a particular pattern until you get to those phases).</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The basic concept of a pattern can also
be seen as the basic concept of program design: adding layers of
<A NAME="Index644"></A><A NAME="Index645"></A>abstraction. Whenever you abstract
something you&#8217;re isolating particular details, and one of the most
compelling motivations behind this is to <I>separate things that change from
things that stay the same</I>. Another way to put this is that once you find
some part of your program that&#8217;s likely to change for one reason or
another, you&#8217;ll want to keep those changes from propagating other
modifications throughout your code. Not only does this make the code much
cheaper to maintain, but it also turns out that it is usually simpler to
understand (which results in lowered costs).</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Often, the most difficult part of
developing an elegant and cheap-to-maintain design is in discovering what I call
&#8220;the
<A NAME="Index646"></A><A NAME="Index647"></A><A NAME="Index648"></A>vector of
change.&#8221; (Here, &#8220;vector&#8221; refers to the maximum gradient and
not a container class.) This means finding the most important thing that changes
in your system, or put another way, discovering where your greatest cost is.
Once you discover the vector of change, you have the focal point around which to
structure your design.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">So the goal of design patterns is to
isolate changes in your code. If you look at it this way, you&#8217;ve been
seeing some design patterns already in this book. For example,
<A NAME="Index649"></A>inheritance could be thought of as a design pattern
(albeit one implemented by the compiler). It allows you to express differences
in behavior (that&#8217;s the thing that changes) in objects that all have the
same interface (that&#8217;s what stays the same).
<A NAME="Index650"></A>Composition could also be considered a pattern, since it
allows you to change &#8211; dynamically or statically &#8211; the objects that
implement your class, and thus the way that class works. Normally, however,
features that are directly supported by a programming language are not
classified as design patterns.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">You&#8217;ve also already seen another
pattern that appears in <I>Design Patterns</I>: the
<A NAME="Index651"></A><I>iterator</I>. This is the fundamental tool used in the
design of the STL; it hides the particular implementation of the container as
you&#8217;re stepping through and selecting the elements one by one. The
iterator allows you to write generic code that performs an operation on all of
the elements in a range without regard to the container that holds the range.
Thus your generic code can be used with any container that can produce
iterators.</FONT><A NAME="_Toc408018795"></A><A NAME="_Toc519042118"></A><BR></P></DIV>
<A NAME="Heading327"></A><FONT FACE = "Verdana, Tahoma, Arial, Helvetica, Sans"><H3 ALIGN="LEFT">
The singleton</H3></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Possibly the simplest design pattern is
the <A NAME="Index652"></A><I>singleton</I>, which is a way to provide one and
only one instance of an object:</FONT><BR></P></DIV>

<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#009900>//: C11:SingletonPattern.cpp</font>
<font color=#009900>//{L} ../TestSuite/Test</font>
#include &lt;iostream&gt;
<font color=#0000ff>using</font> <font color=#0000ff>namespace</font> std;

<font color=#0000ff>class</font> Singleton {
  <font color=#0000ff>static</font> Singleton s;
  <font color=#0000ff>int</font> i;
  Singleton(<font color=#0000ff>int</font> x) : i(x) { }
  <font color=#0000ff>void</font> <font color=#0000ff>operator</font>=(Singleton&amp;);
  Singleton(<font color=#0000ff>const</font> Singleton&amp;);
<font color=#0000ff>public</font>:
  <font color=#0000ff>static</font> Singleton&amp; getHandle() {
    <font color=#0000ff>return</font> s;
  }
  <font color=#0000ff>int</font> getValue() { <font color=#0000ff>return</font> i; }
  <font color=#0000ff>void</font> setValue(<font color=#0000ff>int</font> x) { i = x; }
};

Singleton Singleton::s(47);

<font color=#0000ff>int</font> main() {
  Singleton&amp; s = Singleton::getHandle();
  cout &lt;&lt; s.getValue() &lt;&lt; endl;
  Singleton&amp; s2 = Singleton::getHandle();
  s2.setValue(9);
  cout &lt;&lt; s.getValue() &lt;&lt; endl;
} <font color=#009900>///:~</font></PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The key to creating a singleton is to
prevent the client programmer from having any way to create an object except the
ways you provide. To do this, you must declare all
<A NAME="Index653"></A><A NAME="Index654"></A>constructors as <B>private</B>,
and you must<B> </B>create at least one constructor to prevent the compiler from
<A NAME="Index655"></A><A NAME="Index656"></A>synthesizing a default constructor
for you.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">At this point, you decide how
you&#8217;re going to create your object. Here, it&#8217;s created statically,
but you can also wait until the client programmer asks for one and create it on
demand. In any case, the object should be stored privately. You provide access
through public methods. Here, <B>getHandle(&#160;)</B> produces a reference to
the <B>Singleton</B> object. The rest of the interface (<B>getValue(&#160;)</B>
and <B>setValue(&#160;)</B>) is the regular class interface.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Note that you aren&#8217;t restricted to
creating only one object. This technique easily supports the creation of a
limited pool of objects. In that situation, however, you can be confronted with
the problem of sharing objects in the pool. If this is an issue, you can create
a solution involving a check-out and check-in of the shared
objects.</FONT><BR></P></DIV>
<A NAME="Heading328"></A><FONT FACE = "Verdana, Tahoma, Arial, Helvetica, Sans"><H4 ALIGN="LEFT">
Variations on singleton</H4></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Any static member object inside a class
is an expression of singleton: one and only one will be made. So in a sense, the
language has direct support for the idea; we certainly use it on a regular
basis. However, there&#8217;s a problem associated with static objects (member
or not), and that&#8217;s the order of initialization, as described in Volume 1
of this book. If one static object depends on another, it&#8217;s important that
the order of initialization proceed correctly.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">In Volume 1, you were shown how a static
object defined inside a function can be used to control initialization order.
This delays the initialization of the object until the first time the function
is called. If the function returns a reference to the static object, it gives
you the effect of a singleton while removing much of the worry of static
initialization. For example, suppose you want to create a logfile upon the first
call to a function which returns a reference to that logfile. This header file
will do the trick:</FONT><BR></P></DIV>

<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#009900>//: C11:LogFile.h</font>
#ifndef LOGFILE_H
#define LOGFILE_H
#include &lt;fstream&gt;

std::ofstream&amp; logfile();

#endif <font color=#009900>// LOGFILE_H ///:~</font></PRE></FONT></BLOCKQUOTE>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -