设计模式——策略模式
- 设计模式分为创建型、结构型、行为型三大类。
- 创建型设计模式主要解决“对象的创建”问题
- 比较常用的有单例模式和工厂模式,相关链接如下:
- 设计模式——单例模式
- 设计模式——工厂模式
- 结构型设计模式主要解决“类或对象的组合”问题
- 比较常用的有代理模式,装饰器模式,相关链接如下:
- 设计模式——代理模式
- 设计模式——装饰器模式
- 行为型设计模式主要解决的就是“类或对象之间的交互”问题
- 比较常用的有观察者模式,策略模式,模板模式
- 设计模式——观察者模式
- 设计模式——策略模式
- 设计模式——模板模式
目录
- 模式定义和使用场景
- 模式结构
- 策略模式优点?
- 策略模式缺点?
- 策略模式代码实现
1. 模式定义和使用场景
- 策略模式定义一系列算法,将每个算法分别封装起来,让它们可以互相替换。
- 使用场景:如果一个系统有许多类,区别在于行为不同,那么策略模式可以动态让一个对象在许多行为中选择一种行为,或者一个系统需要动态的在几种算法中选择一种。
- 备注:策略模式可以移除分支判断逻辑,比如将不同类型订单的打折策略设计成策略类,并由工厂来负责创建策略对象。(工厂通过map实现,将不同策略加入map中)
2. 模式结构
- 策略模式包含如下角色:
a. Context: 环境类
b. Strategy: 抽象策略类
c. ConcreteStrategy: 具体策略类
3. 策略模式优点?
- 用户可以在不修改原有系统的基础上选择算法或行为,也可以灵活地增加新的算法或行为,支持“开闭原则”。
- 策略模式提供了管理相关的算法族的办法。
- 策略模式提供了可以替换继承关系的办法。
- 使用策略模式可以避免使用多重条件判断语句。
4. 策略模式缺点?
- 使用者必须知道所有的策略类,并自行决定使用哪一个策略类。
- 策略模式将造成产生很多策略类(可以通过使用享元模式在一定程度上减少对象的数量)。
5. 策略模式代码实现
1. C++代码实现
#include <iostream>
#include <vector>
using namespace std;
class Strategy {
public:
Strategy() {}
virtual ~Strategy() {}
virtual void algorithm() {}
};
class ConcreteStrategyA : public Strategy {
public:
ConcreteStrategyA() {}
virtual ~ConcreteStrategyA() {}
void algorithm() {
cout << "use algorithm A" << endl;
}
};
class ConcreteStrategyB : public Strategy {
public:
ConcreteStrategyB() {}
virtual ~ConcreteStrategyB() {}
void algorithm() {
cout << "use algorithm B" << endl;
}
};
class Context {
public:
Context() {}
virtual ~Context() {}
void algorithm() {
strategy->algorithm();
}
void setStrategy(Strategy *st) {
strategy = st;
}
private:
Strategy *strategy;
};
int main() {
Strategy *s1 = new ConcreteStrategyA();
Context *ctx = new Context();
ctx->setStrategy(s1);
ctx->algorithm();
Strategy *s2 = new ConcreteStrategyB();
ctx->setStrategy(s2);
ctx->algorithm();
delete s1;
delete s2;
return 0;
}
3. Go代码实现
package main
import "fmt"
type Travel struct {
name string
strategy Strategy
}
func NewTravel(name string, strategy Strategy) *Travel {
return &Travel{
name: name,
strategy: strategy,
}
}
func (p *Travel) traffic() {
p.strategy.traffic(p)
}
type Strategy interface {
traffic(*Travel)
}
type Walk struct{}
func (w *Walk) traffic(t *Travel) {
fmt.Println(t.name + " walk")
}
type Ride struct{}
func (w *Ride) traffic(t *Travel) {
fmt.Println(t.name + " ride")
}
type Drive struct{}
func (w *Drive) traffic(t *Travel) {
fmt.Println(t.name + " drive")
}
func ExampleTravel() {
walk := &Walk{}
Travel1 := NewTravel("小明", walk)
Travel1.traffic()
ride := &Ride{}
Travel2 := NewTravel("小美", ride)
Travel2.traffic()
drive := &Drive{}
Travel3 := NewTravel("小刚", drive)
Travel3.traffic()
}
package main
type Order struct {
}
func (o *Order) getType() OrderType {
return NORMAL
}
type DiscountStrategy interface {
calDiscount(order Order) float64
}
type NormalDiscountStrategy struct {
}
func (n *NormalDiscountStrategy) calDiscount(order Order) float64 {
}
type GrouponDiscountStrategy struct {
}
func (n *GrouponDiscountStrategy) calDiscount(order Order) float64 {
}
type PromotionDiscountStrateg struct {
}
func (n *PromotionDiscountStrateg) calDiscount(order Order) float64 {
}
type OrderType int
const (
NORMAL OrderType = iota
GROUPON
PROMOTION
)
type DiscountStrategyFactory struct {
strategies map[OrderType]DiscountStrategy
}
func NewDiscountStrategyFactory() *DiscountStrategyFactory {
discountStrategyFactory := &DiscountStrategyFactory{
strategies: make(map[OrderType]DiscountStrategy),
}
discountStrategyFactory.strategies[NORMAL] = new(NormalDiscountStrategy)
discountStrategyFactory.strategies[GROUPON] = new(GrouponDiscountStrategy)
discountStrategyFactory.strategies[PROMOTION] = new(PromotionDiscountStrateg)
return discountStrategyFactory
}
func (d *DiscountStrategyFactory) getDiscountStrategy(orderType OrderType) DiscountStrategy {
return d.strategies[orderType]
}
type OrderService struct {
}
func (o *OrderService) discount(order Order) float64 {
orderType := order.getType()
discountStrategy := NewDiscountStrategyFactory().getDiscountStrategy(orderType)
return discountStrategy.calDiscount(order)
}