Files
doc-fr/reference/objaggregation/examples.xml
Yannick Torres 3d20fe648b &php; => PHP
git-svn-id: https://svn.php.net/repository/phpdoc/fr/trunk@261459 c90b9560-bf6c-de11-be94-00142212c4b1
2008-06-21 20:51:48 +00:00

458 lines
12 KiB
XML

<?xml version="1.0" encoding="iso-8859-1"?>
<!-- $Revision: 1.2 $ -->
<!-- EN-Revision: 1.3 Maintainer: yannick Status: ready -->
<!-- Reviewed: yes -->
<appendix xml:id="objaggregation.examples">
&reftitle.examples;
<section xml:id="objaggregation.examples.association">
<title>Exemples d'agrégation d'objets</title>
<para>
Une <emphasis>Association</emphasis> est une combinaison d'éléments construits
indépendamment et visibles à l'extérieur. Lorsque nous associons des classes ou
objets, chacun garde une référence à l'autre partie de l'association. Lorsque
nous associons des classes statiquement, une classe contient une référence
à une instance de l'autre classe. Par exemple :
<example>
<title>Association de classes</title>
<programlisting role="php">
<![CDATA[
<?php
class MyDateTime {
function MyDateTime()
{
// constructeur vide
}
function now()
{
return date("Y-m-d H:i:s");
}
}
class Report {
var $_dt;
// autres propriétés ...
function Report()
{
$this->_dt = new MyDateTime();
// initialisation du code ...
}
function generateReport()
{
$dateTime = $this->_dt->now();
// autre code ...
}
// autres méthodes ...
}
$rep = new Report();
?>
]]>
</programlisting>
</example>
Nous pouvons aussi associer des instances dynamiquement, en passant une référence au
constructeur (ou par une autre méthode), ce qui permet de gérer dynamiquement
l'association entre les objets. Nous allons modifier l'exemple ci-dessus pour
illustrer ce point :
<example>
<title>Association d'objets</title>
<programlisting role="php">
<![CDATA[
<?php
class MyDateTime {
// identique au précédent exemple
}
class MyDateTimePlus {
var $_format;
function MyDateTimePlus($format="Y-m-d H:i:s")
{
$this->_format = $format;
}
function now()
{
return date($this->_format);
}
}
class Report {
var $_dt; // Nous allons garder la référence à DateTime ici
// autre propriété ...
function Report()
{
// initialisation
}
function setMyDateTime(&$dt)
{
$this->_dt =& $dt;
}
function generateReport()
{
$dateTime = $this->_dt->now();
// autre code ...
}
// autres méthodes ...
}
$rep = new Report();
$dt = new MyDateTime();
$dtp = new MyDateTimePlus("l, F j, Y (h:i:s a, T)");
// Génération du rapport avec une simple date
$rep->setMyDateTime(&$dt);
echo $rep->generateReport();
// plus loin dans le code ...
// Génération du rapport avec une date designée
$rep->setMyDateTime(&$dtp);
$output = $rep->generateReport();
// sauvegarde pour affichage dans la base
// ... etc ...
?>
]]>
</programlisting>
</example>
</para>
<para>
L'<emphasis>agrégation</emphasis>, d'un autre coté, implique
l'encapsulation et le masquage des parties de la combinaison. Nous
pouvons agréger des classes en utilisant une méthode statique, grâce
aux sous-classes (mais PHP ne supporte pas bien les sous-classes), et,
dans ce cas, la définition de la classe agrégée n'est pas accessible,
sauf via les méthodes de la classe contenant. L'agrégation d'instances
(agrégation d'objets) implique la création dynamique de sous-objets
à l'intérieur d'un autre objet et, dans le même temps, l'extension des
capacités de l'objet principal (en terme de méthodes accessibles).
</para>
<para>
L'agrégation d'objets est une méthode naturelle pour représenter des
relations de type tout-partie (par exemple, une molécule est une agrégation
d'atomes), ou bien peut être utilisée pour obtenir un effet équivalent
à l'héritage multiple, sans avoir à lier plusieurs classes et leurs
interfaces. En fait, les agrégations d'objets sont plus souples,
car nous pouvons alors sélectionner les méthodes et les propriétés qui
sont transmises à l'objet agrégé.
</para>
</section>
<section xml:id="objaggregation.examples2">
&reftitle.examples;
<para>
Nous définissons trois classes, qui implémentent chacune une méthode de stockage
différente :
</para>
<para>
<example>
<title>storage_classes.inc</title>
<programlisting role="php">
<![CDATA[
<?php
class FileStorage {
var $data;
function FileStorage($data)
{
$this->data = $data;
}
function write($name)
{
$fp = fopen(name, "w");
fwrite($fp, $this->data);
fclose($data);
}
}
class WDDXStorage {
var $data;
var $version = "1.0";
var $_id; // variable "privée"
function WDDXStorage($data)
{
$this->data = $data;
$this->_id = $this->_genID();
}
function store()
{
if ($this->_id) {
$pid = wddx_packet_start($this->_id);
wddx_add_vars($pid, "this->data");
$packet = wddx_packet_end($pid);
} else {
$packet = wddx_serialize_value($this->data);
}
$dbh = dba_open("varstore", "w", "gdbm");
dba_insert(md5(uniqid("", true)), $packet, $dbh);
dba_close($dbh);
}
// méthode privée
function _genID()
{
return md5(uniqid(rand(), true));
}
}
class DBStorage {
var $data;
var $dbtype = "mysql";
function DBStorage($data)
{
$this->data = $data;
}
function save()
{
$dbh = mysql_connect();
mysql_select_db("storage", $dbh);
$serdata = serialize($this->data);
mysql_query("insert into vars ('$serdata',now())", $dbh);
mysql_close($dbh);
}
}
?>
]]>
</programlisting>
</example>
</para>
<para>
Puis, nous "instantions" quelques objets issus de ces classes, et nous
réalisons des agrégations et désagrégations, tout en affichant
quelques résultats :
</para>
<para>
<example>
<title>test_aggregation.php</title>
<programlisting role="php">
<![CDATA[
<?php
include "storageclasses.inc";
// quelques utilitaires
function p_arr($arr)
{
foreach ($arr as $k => $v)
$out[] = "\t$k => $v";
return implode("\n", $out);
}
function object_info($obj)
{
$out[] = "Classe : " . get_class($obj);
foreach (get_object_vars($obj) as $var=>$val) {
if (is_array($val)) {
$out[] = "propriété : $var (array)\n" . p_arr($val);
} else {
$out[] = "propriété : $var = $val";
}
}
foreach (get_class_methods($obj) as $method) {
$out[] = "méthode : $method";
}
return implode("\n", $out);
}
$data = array(M_PI, "kludge != cruft");
// créons quelques objets simples
$fs = new FileStorage($data);
$ws = new WDDXStorage($data);
// affichons des informations sur ces objets
echo "\$fs object\n";
echo object_info($fs) . "\n";
echo "\n\$ws object\n";
echo object_info($ws) . "\n";
// maintenant, quelques agrégations
echo "\nagrégeons \$fs avec la classe WDDXStorage\n";
aggregate($fs, "WDDXStorage");
echo "L'objet \$fs \n";
echo object_info($fs) . "\n";
echo"\nagrégeons le résultat avec la classe DBStorage \n";
aggregate($fs, "DBStorage");
echo "L'objet \$fs \n";
echo object_info($fs)."\n";
echo "\nEt finalement, désagrégeons WDDXStorage\n";
deaggregate($fs, "WDDXStorage");
echo "L'objet \$fs \n";
echo object_info($fs) . "\n";
?>
]]>
</programlisting>
</example>
</para>
<para>
Etudions maintenant le résultat du script pour comprendre les effets
secondaires et les limitations des agrégations d'objets en PHP.
D'abord, nous avons créé <varname>$fs</varname> et <varname>$ws</varname>
et ils fournissent le bon résultat (suivant la définition de leur classe).
Notez que dans le but de l'agrégation d'objets,
<emphasis>les éléments privés d'une classe ou
d'un objet doivent commencer par un souligné ("_")</emphasis>,
même s'il n'y a pas de distinction réelle entre un objet
privé et un objet public.
</para>
<para>
<informalexample>
<programlisting>
<![CDATA[
$fs object
Classe : filestorage
propriété : data (array)
0 => 3.1415926535898
1 => kludge != cruft
méthode : filestorage
méthode : write
$ws object
Classe : wddxstorage
propriété : data (array)
0 => 3.1415926535898
1 => kludge != cruft
propriété : version = 1.0
propriété: _id = ID::9bb2b640764d4370eb04808af8b076a5
méthode : wddxstorage
méthode : store
méthode : _genid
]]>
</programlisting>
</informalexample>
</para>
<para>
Nous agrégeons alors <varname>$fs</varname> avec la classe
<classname>WDDXStorage</classname>, et nous affichons les informations.
Nous pouvons aussi voir que même si l'objet <varname>$fs</varname>
est toujours du type <classname>FileStorage</classname>, il a maintenant
la propriété <varname>$version</varname>, et la méthode
<function>store</function>, qui sont définies dans
<classname>WDDXStorage</classname>. Une chose importante à noter est
que les éléments privés n'ont pas été
agrégés, même s'ils sont présents dans l'objet
<varname>$ws</varname>. Un autre absent est le constructeur de
<classname>WDDXStorage</classname>, qu'il n'est pas logique d'agréger.
</para>
<para>
<informalexample>
<programlisting>
<![CDATA[
agrégeons \$fs avec la classe WDDXStorage
L'objet $fs
Classe : filestorage
propriété : data (array)
0 => 3.1415926535898
1 => kludge != cruft
propriété : version = 1.0
méthode : filestorage
méthode : write
méthode : store
]]>
</programlisting>
</informalexample>
</para>
<para>
Le processus d'agrégation est cumulatif, ce qui fait que
lorsque nous agrégeons <varname>$fs</varname> avec la classe
<classname>DBStorage</classname>, nous générons un objet qui
peut utiliser n'importe laquelle des méthodes de stockage de
ces classes.
</para>
<para>
<informalexample>
<programlisting>
<![CDATA[
agrégeons le résultat avec la classe DBStorage
L'objet $fs
Classe : filestorage
propriété : data (array)
0 => 3.1415926535898
1 => kludge != cruft
propriété : version = 1.0
propriété : dbtype = mysql
méthode : filestorage
méthode : write
méthode : store
méthode : save
]]>
</programlisting>
</informalexample>
</para>
<para>
Finalement, de la même façon que nous avons agrégé
les méthodes et propriétés dynamiquement, nous pouvons aussi
les désagréger. Si nous désagrégeons
la classe <classname>WDDXStorage</classname> de l'objet <varname>$fs</varname>,
nous allons obtenir :
</para>
<para>
<informalexample>
<programlisting>
<![CDATA[
Et finalement, désagrégeons WDDXStorage
L'objet $fs
Classe : filestorage
propriété : data (array)
0 => 3.1415926535898
1 => kludge != cruft
propriété : dbtype = mysql
méthode : filestorage
méthode : write
méthode : save
]]>
</programlisting>
</informalexample>
</para>
<para>
Un point que nous n'avons pas mentionné ci-dessus et que l'agrégation ne va
pas écraser les méthodes ou propriétés déjà existantes dans l'objet principal.
Par exemple, la classe <classname>FileStorage</classname> définit une
propriété <varname>$data</varname>, et la classe
<classname>WDDXStorage</classname> aussi. Mais cette dernière ne sera pas
impliquée dans l'agrégation.
</para>
</section>
</appendix>
<!-- Keep this comment at the end of the file
Local variables:
mode: sgml
sgml-omittag:t
sgml-shorttag:t
sgml-minimize-attributes:nil
sgml-always-quote-attributes:t
sgml-indent-step:1
sgml-indent-data:t
indent-tabs-mode:nil
sgml-parent-document:nil
sgml-default-dtd-file:"../../../manual.ced"
sgml-exposed-tags:nil
sgml-local-catalogs:nil
sgml-local-ecat-files:nil
End:
vim600: syn=xml fen fdm=syntax fdl=2 si
vim: et tw=78 syn=sgml
vi: ts=1 sw=1
-->