Шаблон проектирования "Стратегия"
24 июня 2020Относится к поведенческим шаблонам.
Плюсы:
- позволяет менять алгоритм независимо от объектов, которые его используют.
Пример на PHP
Рассмотрим сортировку списка объектов, где одна стратегия сортирует по id, другая - по названию.
interface ComparatorInterface
{
public function compare($a, $b);
}
class IdComparator implements ComparatorInterface
{
public function compare($a, $b)
{
return $a['id'] <=> $b['id'];
}
}
class TitleComparator implements ComparatorInterface
{
public function compare($a, $b)
{
return $a['title'] <=> $b['title'];
}
}
class CitiesCollection
{
private array $cities;
private ComparatorInterface $comparator;
public function __construct($cities = [])
{
$this->cities = $cities;
}
public function setComparator(ComparatorInterface $comparator)
{
$this->comparator = $comparator;
}
public function sort(): array
{
if (!$this->comparator) {
throw new \Exception('Comparator is not set');
}
uasort($this->cities, [$this->comparator, 'compare']);
return $this->cities;
}
}
Использование:
$cities = [['id' => 2, 'title' => 'Moscow'], ['id' => 4, 'title' => 'Kaliningrad'], ['id' => 3, 'title' => 'Barcelona']];
$obj = new CitiesCollection($cities);
$obj->setComparator(new IdComparator());
$results = $obj->sort(); // [['id' => 2, 'title' => 'Moscow'], ['id' => 3, 'title' => 'Barcelona'], ['id' => 4, 'title' => 'Kaliningrad']]
$obj->setComparator(new TitleComparator());
$results = $obj->sort(); // [['id' => 3, 'title' => 'Barcelona'], ['id' => 4, 'title' => 'Kaliningrad'], ['id' => 2, 'title' => 'Moscow']]
Пример на Go
package main
import "sort"
type IComparator interface {
Compare(city1 City, city2 City) bool
}
type City struct {
id int
title string
}
type CitiesCollection struct {
cities []City
comparator IComparator
}
type IdComparator struct {
}
type TitleComparator struct {
}
func (c *IdComparator) Compare(city1 City, city2 City) bool {
return city1.id < city2.id
}
func (c *TitleComparator) Compare(city1 City, city2 City) bool {
return city1.title < city2.title
}
func (c *CitiesCollection) SetCities(cities []City) {
c.cities = cities
}
func (c *CitiesCollection) SetComparator(comparator IComparator) {
c.comparator = comparator
}
func (c *CitiesCollection) Sort() []City {
sortedCities := make([]City, len(c.cities))
copy(sortedCities, c.cities)
sort.Slice(sortedCities, func(i, j int) bool {
return c.comparator.Compare(sortedCities[i], sortedCities[j])
})
return sortedCities
}
func main() {
cities := []City{
{
id: 2,
title: "Moscow",
},
{
id: 4,
title: "Kaliningrad",
},
{
id: 3,
title: "Barcelona",
},
}
idComparator := IdComparator{}
titleComparator := TitleComparator{}
collection := CitiesCollection{}
collection.SetCities(cities)
collection.SetComparator(&idComparator)
collection.Sort()
collection.SetComparator(&titleComparator)
collection.Sort()
}
Источники:
http://designpatternsphp.readthedocs.io/ru/latest/Behavioral/Strategy/README.html
https://habrahabr.ru/company/mailru/blog/325492/