Sovitin (suunnittelukuvio)
Kokeneet kirjoittajat eivät ole vielä tarkistaneet sivun nykyistä versiota, ja se voi poiketa merkittävästi 9. maaliskuuta 2016 tarkistetusta
versiosta . tarkastukset vaativat
47 muokkausta .
Sovitin |
---|
Sovitin |
Mallin rakennenäkymäsovitin |
Tyyppi |
rakenteellinen |
Tarkoitus |
järjestää sellaisen objektin toimintojen käyttö, joka ei ole muokattavissa erityisesti luodun käyttöliittymän kautta (tuo luokan (tai useamman luokan) rajapinnan vaaditun tyyppiseen käyttöliittymään) |
Pätee tapauksissa |
järjestelmä tukee vaadittuja tietoja ja käyttäytymistä, mutta sillä on sopimaton käyttöliittymä. Yleisin Adapter-mallin käyttö on silloin, kun halutaan luoda luokka, joka on peräisin juuri määritellystä tai jo olemassa olevasta abstraktista luokasta. |
Plussat |
- ulkoisten luokkien (komponenttien, kirjastojen) toteutuksen kapselointi, järjestelmästä tulee riippumaton ulkoisten luokkien rajapinnasta;
- siirtyminen muiden ulkoisten luokkien käyttöön ei vaadi itse järjestelmän uudelleenkäsittelyä, riittää yhden luokan toteuttaminen Adapter.
|
Aiheeseen liittyvät mallit |
Julkisivu , sisustaja |
Kuvattu suunnittelukuvioissa |
Joo |
Adapteri ( eng. Adapter ) on rakennesuunnittelumalli , joka on suunniteltu organisoimaan kohteen toimintojen käyttö, jota ei voi muokata erityisesti luodun käyttöliittymän kautta . Toisin sanoen se on rakennesuunnittelumalli, jonka avulla objektit, joilla on yhteensopimattomat rajapinnat, voivat toimia yhdessä.
Tärkeimmät ominaisuudet
Haaste
Järjestelmä tukee vaadittuja tietoja ja käyttäytymistä, mutta siinä on sopimaton käyttöliittymä.
Ratkaisu
Sovitin mahdollistaa kääreluokan [1] luomisen vaaditulla liitännällä.
Jäsenet
Luokka Adapterkartoittaa luokkarajapinnan Adapteeluokkaliittymään Target(jonka luokka toteuttaa Adapter). Tämä sallii objektin Clientkäyttää objektia Adaptee(sovittimen kautta Adapter) ikään kuin se olisi luokan esiintymä Target.
Siten käyttää luokan toteuttamaa Clientkäyttöliittymää , joka ohjaa kutsun osoitteeseen .
TargetAdapterAdaptee
Seuraukset
Sovitinmalli mahdollistaa olemassa olevien objektien sisällyttämisen uusiin objektirakenteisiin riippumatta niiden rajapintojen eroista.
Huomautuksia ja kommentteja
Sovitinmallin avulla suunnitteluprosessi voi jättää huomioimatta mahdolliset erot olemassa olevien luokkien rajapinnoissa. Jos on olemassa luokka, jolla on vaaditut menetelmät ja ominaisuudet (ainakin käsitteellisesti), niin tarvittaessa voit aina käyttää Adapter-mallia saadakseen sen rajapinnan haluttuun muotoon.
Sovittimen lähellä on julkisivukuvio , jota ei aina ole mahdollista erottaa toisistaan [2] .
Mallin käyttäminen
Tyypillinen esimerkki Adapter-mallin käytöstä on luokkien luominen, jotka johtavat yhteen PHP -kielifunktion käyttöliittymään, joka tarjoaa pääsyn erilaisiin tietokantajärjestelmiin [3] .
Ratkaisu tähän ongelmaan käyttämällä sovitinmallia on esitetty kuvassa.
Toteutus
Jo olemassa olevan luokan sisällyttäminen toisella luokalla. Sisältävän luokan käyttöliittymä päivitetään vastaamaan uusia vaatimuksia ja sen menetelmien kutsut muunnetaan kutsuiksi sisällytetyn luokan menetelmille.
Käyttöönoton vaiheet
- Varmista, että sinulla on kaksi luokkaa, joiden liitännät eivät ole yhteensopivia:
- hyödyllinen palvelu - hyödyllisyysluokka, jota et voi muuttaa (se on joko kolmannen osapuolen tai muu koodi riippuu siitä);
- yksi tai useampi asiakas - olemassa olevat sovellusluokat, jotka eivät ole yhteensopivia palvelun kanssa hankalan tai yhteensopimattoman käyttöliittymän vuoksi.
- Kuvaa asiakasliittymä, jonka kautta sovellusluokat voivat käyttää palveluluokkaa.
- Luo sovitinluokka toteuttamalla tämä käyttöliittymä.
- Aseta sovittimeen kenttä, joka tallentaa viittauksen palveluobjektiin. Yleensä tämä kenttä täytetään sovittimen rakentajalle välitetyllä objektilla. Yksinkertaisen mukautuksen tapauksessa tämä objekti voidaan välittää parametreina sovitinmenetelmille.
- Toteuta kaikki asiakasliittymämenetelmät sovittimessa. Sovittimen on delegoitava suurin osa työstä palvelulle.
- Sovelluksen tulisi käyttää sovitinta vain asiakasliittymän kautta. Tämä helpottaa sovittimien vaihtamista ja lisäämistä tulevaisuudessa.
Ruby
Esimerkki
Rubyssa
moduuli AdapterPattern
# Sallii asiakkaan käyttää sovittimia yhteensopimattomien liitäntöjen kanssa sovittimien kautta, joissa on käyttöliittymä Kohde
# Adaptee
luokka Twitter
def twit
laittaa " Twit julkaistiin"
loppuun
# Sopeutuva
luokka Facebook
def post
laittaa "Facebook- viesti julkaistiin"
loppuun
#
Kohdemoduuli WebServiceInterface
def send_message
nosta NotImplementedError
end
end
#
Sovitinluokka TwitterAdapter sisältää WebServiceInterfacen
def initialize
@webservice = Twitter . uusi
loppu
def send_message
@webservice . twiitin
loppu
_
# Adapteriluokka FacebookAdapter sisältää WebServiceInterfacen
def initialize
@webservice = Facebook . uusi
loppu
def send_message
@webservice . post
loppu
loppu
# Asiakasluokan
Viesti attr_accessor : webservice
def send
@webservice . send_message
end
end
itsevarmasti . _ run laittaa '=> sovittimen'
viesti = Viesti . Uusi
viestiä . verkkopalvelu = TwitterAdapter . uusi
viesti . lähettää
viestiä . verkkopalvelu = FacebookAdapter . uusi
viesti . lähettää
laittaa ' '
lopun
Adapter Pattern . juosta
Java - periytyminen
Java - esimerkki (perinnön kautta)
// Kohde
julkinen käyttöliittymä Päällikkö
{
public Object makeBreakfast ();
julkinen Object makeLunch ();
julkinen Object makeDinner ();
}
// Adaptee
public class Putkimies
{
public Object getScrewNut ()
{ ... }
public Object getPipe ()
{ ... }
public Object getGasket ()
{ ... }
}
// Adapter
public class ChiefAdapter laajenee Putkimies toteuttaa Päällikkö
{
public Object makeBreakfast ()
{
return getGasket ();
}
public Object makeLunch ()
{
return getPipe ();
}
public Object makeDinner ()
{
return getScrewNut ();
}
}
// Client
public class Asiakas
{
public static void eat ( Object dish )
{ ... }
public static void main ( String [] args )
{
Chief ch = new ChiefAdapter ();
Objektilautanen = ch . _ teeAamiainen (); syödä ( ruokalaji ); ruokalaji = ch . teeLounas (); syödä ( ruokalaji ); ruokalaji = ch . teeDinner (); syödä ( ruokalaji ); soita ambulanssiin (); } }
Java-kokoonpano
Java - esimerkki (koostumuksen kautta)
// Chief.java-tiedosto
julkisen käyttöliittymän päällikkö {
julkinen Object makeBreakfast ();
julkinen Object makeDinner ();
julkinen Object makeSupper ();
}
// Putkimies.java-tiedosto
julkisen luokan putkimies {
public Object getPipe () {
return new Object ();
}
public Object getKey () {
return new Object ();
}
public Object getScrewDriver () {
return new Object ();
}
}
// ChiefAdapter.java-tiedosto
public class ChiefAdapter toteuttaa Chief {
yksityinen Putkimies putkimies = uusi Putkimies ();
@Override
public Object makeBreakfast () {
paluu putkimies . getkey ();
}
@Override
public Object makeDinner () {
paluu putkimies . getScrewDriver ();
}
@Override
public Object makeSupper () {
return putkimies . getPipe ();
}
}
// Client.java-tiedosto
public class Asiakas {
public static void main ( String [] args ) {
Chief chief = new ChiefAdapter ();
Objektiavain = pää . _ teeDinner (); }
}
scala
Scala esimerkki
pakettiobjektisovitin { _ _
esine Battlefield {
suojattu var redTroops : Array [ Joukko ] = Array ( )
suojattu var blueTroops : Array [ Joukko ] = Array ( )
def addTroop ( joukko : Joukko ) : Yksikkö = {
if ( joukko . puoli == "punainen" ) {
redJoukkoja :+= joukko
} else if ( joukko . puoli == "sininen" ) {
blueTroops :+= joukko
} else {
heittää uusi poikkeus ( s"Virheellinen puoli ${ troop . side } for troop ${ troop . name } " )
}
}
def getClosestEnemyTroop ( puoli : String ): Joukko = {
if ( puoli == "punainen" ) {
getTroop ( blueTroops )
} else {
getTroop ( redTroops )
}
}
yksityinen def getTroop ( joukot : Array [ Joukko ]): Joukko = {
if ( joukot . pituus == 0 ) {
heittää uusi poikkeus ( "Ei käytettävissä olevia joukkoja" )
}
joukot ( 0 )
}
}
luokka Joukko (
val side : String ,
val nimi : String ,
val closeAse : String ,
val distanceWeapon : String
) {
def move ( suunta : merkkijono , etäisyys : int ): Yksikkö = {
println ( s"Joukun $ nimi liikkuu $ suunnassa $ etäisyys jaardia " ) }
def attack ( enemyTroop : Troop , attackType : String ) : Yksikkö = {
val ase = attackType match {
case "etäisyys" => etäisyysAsetapaus "
close " => closeAsetapaus _ => heittää uusi Poikkeus ( s"Virheellinen hyökkäystyyppi $ attackType joukolle $ nimi " ) }
println ( s"Joukkojen $ nimi hyökkää vihollisjoukkoja ${ enemyTroop . name } vastaan ${ ase } s" )
}
}
ominaisuus LanceKnightTroopTrait {
def moveForward ( etäisyys : Int ) : Yksikkö
def attackClosest ( attackType : String ) : Yksikkö
}
luokka LanceKnightTroop (
ohita val side : String ,
ohita val nimi : String ,
ohita val closeWeapon : String ,
ohita val distanceWeapon : String
)
laajentaa joukkoa ( puoli , nimi , closeWeapon , distanceWeapon ) kanssa LanceKnightTroopTrait {
override def moveForward ( etäisyys : Int ): Yksikkö = {
liikkua ( "eteenpäin" , etäisyys )
}
ohittaa def attackClosest ( attackType : String ): Yksikkö = {
hyökkäys ( Battlefield . getClosestEnemyTroop ( side ), attackType )
}
}
object AdapterTest expands AbstractTest {
ohittaa def run (): Yksikkö = {
val troop = uusi joukko ( "sininen" , "jousimiehet" , "miekka" , "pitkäjousi" )
val lanceKnightTroop = uusi LanceKnightTroop ( "punainen" , "Lance Knights" , "hauki" " , varsijousi )
Taistelukenttä . addTroop ( joukko )
Battlefield . addTroop ( lanceKnightTroop )
println ( "Output:" )
lanceKnightTroop . Siirry eteenpäin ( 300 ) lanceKnightTroop . attackClosest ( "sulje" ) } } }
// Tulos:
// Joukko Lance Knights liikkuu eteenpäin 300 jaardia
// Troop Lance Knights hyökkää vihollisjoukkojen jousimiesten kimppuun haukeineen
PHP5
Esimerkki
PHP 5 :ssä
<?php
class IndependentDeveloper1
{
public function calc ( $a , $b ) {
return $a + $b ;
}
}
class IndependentDeveloper2
{
julkisen funktion nimiIsVeryLongAndUncomfortable ( $a , $b ) {
return $a + $b ;
}
}
käyttöliittymä IAdapter
{
julkinen funktio summa ( $a , $b );
}
luokka ConcreteAdapter1 toteuttaa IAAdapterin
{
suojattu $objekti ;
public function __construct () {
$this -> object = new IndependentDeveloper1 ();
}
julkinen funktio summa ( $a , $b ) {
return $this -> object -> calc ( $a , $b );
}
}
luokka ConcreteAdapter2 toteuttaa IAAdapterin
{
suojattu $objekti ;
public function __construct () {
$this -> object = new IndependentDeveloper2 ();
}
julkinen funktio summa ( $a , $b ) {
return $this -> object -> nameIsVeryLongAndUncomfortable ( $a , $b );
}
}
//yhdessä paikassa luomme betonisovittimen ja käytämme sitten käyttöliittymää
$adapter1 = new ConcreteAdapter1 ();
$adapteri2 = uusi ConcreteAdapter2 ();
/**
* Kaikkialla koodissa emme käytä luokkia suoraan, vaan käyttöliittymän kautta
* tällä funktiolla ei ole väliä mitä luokkaa käytämme, koska luotamme käyttöliittymään
*
* @param IAdapter $adapter
*/
funktion summa ( IAdapter $ sovitin ) {
kaiku $ sovitin -> summa ( 2 , 2 );
}
summa ( $adapteri1 );
summa ( $sovitin2 );
PHP5.4
Esimerkki
PHP 5.4:ssä (Trait)
<?php
class SomeClass
{
public function someSum ( $a , $b )
{
return $a + $b ;
}
}
class AnotherClass
{
julkinen funktio otherSum ( $a , $b )
{
return $a + $b ;
}
}
ominaisuus TAdaptee
{
julkinen funktio summa ( int $a , int $b )
{
$method = $this -> method ;
palauttaa $this -> $method ( $a , $b );
}
}
class SomeAdaptee laajentaa SomeClass
{
use TAdaptee ;
yksityinen $method = 'someSum' ;
}
class AnotherAdaptee laajentaa AnotherClass
{
use TAdaptee ;
yksityinen $method = 'toinenSumma' ;
}
$joku = uusi SomeAdaptee ;
$toinen = uusi AnotherAdaptee ;
$joku -> summa ( 2 , 2 );
$toinen -> summa ( 5 , 2 );
PHP5.4 Compact
Esimerkki
PHP 5.4:ssä (Compact)
<?php
ominaisuus TAdaptee
{
julkinen funktio summa ( int $a , int $b )
{
$method = $this -> method ;
palauttaa $this -> $method ( $a , $b );
}
}
class SomeClass
{
käytä TAdaptee ;
yksityinen $method = 'someSum' ;
julkinen funktio jokinSumma ( $a , $b )
{
return $a + $b ;
}
}
class AnotherClass
{
käytä TAdaptee ;
yksityinen $method = 'toinenSumma' ;
julkinen funktio otherSum ( $a , $b )
{
return $a + $b ;
}
}
$joku = uusi SomeClass ;
$toinen = uusi AnotherClass ;
$joku -> summa ( 2 , 2 );
$toinen -> summa ( 5 , 2 );
JavaScript
JavaScript esimerkki
function Haku ( teksti , sana ) {
var teksti = teksti ;
var sana = sana ;
tämä . searchWordInText = function () {
return text ;
};
tämä . getWord = function ( ) {
paluusana ; }; }; function SearchAdapter ( adaptee ) { this . searchWordInText = function () { return 'Nämä sanat' + adaptee . getWord () + ' löytyy tekstistä ' + adaptee . searchWordInText (); }; }; var search = new Haku ( "teksti" , "sanat" ); var searchAdapter = uusi SearchAdapter ( haku ); hakusovitin . searchWordInText ();
Python
Esimerkki
Pythonissa
luokka GameConsole :
def create_game_picture ( itse ):
palauttaa 'kuva konsolista'
luokan antenni :
def create_wave_picture ( self ):
return 'kuva aallosta'
luokka SourceGameConsole ( GameConsole ):
def get_picture ( self ):
return self . create_game_picture ()
luokka SourceAntenna ( Antenna ):
def get_picture ( self ):
return self . luo_aaltokuva ()
luokka TV :
def __init__ ( itse , lähde ):
itse . lähde = lähde
def show_picture ( self ):
return self . lähde . hanki_kuva ()
g = SourceGameConsole ()
a = SourceAntenna ()
game_tv = TV ( g )
cabel_tv = TV ( a )
tulosta ( game_tv . show_picture ())
tulosta ( cabel_tv . show_picture ())
C# - kokoonpano
C# -esimerkki (koostumus)
käyttäen System ;
nimiavaruussovitin { _
class MainApp
{
static void Main ()
{
// Luo sovitin ja aseta pyyntö
Kohdekohde = uusi sovitin ( ); kohde . pyytää ();
// Odota käyttäjän
konsolia . lue ();
}
}
// "Kohde"
class Kohde
{
public virtual void Pyyntö ()
{
Konsoli . WriteLine ( "Called TargetRequest()" );
}
}
// "Sovitin"
class Sovitin : Kohde
{
yksityinen sopeutuja sopeutuja = uusi sopeutuja ();
public override void Request ()
{
// Tee mahdollisesti muuta työtä
// ja soita sitten SpecificRequest
adaptee . SpecificRequest ();
}
}
// "Sopeutunut"
class Adaptee
{
public void SpecificRequest ()
{
Konsoli . WriteLine ( "Called SpecificRequest()" );
}
}
}
C# - perintö
C# -esimerkki (perintö)
käyttäen System ;
nimiavaruussovitin { _
class MainApp
{
static void Main ()
{ // Luo
sovitin ja aseta pyyntö
Sovitinsovitin = uusi Sovitin (); sovitin . pyytää ();
// Odota käyttäjän
konsolia . lue ();
}
}
// "Kohde"
käyttöliittymä ITarget
{
public void Request ();
}
// Voit käyttää abstraktia luokkaa
// "Sovitin"
class Sovitin : Adaptee , ITarget
{
public void Request ()
{
// Tee mahdollisesti muuta työtä
// ja kutsu sitten SpecificRequest
SpecificRequest ();
}
}
// "Sopeutunut"
class Adaptee
{
public void SpecificRequest ()
{
Konsoli . WriteLine ( "Called SpecificRequest()" );
}
}
}
Delphi
Delphi esimerkki
ohjelma-adapteri;
{$APPTYPE CONSOLE}
{$R *.res}
käyttää
System.SysUtils;
(*TTarget-luokan asiakaskäyttöliittymä toteutettu TAadapterina*)
(*TAdapter uudelleenohjaa puhelun TAdaptee*)
tyyppi
TTarget = luokka
functionRequest:string; virtuaalinen;
loppu;
TAdapte = luokka
toiminto SpecificRequest:string;
loppu;
TAsovitin = luokka (TTkohde)
fAdaptee: TAdaptee;
functionRequest:string; ohittaa;
rakentajaLuo;
loppu;
{ TTarget }
toiminto TTarget.Request: merkkijono;
alkaa
Result:= 'Called Target Request()';
loppu;
{TAdaptee}
toiminto TAdaptee.SpecificRequest: merkkijono;
alkaa
Result:= 'Called SpecificRequest()';
loppu;
{TAsovitin}
rakentaja TAdapter.Create;
alkaa
fAdaptee:= TAdaptee.Create;
loppu;
toiminto TAdapter.Request: merkkijono;
alkaa
(*Mahdollisesti tehdä muita töitä ja soita SpecificRequest*)
Tulos:= fAdaptee.SpecificRequest;
loppu;
var target: TTarget;
alkaa
yrittää
{ TODO -oUser -cConsole Main : Lisää koodi tähän }
(*luo sovitin ja tee pyyntö*)
kohde:= TAadapter.Create;
WriteLn(target.Request);
WriteLn(#13#10+'Jatka painamalla mitä tahansa näppäintä...');
ReadLn;
kohde.Ilmainen;
paitsi
E: Poikkeus
Writeln(E.Luokannimi, ':', E.Viesti);
loppu;
loppu.
Muistiinpanot
- ↑ Termien kuori ja kääre ( englanniksi wrapper - käytetty synonyyminä sisustajalle) läheisyys johtaa joskus sekaannukseen ja Adapteri määritellään synonyymiksi sisustaja -mallille , kun taas nämä ovat kaksi eri mallia ja jälkimmäinen. ratkaisee eri tehtävän, nimittäin: lisävelvoitteiden liittäminen objektiin.
- ↑ Erona on, että julkisivukuvio on suunniteltu yksinkertaistamaan käyttöliittymää, kun taas Adapter-kuvio on suunniteltu tuomaan useat olemassa olevat rajapinnat samaan haluttuun ilmeeseen.
- ↑ PHP-kielen vanhentuneissa versioissa pääsy DBMS-järjestelmään on toteutettu funktioiden sarjana, jokaiselle DBMS:lle niillä on eri nimet ja joskus eri parametrijoukko, mikä johtaa merkittäviin ongelmiin vaihdettaessa yhdestä DBMS:stä toiseen. toinen, jos tällaista siirtymää ei tarjota etukäteen käyttämällä sovitinmallia.
Kirjallisuus
- Alan Shalloway, James R. Trott. Suunnittelumalleja. Uusi lähestymistapa olio-suuntautuneeseen suunnitteluun = Design Patterns Explained: A New Perspective on Object-Oriented Design. - M . : "Williams" , 2002. - S. 288. - ISBN 0-201-71594-5 .
- E. Gamma, R. Helm, R. Johnson, J. Vlissides . Olio-suunnittelun tekniikat. Suunnittelumallit = Suunnittelumallit: Uudelleenkäytettävän olio-ohjelmiston elementit. - Pietari. : "Peter" , 2007. - S. 366. - ISBN 978-5-469-01136-1 . (myös ISBN 5-272-00355-1 )
- Eric Freeman, Elizabeth Freeman. Suunnittelukuviot = Head First Design Patterns. - Pietari. : Peter, 2011. - 656 s. - ISBN 978-5-459-00435-9 .
Linkit