现实例子
举一个排序的例子,我们首先实现了冒泡排序,但是随着数据量的增长我们发现冒泡排序的效率变得很慢,为此,我们又实现了快速排序处理大数据,但是这个快速排序处理小规模数据的效率比较低,所以为了处理这个问题,我们又实现了一个针对小规模数据的策略,使得在大规模数据上使用快速排序,小规模数据使用冒泡排序。
说人话
策略模式允许您根据情况切换算法或策略
(实际上在js里面由于函数是一等公民,第一个参数设为函数,之后传入不同的排序函数就能达成类似的效果)
typescript example
typescript 给JavaScript添加了更完善的面向对象支持,支持类型和interface
下面是用typescript实现这个排序的例子的代码
interface SortStrategy {
sort(arr: Array<number>): Array<number>
}
class BubbleSortStrategy implements SortStrategy {
sort(arr: number[]): number[] {
console.log('do bubble sort')
return arr
}
}
class QuickSortStrategy implements SortStrategy {
sort(arr: number[]): number[] {
console.log('do quick sort')
return arr
}
}
class Sorter {
sortStrategy: SortStrategy
constructor(sortStrategy: SortStrategy) {
this.sortStrategy = sortStrategy
}
sort(arr: Array<number>): Array<number> {
return this.sortStrategy.sort(arr)
}
}
new Sorter(new BubbleSortStrategy()).sort([9, 2, 4, 3, 5])
new Sorter(new QuickSortStrategy()).sort([9, 2, 4, 3, 5])
实际上最后生成es5的代码,里面就没有接口了,
JavaScript的多态和python一样,是通过鸭子类型实现的。
"use strict";
var BubbleSortStrategy = /** @class */ (function () {
function BubbleSortStrategy() {
}
BubbleSortStrategy.prototype.sort = function (arr) {
console.log('do bubble sort');
return arr;
};
return BubbleSortStrategy;
}());
var QuickSortStrategy = /** @class */ (function () {
function QuickSortStrategy() {
}
QuickSortStrategy.prototype.sort = function (arr) {
console.log('do quick sort');
return arr;
};
return QuickSortStrategy;
}());
var Sorter = /** @class */ (function () {
function Sorter(sortStrategy) {
this.sortStrategy = sortStrategy;
}
Sorter.prototype.sort = function (arr) {
return this.sortStrategy.sort(arr);
};
return Sorter;
}());
new Sorter(new BubbleSortStrategy()).sort([9, 2, 4, 3, 5]);
new Sorter(new QuickSortStrategy()).sort([9, 2, 4, 3, 5]);
下面是按照head first 设计模式,这本书第一个例子实现的鸭子模拟器代码。
使用了策略模式,把给鸭子添加各种行为的代码抽离出来了,使得添加新的行为的代码改动比较小,并且可以动态改变行为。
interface FlyBehavior {
fly(): void
}
class FlyWithWings implements FlyBehavior {
fly(): void {
console.log('i can fly')
}
}
class FlyNoWay implements FlyBehavior {
fly(): void {
console.log('i can not fly')
}
}
class FlyRocketPowered implements FlyBehavior {
fly(): void {
console.log('fly with a rocket!!!!!!!')
}
}
interface QuackBehavior {
quack(): void
}
class Quack implements QuackBehavior {
quack(): void {
console.log('quack!!!')
}
}
class MuteQuack implements QuackBehavior {
quack(): void {
console.log('<<Silence>>')
}
}
abstract class Duck {
abstract flyBehavior: FlyBehavior
abstract quackBehavior: QuackBehavior
abstract display(): void
performFly(): void {
this.flyBehavior.fly()
}
performQuack(): void {
this.quackBehavior.quack()
}
swim(): void {
console.log('All ducks float,even decoys')
}
}
class MallardDuck extends Duck {
flyBehavior: FlyBehavior = new FlyWithWings()
quackBehavior: QuackBehavior = new Quack()
display(): void {
console.log('this is MallarDuck')
this.performQuack()
this.performFly()
this.swim()
}
}
class ModelDuck extends Duck {
flyBehavior: FlyBehavior = new FlyRocketPowered()
quackBehavior: QuackBehavior = new MuteQuack()
display(): void {
console.log('this is model duck')
this.performQuack()
this.performFly()
this.swim()
}
}
class DuckCall extends Quack {}
// const duck1 = new TestDuck()
// duck1.performFly()
// duck1.performQuack()
new MallardDuck().display()
new ModelDuck().display()
new DuckCall().quack()
golang example
go语言没有继承,go语言的interface也比较轻量,类似于python和js这样的鸭子类型了,只是多了类型检查而已,编译阶段找不到对应的函数就会报错了。
golang的interface只能包含函数,然后实现这个interface只要实现同样格式的函数就算实现接口。所以一个空接口interface{}所有类型都实现了它,可以用空接口接收所有类型。
整体来说还是比较灵活的,比较简洁的。
package main
import "fmt"
type SortStrategyer interface {
sort(list []int) []int
}
type BubbleSortStrategy struct {
}
func (b *BubbleSortStrategy) sort(list []int) []int {
fmt.Println("do bubble sort")
return list
}
type QuickSortStrategy struct {
}
func (b *QuickSortStrategy) sort(list []int) []int {
fmt.Println("do quick sort")
return list
}
type Sorter struct {
strategy SortStrategyer
}
func (s *Sorter) doSort(list []int) []int {
return s.strategy.sort(list)
}
func main() {
testList := []int{4, 5, 3}
sort1 := Sorter{strategy: &BubbleSortStrategy{}}
sort1.doSort(testList)
sort2 := Sorter{strategy: &QuickSortStrategy{}}
sort2.doSort(testList)
sort1.strategy = &QuickSortStrategy{}
sort1.doSort(testList)
}
dart example
dart 是我用的几种编程语言中语法最接近java的。
typescript也很像java,但是它跟go一样把类型放在变量后面了。
dart的不同之处在于,dart中没有像java一样的interface关键字,dart中每个类都可以当作接口,因此这里我们用了抽象类作为一个接口使用。
abstract class SortStrategy {
List<int> sort(List<int> data);
}
class BubbleSortStrategy implements SortStrategy {
@override
List<int> sort(List<int> data) {
print('do bubble sort');
return data;
}
}
class QuickSortStrategy implements SortStrategy {
@override
List<int> sort(List<int> data) {
print('do qucik sort');
return data;
}
}
class Sorter {
final SortStrategy sortStrategy;
// datr 构造函数语法糖,只需要在参数列表列出初始化参数,赋值自动帮你实现
Sorter(this.sortStrategy);
List<int> doSort(List<int> data) {
return this.sortStrategy.sort(data);
}
}
main(List<String> args) {
var sort1 = Sorter(BubbleSortStrategy());
sort1.doSort([1, 2, 3]);
var sort2 = Sorter(QuickSortStrategy());
sort2.doSort([1, 2, 3]);
}