Декоратор (шаблон проектирования)
- 1 year ago
- 0
- 0
Адаптер ( англ. Adapter ) — структурный шаблон проектирования , предназначенный для организации использования функций объекта , недоступного для модификации, через специально созданный интерфейс . Другими словами — это структурный паттерн проектирования, который позволяет объектам с несовместимыми интерфейсами работать вместе.
Система поддерживает требуемые данные и поведение, но имеет неподходящий интерфейс.
Адаптер предусматривает создание класса-оболочки с требуемым интерфейсом.
Класс
Adapter
приводит интерфейс класса
Adaptee
в соответствие с интерфейсом класса
Target
(который реализуется классом
Adapter
). Это позволяет объекту
Client
использовать объект
Adaptee
(посредством адаптера
Adapter
) так, словно он является экземпляром класса
Target
.
Таким образом
Client
обращается к интерфейсу
Target
, реализованному классом
Adapter
, который перенаправляет обращение к
Adaptee
.
Шаблон Адаптер позволяет включать уже существующие объекты в новые объектные структуры, независимо от различий в их интерфейсах.
Шаблон Адаптер позволяет в процессе проектирования не принимать во внимание возможные различия в интерфейсах уже существующих классов. Если есть класс, обладающий требуемыми методами и свойствами (по крайней мере, концептуально), то при необходимости всегда можно воспользоваться шаблоном Адаптер для приведения его интерфейса к нужному виду.
Близким Адаптеру является шаблон Фасад , не всегда можно отличить один от другого .
Типичным примером использования шаблона Адаптер можно назвать создание классов, приводящих к единому интерфейсу функции языка PHP обеспечивающие доступ к различным СУБД .
Вариант решения данной проблемы с использованием шаблона Адаптер показан на рисунке.
Включение уже существующего класса в другой класс. Интерфейс включающего класса приводится в соответствие с новыми требованиями, а вызовы его методов преобразуются в вызовы методов включённого класса.
module AdapterPattern
# Allows Client to use Adaptees with incompatible interfaces via Adapters with interface Target
# Adaptee
class Twitter
def twit
puts 'Twit was published'
end
end
# Adaptee
class Facebook
def post
puts 'Facebook post was published'
end
end
# Target
module WebServiceInterface
def send_message
raise NotImplementedError
end
end
# Adapter
class TwitterAdapter
include WebServiceInterface
def initialize
@webservice = Twitter.new
end
def send_message
@webservice.twit
end
end
# Adapter
class FacebookAdapter
include WebServiceInterface
def initialize
@webservice = Facebook.new
end
def send_message
@webservice.post
end
end
# Client
class Message
attr_accessor :webservice
def send
@webservice.send_message
end
end
def self.run
puts '=> Adapter'
message = Message.new
message.webservice = TwitterAdapter.new
message.send
message.webservice = FacebookAdapter.new
message.send
puts ''
end
end
AdapterPattern.run
// Target
public interface Chief
{
public Object makeBreakfast();
public Object makeLunch();
public Object makeDinner();
}
// Adaptee
public class Plumber
{
public Object getScrewNut()
{ ... }
public Object getPipe()
{ ... }
public Object getGasket()
{ ... }
}
// Adapter
public class ChiefAdapter extends Plumber implements Chief
{
public Object makeBreakfast()
{
return getGasket();
}
public Object makeLunch()
{
return getPipe();
}
public Object makeDinner()
{
return getScrewNut();
}
}
// Client
public class Client
{
public static void eat(Object dish)
{ ... }
public static void main(String[] args)
{
Chief ch = new ChiefAdapter();
Object dish = ch.makeBreakfast();
eat(dish);
dish = ch.makeLunch();
eat(dish);
dish = ch.makeDinner();
eat(dish);
callAmbulance();
}
}
// Файл Chief.java
public interface Chief {
public Object makeBreakfast();
public Object makeDinner();
public Object makeSupper();
}
// Файл Plumber.java
public class Plumber {
public Object getPipe() {
return new Object();
}
public Object getKey() {
return new Object();
}
public Object getScrewDriver() {
return new Object();
}
}
// Файл ChiefAdapter.java
public class ChiefAdapter implements Chief {
private Plumber plumber = new Plumber();
@Override
public Object makeBreakfast() {
return plumber.getKey();
}
@Override
public Object makeDinner() {
return plumber.getScrewDriver();
}
@Override
public Object makeSupper() {
return plumber.getPipe();
}
}
// Файл Client.java
public class Client {
public static void main(String [] args) {
Chief chief = new ChiefAdapter();
Object key = chief.makeDinner();
}
}
package object adapter {
object Battlefield {
protected var redTroops : Array[Troop] = Array()
protected var blueTroops : Array[Troop] = Array()
def addTroop(troop : Troop) : Unit = {
if (troop.side == "red") {
redTroops :+= troop
} else if (troop.side == "blue") {
blueTroops :+= troop
} else {
throw new Exception(s"Invalid side ${troop.side} for troop ${troop.name}")
}
}
def getClosestEnemyTroop(side : String): Troop = {
if (side == "red") {
getTroop(blueTroops)
} else {
getTroop(redTroops)
}
}
private def getTroop(troops: Array[Troop]): Troop = {
if (troops.length == 0) {
throw new Exception("No available troops")
}
troops(0)
}
}
class Troop (
val side : String,
val name : String,
val closeWeapon : String,
val distanceWeapon : String
) {
def move(direction: String, distance: Int): Unit = {
println(s"Troop $name moves $direction on $distance yards")
}
def attack(enemyTroop: Troop, attackType: String) : Unit = {
val weapon = attackType match {
case "distance" => distanceWeapon
case "close" => closeWeapon
case _ => throw new Exception(s"Invalid attack type $attackType for troop $name")
}
println(s"Troop $name attacks enemy troop ${enemyTroop.name} with their ${weapon}s")
}
}
trait LanceKnightTroopTrait {
def moveForward(distance : Int) : Unit
def attackClosest(attackType : String) : Unit
}
class LanceKnightTroop(
override val side : String,
override val name : String,
override val closeWeapon: String,
override val distanceWeapon: String
)
extends Troop(side, name, closeWeapon, distanceWeapon)
with LanceKnightTroopTrait {
override def moveForward(distance: Int): Unit = {
move("forward", distance)
}
override def attackClosest(attackType: String): Unit = {
attack(Battlefield.getClosestEnemyTroop(side), attackType)
}
}
object AdapterTest extends AbstractTest {
override def run(): Unit = {
val troop = new Troop("blue", "Archers", "sword", "longbow")
val lanceKnightTroop = new LanceKnightTroop("red", "Lance Knights", "pike", "crossbow")
Battlefield.addTroop(troop)
Battlefield.addTroop(lanceKnightTroop)
println("Output:")
lanceKnightTroop.moveForward(300)
lanceKnightTroop.attackClosest("close")
}
}
}
// Output:
// Troop Lance Knights moves forward on 300 yards
// Troop Lance Knights attacks enemy troop Archers with their pikes
<?php
class IndependentDeveloper1
{
public function calc($a, $b) {
return $a + $b;
}
}
class IndependentDeveloper2
{
public function nameIsVeryLongAndUncomfortable($a, $b) {
return $a + $b;
}
}
interface IAdapter
{
public function sum($a, $b);
}
class ConcreteAdapter1 implements IAdapter
{
protected $object;
public function __construct() {
$this->object = new IndependentDeveloper1();
}
public function sum($a, $b) {
return $this->object->calc($a, $b);
}
}
class ConcreteAdapter2 implements IAdapter
{
protected $object;
public function __construct() {
$this->object = new IndependentDeveloper2();
}
public function sum($a, $b) {
return $this->object->nameIsVeryLongAndUncomfortable($a, $b);
}
}
//в одном месте мы создаем конкретный адаптер а потом пользуемся интерфейсом
$adapter1 = new ConcreteAdapter1();
$adapter2 = new ConcreteAdapter2();
/**
* Везде в коде мы не используем классы напрямую а через интерфейс
* этой функции нет разницы какой класс мы используем, так как мы опираемся на интерфейс
*
* @param IAdapter $adapter
*/
function sum(IAdapter $adapter) {
echo $adapter->sum(2, 2);
}
sum($adapter1);
sum($adapter2);
<?php
class SomeClass
{
public function someSum($a, $b)
{
return $a + $b;
}
}
class AnotherClass
{
public function anotherSum($a, $b)
{
return $a + $b;
}
}
trait TAdaptee
{
public function sum(int $a, int $b)
{
$method = $this->method;
return $this->$method($a, $b);
}
}
class SomeAdaptee extends SomeClass
{
use TAdaptee;
private $method = 'someSum';
}
class AnotherAdaptee extends AnotherClass
{
use TAdaptee;
private $method = 'anotherSum';
}
$some = new SomeAdaptee;
$another = new AnotherAdaptee;
$some->sum(2,2);
$another->sum(5,2);
<?php
trait TAdaptee
{
public function sum(int $a, int $b)
{
$method = $this->method;
return $this->$method($a, $b);
}
}
class SomeClass
{
use TAdaptee;
private $method = 'someSum';
public function someSum($a, $b)
{
return $a + $b;
}
}
class AnotherClass
{
use TAdaptee;
private $method = 'anotherSum';
public function anotherSum($a, $b)
{
return $a + $b;
}
}
$some = new SomeClass;
$another = new AnotherClass;
$some->sum(2,2);
$another->sum(5,2);
function Circle (radius) {
this.getRadius = function () {
return radius;
};
};
function SquareCircleAdapter (adaptee) {
this.getSide = function () {
return 2 * adaptee.getRadius();
};
};
const circle = new Circle(3.14);
const square = new SquareCircleAdapter(circle);
const side = square.getSide();
class GameConsole:
def create_game_picture(self):
return 'picture from console'
class Antenna:
def create_wave_picture(self):
return 'picture from wave'
class SourceGameConsole(GameConsole):
def get_picture(self):
return self.create_game_picture()
class SourceAntenna(Antenna):
def get_picture(self):
return self.create_wave_picture()
class TV:
def __init__(self, source):
self.source = source
def show_picture(self):
return self.source.get_picture()
g = SourceGameConsole()
a = SourceAntenna()
game_tv = TV(g)
cabel_tv = TV(a)
print( game_tv.show_picture())
print( cabel_tv.show_picture())
using System;
namespace Adapter
{
class MainApp
{
static void Main()
{
// Create adapter and place a request
Target target = new Adapter();
target.Request();
// Wait for user
Console.Read();
}
}
// "Target"
class Target
{
public virtual void Request()
{
Console.WriteLine("Called Target Request()");
}
}
// "Adapter"
class Adapter : Target
{
private Adaptee adaptee = new Adaptee();
public override void Request()
{
// Possibly do some other work
// and then call SpecificRequest
adaptee.SpecificRequest();
}
}
// "Adaptee"
class Adaptee
{
public void SpecificRequest()
{
Console.WriteLine("Called SpecificRequest()");
}
}
}
С# - наследование
using System;
namespace Adapter
{
class MainApp
{
static void Main()
{
// Create adapter and place a request
Adapter adapter = new Adapter();
adapter.Request();
// Wait for user
Console.Read();
}
}
// "Target"
interface ITarget
{
public void Request();
}
// You can use abstract class
// "Adapter"
class Adapter : Adaptee, ITarget
{
public void Request()
{
// Possibly do some other work
// and then call SpecificRequest
SpecificRequest();
}
}
// "Adaptee"
class Adaptee
{
public void SpecificRequest()
{
Console.WriteLine("Called SpecificRequest()");
}
}
}
program Adapter;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils;
(*Client use interface of class TTarget realized as TAdapter*)
(*TAdapter redirects the call to TAdaptee*)
type
TTarget = class
function Request: string; virtual;
end;
TAdaptee = class
function SpecificRequest: string;
end;
TAdapter = class(TTarget)
fAdaptee: TAdaptee;
function Request: string; override;
constructor Create;
end;
{ TTarget }
function TTarget.Request: string;
begin
Result:= 'Called Target Request()';
end;
{ TAdaptee }
function TAdaptee.SpecificRequest: string;
begin
Result:= 'Called SpecificRequest()';
end;
{ TAdapter }
constructor TAdapter.Create;
begin
fAdaptee:= TAdaptee.Create;
end;
function TAdapter.Request: string;
begin
(*Possibly do some other work and when call SpecificRequest*)
Result:= fAdaptee.SpecificRequest;
end;
var target: TTarget;
begin
try
{ TODO -oUser -cConsole Main : Insert code here }
(*create adapter and place a request*)
target:= TAdapter.Create;
WriteLn(target.Request);
WriteLn(#13#10+'Press any key to continue...');
ReadLn;
target.Free;
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
end.