策略模式
目标市场选择策略的常用模式

目标市场选择策略的常用模式
在选择目标市场时,常用的策略模式包括:
1. 市场细分策略:将整个市场细分为不同的市场细分群体,然后选择其中一个或几个细分市场作为目标市场。
细分市场可以按照地理位置、人口特征、消费习惯等进行划分。
2. 细分市场专注策略:选择一个细分市场专注服务,通过深入了解目标市场的需求,提供定制化的产品和服务,从而获得竞争优势。
3. 多细分市场策略:选择多个细分市场作为目标市场,通过不同的市场定位和营销策略来满足不同细分市场的需求。
4. 全球市场策略:选择全球范围内的市场作为目标市场,通过进行全球市场研究和了解不同国家和地区的消费习惯和需求,开展全球营销活动。
5. 本土化市场策略:选择一个具体的国家或地区作为目标市场,并根据当地的文化、法律法规和消费习惯进行产品和服务的本土化定制。
6. 阶段性市场策略:根据产品或企业发展的阶段,选择不同的目标市场。
比如初创企业可以选择小众市场进行试点,然后逐步扩大市场范围。
7. 共享市场策略:选择与其他企业合作开发共享市场,通过资
源整合和合作来共同开拓市场,提高市场竞争力。
总之,选择目标市场的策略需要考虑产品特征、市场规模、竞争情况等因素,并结合企业自身资源和能力来制定最合适的策略。
策略模式详解

策略模式详解
策略模式是一种行为型设计模式,它定义了一系列算法,并将每一个算法封装起来,使它们可以相互替换。
策略模式使得算法可以独立于使用它的客户端而变化。
策略模式适用于那些需要使用多种算法的问题。
由于每种算法都有其特殊的用途,因此客户端需要根据当前的情况选择最合适的算法。
在这种情况下,策略模式提供了一个灵活且可扩展的框架,使得算法的选择和使用变得简单且易于维护。
在策略模式中,有三个主要的参与者:
1. Strategy:策略接口定义了所有算法的公共接口,客户端通过这个接口来调用算法。
这样,客户端就不需要关心具体的算法实现,只需要根据需要选择相应的策略即可。
2. ConcreteStrategy:具体策略类实现了策略接口,并提供了具体的算法实现。
每个具体策略类都代表了一种特定的算法。
3. Context:上下文对象负责维护策略对象的实例,并根据需要切换不同的策略。
上下文对象通常会根据客户端的请求选择合适的策略对象,并将这个策略对象传递给客户端。
策略模式的优点在于它能够提供一种灵活且可扩展的解决方案,使得算法的选择和使用变得简单且易于维护。
由于策略对象是独立的,因此可以很容易地添加新的策略,而不需要修改现有的代码。
此外,策略模式还可以提供一种替换算法的方式,使得系统能够根据需要进
行动态的调整。
总之,策略模式是一种非常有用的行为型设计模式,它能够提供一种灵活且可扩展的解决方案来解决那些需要使用多种算法的问题。
策略模式

策略模式(Strategy)●策略模式(Strategy Pattern)中体现了两个非常基本的面向对象设计的原则------------封装变化的概念------------变成中使用接口,而不是对接口的实现●面向接口的编程1.策略模式的定义1)定义一组算法,将每个算法都封装起来,并且使它们之间可以互换2)策略模式是这些算法在客户端调用它们的时候能够互不影响的变化2.策略模式的意义1)策略模式使开发人员能够开发出由许多可替换的部分组成的软件,并且各个部分之间是弱连接的关系2)弱连接的特性使软件具有更强的可扩展性,易于维护;更重要的是:它大大提高了软件的可重用性3.策略模式的组成1)抽象策略角色:策略类,通常由一个接口或者抽象类实现,比如:Comparator 2)具体策略角色:包装了相关的算法和行为,比如接口的多个实现类3)环境角色:持有一个策略类的引用,最终给客户端调用的,比如:TreeSet,TreeMap4.策略模式的实现1)策略模式的用意是针对一组算法,将每一个算法封装到具有共同接口的独立的类中,从而使得它们可以相互替换2)策略模式使得算法可以在不影响到客户端的情况下发生变化。
使用策略模式可以把行为和环境分割开来3)环境类负责维持和查询行为类,各种算法则在具体策略中提供。
由于算法和环境独立开来,算法的修改都不会影响环境和客户端5.策略模式的编写步骤1)对策略对象定义一个公共接口(抽象策略角色)2)编写具体策略类,该类实现了上面的公共接口3)在使用具体策略对象的类中保存一个对抽象策略对象的引用(环境角色)4)在使用策略对象的类中,实现对策略对象的set和get方法(注入)或者使用构造方法完成赋值(客户端)6.参看JDK Collections类的源代码7.策略模式的缺点1)客户端必须知道所有的策略类,并自行决定使用哪一个策略类2)造成很多的策略类8.解决方法采用工厂方法(一种设计模式)。
策略模式

什么是Cache的替换算法呢?简单解释一下, 当发生Cache缺失时,Cache控制器必须选择 Cache中的一行,并用欲获得的数据来替换它。所采用的选择策略就是Cache的替换算法。下面给 出相应的UML图。
2. {
3.
Cache cache(LRU); //指定标签即可
4.
cache.Replace();
5.
return 0;
6. }
上面两种方式,构造函数都需要形参。构造函数是否可以不用参数呢?下面给出第三
种实现方式。
方式三:利用模板实现。算法通过模板的实参指定。当然了,还是使用了
参数,只不过不是构造函数的参数。在策略模式中,参数的传递难以避免,客户
[cpp] view plain copy
1. //Cache需要用到替换算法
2. class Cache
3. {
4. private:
5.
ReplaceAlgorithm *m_ra;
6. public:
7.
Cache(ReplaceAlgorithm *ra) { m_ra = ra; }
8.
~Cache() { delete m_ra; }
必须指定某种算法。
[cpp] view plain copy
1. //Cache需要用到替换算法
2. template <class RA>
3. class Cache
策略模式之两型--动态策略模式和静态策略模式

策略模式之两型--动态策略模式和静态策略模式策略模式⼀般是反应⾯向对象语⾔的多态特性,即可在运⾏时更改或选择不同的策略,典型的使⽤⽅式如下:class Strategy{public:Strategy() {}virtual ~Strategy() {}virtual int stopTask() = 0;};//策略Aclass Strategy_A : public Strategy{public:Strategy_A(): Strategy() {}~Strategy_A() {}//virtualint stopTask(){//do your strategy-A}};//策略Bclass Strategy_B : public Strategy{public:Strategy_B(): Strategy() {}~Strategy_B() {}//virtualint stopTask(){//do your strategy-B}};//使⽤时,你可以根据情况或条件(变量),让⽗对象指针指向⼀个实际构造的⼦对象Strategy* pOptionChose = new Strategy_B(); //遇到其他情况,你也可以指向⼀个new Strategy_A()-------------------------------------------------以上就是⼀般的策略模式的⽤法,可以称之为动态策略模式;实际上C++也可以⽤模板来实现,或称之为静态策略模式,这样实现的策略模式有编译期特性,即⼀经编译即固化了策略,特别适⽤于⾯向不同的客户做定制化⽅案的情形。
其⽤法如下:class StrategyA{public:void fun_1(){//do your strategy-A's fun_1}//....void fun_n(){//do your strategy-A's fun_n}};class StrategyB{public:void fun_1(){//do your strategy-B's fun_1}//...void fun_n(){//do your strategy-B's fun_n}};template<class T>class Context{public:void fun_1(){strategy.fun_1();}//...void fun_n(){strategy.fun_n();}private:T strategy;};如上所⽰,类StrategyA和StrategyB除了有同样的fun_1()到fun_n()这n个同名的⽅法外,并没有其他关系;模板类Context<T>中也有上述n个同名⽅法,实际使⽤时,只有根据情况具象化⼀个⾃⼰想要的⼀个策略实例即可,⽐如Context<StrategyA> intance;然后让实例intance调⽤任何想要的⽅法就可以了,⽐如intance.fun_1();就是执⾏类StrategyA中的fun_1()⽅法。
营销推广策略模式有哪些

营销推广策略模式有哪些策略之一:口碑营销口碑营销是一种通过传播消费者对产品或服务的好评和推荐来吸引更多人群的营销策略。
它利用顾客的口碑宣传力量,借助社交媒体、口碑网站、媒体报道等渠道来扩大影响力。
在营销推广过程中,企业可以通过提供优质产品和服务来提高顾客满意度,从而获得更多的正面口碑。
策略之二:内容营销内容营销是一种通过创作和分享有价值内容以吸引潜在客户的策略。
企业可以通过撰写博客文章、发布社交媒体帖子、制作视频等方式来提供有趣、有用或有知识性的内容。
这些内容不仅能够吸引目标群体的关注,还可以建立自身在行业中的专业形象,以吸引更多的潜在客户和增加销售额。
策略之三:搜索引擎优化(SEO)搜索引擎优化是一种通过优化网站结构、关键词选择和内容质量等手段提高网站在搜索引擎中的排名,从而吸引更多有针对性的流量的策略。
优化后的网站能够更好地被搜索引擎收录和展示,使得潜在客户更容易找到和了解企业的产品或服务。
策略之四:社交媒体营销社交媒体营销是一种利用各种社交媒体平台来推广产品或服务的策略。
企业可以通过建立品牌形象、与客户互动和提供独特的内容等方式来吸引更多的关注和互动。
社交媒体平台如Facebook、Twitter、Instagram等,提供了一个广泛而直接的渠道,使企业能够与目标客户建立紧密联系。
策略之五:营销合作营销合作是一种与其他品牌或企业合作,通过共同推广来扩大影响力的策略。
通过与具有相似目标客户或相互补充的企业合作,可以有效地扩大市场覆盖和提高品牌知名度。
合作伙伴可以合作举办活动、共同推出产品或互相宣传,以共同获得更多的曝光度和业务增长。
策略之六:电子邮件营销电子邮件营销是一种通过发送电子邮件来与潜在客户和现有客户建立联系、推广产品或服务的策略。
企业可以通过采集客户的电子邮件地址,定期向他们发送有价值而个性化的电子邮件,以提供优惠、新闻、内容等,从而有效地吸引客户并维持客户关系。
策略之七:线下活动营销线下活动营销是一种通过举办各种线下活动来吸引目标客户的策略。
策略模式与模板方法模式
策略模式与模板⽅法模式1. 策略模式策略模式是⼀种⾏为设计模式,它能让你定义⼀系列算法,并将每种算法分别放⼊独⽴的类中,以使算法的对象能够相互替换。
当你有许多仅在执⾏某些⾏为时略有不同的相似类时,可使⽤策略模式。
使⽤该模式能将类的业务逻辑与其算法实现细节隔离开来。
说⽩了,其实还是解耦策略模式的结构如上图所⽰,主要包含三个⾓⾊:抽象⾓⾊:通常是⼀个接⼝具体⾓⾊:接⼝的具体实现环境⾓⾊:调⽤接⼝的上下⽂环境,通常是⼀段业务逻辑⽅法举个常见的例⼦:⽀付先定义⼀个接⼝ PayStrategy.javapackage com.example.service;import com.example.domain.dto.PayDTO;import com.example.domain.dto.PayDetailDTO;/*** @author ChengJianSheng* @date 2021/1/11*/public interface PayStrategy{/*** 下单*/PayDTO prepay();/*** 查询*/PayDetailDTO query();/*** 撤销*/void cancel();/*** 退款*/void refund();}然后是具体实现AlipayStrategy.javapackage com.example.service.impl;import com.alipay.api.AlipayClient;import com.alipay.api.request.AlipayTradePrecreateRequest;import com.alipay.api.response.AlipayTradeCancelResponse;import com.example.domain.dto.PayDTO;import com.example.domain.dto.PayDetailDTO;import com.example.service.PayStrategy;import org.springframework.beans.factory.annotation.Autowired;import ponent;/*** https:///open/common/abilitymap* https:///open/194/106078* 扫码⽀付*/@Componentpublic class AlipayStrategy implements PayStrategy{@Autowiredprivate AlipayClient alipayClient;@Overridepublic PayDTO prepay(){AlipayTradePrecreateRequest request=new AlipayTradePrecreateRequest();AlipayTradeCancelResponse response=alipayClient.execute(request);return null;}@Overridepublic PayDetailDTO query(){return null;}@Overridepublic void cancel(){}@Overridepublic void refund(){}public void payNotify(String data){}public void refundNotify(){}}WeixinPayStrategy.javapackage com.example.service.impl;import com.example.domain.dto.PayDTO;import com.example.domain.dto.PayDetailDTO;import com.example.service.PayStrategy;import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult; import com.github.binarywang.wxpay.bean.request.WxPayOrderQueryRequest; import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest; import com.github.binarywang.wxpay.service.WxPayService;import org.springframework.beans.factory.annotation.Autowired;import ponent;/*** https:///wiki/doc/apiv3/wxpay/pages/index.shtml* https:///Wechat-Group/WxJava/wiki/%E5%BE%AE%E4%BF%A1%E6%94%AF%E4%BB%98 * @author ChengJianSheng* @date 2021/1/11*/@Componentpublic class WeixinPayStrategy implements PayStrategy{@Autowiredprivate WxPayService wxPayService;@Overridepublic PayDTO prepay(){WxPayUnifiedOrderRequest request=new WxPayUnifiedOrderRequest();wxPayService.createOrder(request);return null;}@Overridepublic PayDetailDTO query(){WxPayOrderQueryRequest request=new WxPayOrderQueryRequest();wxPayService.queryOrder(request);return null;}@Overridepublic void cancel(){}@Overridepublic void refund(){}public void payNotify(String data){WxPayOrderNotifyResult result=wxPayService.parseOrderNotifyResult(data);}public void refundNotify(String data){WxPayOrderNotifyResult result=wxPayService.parseRefundNotifyResult(data);}}上下⽂package com.example.service.impl;import com.example.domain.dto.PayDTO;import com.example.service.PayService;import com.example.service.PayStrategy;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;/*** @author ChengJianSheng* @date 2021/1/11*/@Servicepublic class PayServiceImpl implements PayService{@Autowiredprivate AlipayStrategy alipayStrategy;@Autowiredprivate WeixinPayStrategy weixinPayStrategy;@Overridepublic void prePay(PayDTO payDTO){// 创建⽀付订单// 组装参数PayStrategy payStrategy=null;if(payDTO.getChannel()==1){payStrategy=alipayStrategy;}else{payStrategy=weixinPayStrategy;}payStrategy.prepay();}}这样就将算法的细节与业务逻辑隔离开,开发始终要遵循的原则是:⾼内聚,低耦合其余部分代码补充如下:pom.xml<dependency><groupId>com.alipay.sdk</groupId><artifactId>alipay-sdk-java</artifactId><version>4.11.8.ALL</version></dependency><dependency><groupId>com.github.binarywang</groupId><artifactId>weixin-java-pay</artifactId><version>4.0.0</version></dependency>AlipayConfig.javapackage com.example.config;import com.alipay.api.AlipayClient;import com.alipay.api.DefaultAlipayClient;import org.springframework.beans.factory.annotation.Value;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;/*** 扫码⽀付* https:///open/194/106078* https:///open/common/abilitymap** @author ChengJianSheng* @date 2021/1/11*/@Configurationpublic class AlipayConfig{@Value("${alipay.appId}")private String appId;@Value("${alipay.privateKey}")private String privateKey;@Value("${alipay.publicKey}")private String publicKey;@Beanpublic AlipayClient alipayClient(){AlipayClient alipayClient=new DefaultAlipayClient("https:///gateway.do",appId,privateKey,"json","UTF-8",publicKey,"RSA2");return alipayClient;}}WeixinPayConfig.javapackage com.example.config;import com.github.binarywang.wxpay.config.WxPayConfig;import com.github.binarywang.wxpay.service.WxPayService;import com.github.binarywang.wxpay.service.impl.WxPayServiceImpl;import org.springframework.beans.factory.annotation.Value;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;/*** https:///wiki/doc/apiv3/index.shtml* https:///Wechat-Group/WxJava/wiki/%E5%BE%AE%E4%BF%A1%E6%94%AF%E4%BB%98* @author ChengJianSheng* @date 2021/1/11*/@Configurationpublic class WeixinPayConfig{/*** 公众号appid*/@Value("${weixin.pay.appId}")private String appId;/*** 商户号.*/@Value("${weixin.pay.mchId}")private String mchId;/*** 商户密钥.*/@Value("${weixin.pay.mchKey}")private String mchKey;@Value("${weixin.pay.notifyUrl}")private String notifyUrl;@Beanpublic WxPayService wxPayService(){WxPayConfig payConfig=new WxPayConfig();payConfig.setAppId(appId);payConfig.setMchId(mchId);payConfig.setMchKey(mchKey);payConfig.setNotifyUrl(notifyUrl);WxPayService wxPayService=new WxPayServiceImpl();wxPayService.setConfig(payConfig);return wxPayService;}}2. 模板⽅法模式模板⽅法模式是⼀种⾏为设计模式,它在超类中定义了⼀个算法的框架,允许⼦类在不修改结构的情况下重写算法的特定步骤。
策略模式和工厂模式的区别
策略模式和工厂模式的区别工厂模式和策略模式看着很像,经常让人混淆不清;它们的区别在哪里,需要细细体味;相似点在模式结构上,两者很相似;差异•用途不一样工厂是创建型模式,它的作用就是创建对象;策略是行为型模式,它的作用是让一个对象在许多行为中选择一种行为;•关注点不一样一个关注对象创建一个关注行为的封装•解决不同的问题工厂模式是创建型的设计模式,它接受指令,创建出符合要求的实例;它主要解决的是资源的统一分发,将对象的创建完全独立出来,让对象的创建和具体的使用客户无关。
主要应用在多数据库选择,类库文件加载等。
策略模式是为了解决的是策略的切换与扩展,更简洁的说是定义策略族,分别封装起来,让他们之间可以相互替换,策略模式让策略的变化独立于使用策略的客户。
•工厂相当于黑盒子,策略相当于白盒子;举例说明•工厂模式有一天你决定去吃培根披萨,首先得选择店铺,A店和B店都有培根披萨;你点了A店的培根披萨,过了二十分钟,你的披萨就来了就可以吃到了。
但这个披萨是怎么做的,到底面粉放了多少,培根放了多少,佐料放了多少,有多少道工序,你是不需要管的,你需要的是一个美味培根披萨。
•策略模式在披萨店,你要一个培根披萨,老板说有标准的pizza,也可以自己去做。
原料有培根、面粉、佐料。
工序有1、2、3工序,你自己去做吧。
然后你就需要自己去做,到底放多少培根,放多少面粉,放多少佐料,这都你自己来决定,工序1、2、3,你是怎么实现的,都你自己决定。
最后你得到了披萨。
代码实现我们用代码来实现上面的不同点:•工厂模式•策略模式。
策略模式 模板方法
策略模式模板方法嘿,策略模式和模板方法啊,我可折腾了好久才总算找到点门道。
我一开始对这俩概念真的是瞎摸索。
先说说策略模式吧,就好比你去旅游,有不同的出行策略。
你可以坐飞机,那速度快,但可能比较贵;你也可以坐火车,性价比挺高;还能自己开车,比较自由。
这每种出行方式就是一个策略。
我开始做个小项目的时候,想要实现根据用户不同需求来做不同操作。
我当时犯了个错,想把这些不同操作都写在一个函数里,结果那函数变得超级复杂,就像一团乱麻一样。
后来我才明白,得把每种操作单独写成一个策略类,像那些出行方式各自独立一样。
这样当需要用到哪个操作的时候,就调用对应策略类就好,清晰多了。
再说模板方法,这就像是做菜。
有个总体的做菜模板,先洗菜、切菜,再下锅炒,最后调味。
但是具体每步怎么做,根据不同菜又有不同。
像炒土豆丝和炒豆角,洗菜切菜炒的时间啥的不一样,但整体框架是一样的。
我做项目里有个数据处理任务,不同数据来源的数据处理步骤大体相同,但具体处理又有差异。
我开始想每个都单独写一套完全不同的方法,代码特别冗余。
后来我就用模板方法,先定好处理数据的整体框架,比如先读取数据、校验数据、处理数据、存储结果。
然后对于不同数据来源,把具体校验和处理的部分抽象出来让子类去实现。
我还试过以前没理解好的时候,把这两个概念混为一谈。
结果做出的项目代码又难维护,逻辑也混乱。
所以一定得清楚,策略模式侧重于算法的替换,是平等的一些策略算法,根据情况调用其中一个。
而模板方法是整体框架不变,一些步骤让子类去定制化。
我又想起一个例子,比如说打印文档。
有不同的打印策略,可以双面打印,单面打印,或者打印彩色的。
这时候用策略模式就合理。
而打印前的文档准备,比如检查格式、分页这些可以作为一个模板,不同类型文档基本这些步骤有个大纲,但具体怎么做在某些情况下可以不同,这就适合模板方法。
把这俩用得好的话,代码可读性可维护性大大提高。
真的要多在项目实际中尝试,才能更好理解这两个概念的妙处。
策略模式的应用场景
策略模式的应用场景一、策略模式简介策略模式是一种行为型设计模式,它定义了算法族,分别封装起来,让它们之间可以互相替换。
此模式让算法的变化独立于使用算法的客户端。
二、策略模式的优点1. 算法可以自由切换:由于策略类实现自同一个接口,所以使得它们之间可以自由切换。
2. 易于扩展:增加一个新的具体策略只需要实现接口即可,符合开闭原则。
3. 避免使用多重条件语句:使用多重条件语句会导致代码臃肿、难以维护和扩展。
4. 提高算法的保密性和安全性:客户端只知道使用了哪些算法,而不知道具体实现细节。
三、应用场景1. 计费系统:对于不同用户类型和消费金额采用不同的计费方式。
2. 游戏开发中的角色技能系统:不同角色拥有不同技能,在游戏中可以根据角色选择相应技能进行攻击或防御。
3. 商城促销活动:根据不同促销活动采取不同的优惠方式,如打折、满减等。
4. 策略模式与工厂方法模式结合使用,可以实现动态创建策略对象,提高代码的灵活性和可扩展性。
5. 策略模式可以用于解决大量的if-else语句,例如根据不同条件选择不同的算法进行计算。
四、实例分析假设有一个电商网站,需要根据用户的购买记录和会员等级进行折扣计算。
会员等级分为普通会员、银卡会员、金卡会员和钻石会员,不同等级享受不同的折扣。
设计一个策略模式来实现该功能。
1. 定义接口DiscountStrategypublic interface DiscountStrategy {double getDiscount(double originPrice);}2. 实现具体策略类NormalDiscountStrategy、SilverDiscountStrategy、GoldDiscountStrategy和DiamondDiscountStrategypublic class NormalDiscountStrategy implements DiscountStrategy {@Overridepublic double getDiscount(double originPrice) {return originPrice;}}public class SilverDiscountStrategy implements DiscountStrategy {@Overridepublic double getDiscount(double originPrice) {return originPrice * 0.9;}}public class GoldDiscountStrategy implements DiscountStrategy {@Overridepublic double getDiscount(double originPrice) {return originPrice * 0.8;}}public class DiamondDiscountStrategy implements DiscountStrategy {@Overridepublic double getDiscount(double originPrice) {return originPrice * 0.7;}}3. 定义Context类public class DiscountContext {private DiscountStrategy discountStrategy;public DiscountContext(DiscountStrategy discountStrategy) {this.discountStrategy = discountStrategy;}public double getFinalPrice(double originPrice) {return discountStrategy.getDiscount(originPrice);}}4. 测试代码public class Test {public static void main(String[] args) {DiscountContext context = new DiscountContext(new NormalDiscountStrategy());double price1 = context.getFinalPrice(100);//不打折,原价100元System.out.println(price1);context = new DiscountContext(new SilverDiscountStrategy());double price2 = context.getFinalPrice(100);//打9折,最终价格90元System.out.println(price2);context = new DiscountContext(new GoldDiscountStrategy());double price3 = context.getFinalPrice(100);//打8折,最终价格80元System.out.println(price3);context = new DiscountContext(new DiamondDiscountStrategy());double price4 = context.getFinalPrice(100);//打7折,最终价格70元System.out.println(price4);}}五、总结策略模式是一种非常实用的设计模式,在实际开发中经常使用。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
策略模式的优点
(1)策略模式提供了管理相关的算法族的方 法。
定义了一系列算法,使这些算法可以相互替换, 自由切换。
(2)策略模式提供了可以替换继承关系的方 法。 (3)使用策略模式可以避免使用多重条件转 移语句。 (4)更好的扩展性
策略模式的缺点
(1)所有的策略模式都需要对外暴露
客户端必须知道所有的策略类,并自行决定使用 哪一个策略类。
• 与享元(Flyweight Pattern)的关系
享元模式类图
如果有多个客户端对象需要调用同样的一些策略类的 话,就可以使它们实现享元模式,这样客户端可以共 享这些策略类。可组合使用。
• 与桥梁(Bridge)模式的关系
两种模式结构图比较
策略模式是一个行为模式,旨在封装一系列的行为 (自由切换算 法) 桥梁模式则是解决在不破坏封装的情况下如何抽取出它的抽象部 分和实现部分(独立扩展)
对象行为型模式
策略模式
刘备江东娶老婆, 赵云伤不起啊~~!!
一、引子
• 假设现在要设计一个贩卖各类书籍的电子商务网 站的购物车(Shopping Cart)系统。一个最简单 的情况就是把所有货品的Байду номын сангаас价乘上数量,但实际 情况肯定比这要复杂。比如,本网站可能对所有 的教材类图书实行每本一元的折扣;对连环画类 图书提供每本7%的促销折扣,而对非教材类的计 算机图书有3%的折扣;对其余的图书没有折扣。 由于有这样复杂的折扣算法,使得价格计算问题 需要系统地解决。 • 那么怎么解决这个问题呢?
• 环境(Context)角色:由 Container类扮演。 • 抽象策略(Strategy)角色: 由LayoutManager类扮演。 此类角色给出所有的具体 Layout类所需的接口。 • 具体策略(ConcreteStrategy) 角色:由 BorderLayout,FlowLayout,Gr idLayout,GridBag,CardLayou t等扮演,它们包装了不同的 Layout行为。
(2)策略模式造成很多的策略类 (3)只适合扁平的算法结构,不适合于处理 同时嵌套多于一个算法的情形。
装饰模式 享元模式 工厂方法模式 门面模式
策略模式与其他模式的关系
• 与建造者(Builder)模式的关系
二者结构上相似。事实上建造模式 是策略模式的一种特殊情况。 这两种模式之间的区别是它们用意 不同。 建造者模式中,核心功能是一步一 步的方式创立一个产品,它的 Director角色一遍一遍调用建造者对 象来把零件增加到产品上,最后返 还整个产品对象。 策略模式,Strategy角色在Context 角色的调用下,不仅可以提供新对 象的创立,还可以提供任何一种服 务。
三种解决方案:
• 所有的业务逻辑都放在客户端里面。客户端利用 条件选择语句决定使用哪一个算法。但是这样, 客户端代码会变得复杂和难以维护。 • 客户端可以利用继承的办法在子类里面实现不同 的行为。但是这样使得环境和行为紧密耦合在一 起。强耦合会使这二者不能单独演化。 • 使用策略模式。策略模式把行为和环境分割开来。 环境类负责维持和查询行为类,各种算法则在具 体策略类中提供。由于算法和环境独立开来,算 法的增减、修改都不会影响环境和客户端。
状态模式结构图
策略模式封装不同的算法,算法之间没有交互,以达到算法自由切 换。 状态模式封装不同的状态,以达到状态切换导致行为发生改变的目 的。
设计原则的讨论
• “开—闭”原则(OCP) 对扩展开放,对修改关闭。 极好体现! • 里氏代换原则(LSP) 所有引用基类的地方必须能透明的使用其子类的 对象。基础! • 迪米特法则(LoD) 一个对象应当对其他对象有尽可能少的了解。违 背!
建造者模式类图
• 与适合器(Adapter)模式的关系
左边是类的适配器模式,右边是对象的适配器模式
二者在结构上相似。它们的区别在于它们的用意不同。 适配器模式的用意是允许一个客户对象通过调用一个配备着 完全不同的接口的对象来完成它原来所要做的功能。 策略模式的用意是使用统一的接口为客户端提供不同的算法。
引进策略模式
• 意图:
• “Define a family of algorithms, encapsulate each one, and make them interchangeable. Strategy lets the algorithm vary independently from clients that use it.”
系统类图
抽象折扣类DiscountStrategy
具体折扣类NoDiscountStrategy
具体折扣类FlatRateStrategy
具体折扣类PercentageStrategy
环境类Discounter
客户端Client
运行结果
使用场合
• 如果一系统里面有许多类,它们之间的区别仅在 于它们的行为,那么使用策略模式可以动态地让 一个对象在许多行为中选择一种行为。 • 一个系统需要动态地在几种算法中选择一种。那 么这些算法可以包装到一个个的具体算法类里面, 而这些具体算法类都是一个抽象算法类的子类。 • 一个系统的算法使用的数据不可以让客户端知道。 策略模式可以避免让客户端涉及到不必要接触到 的复杂的和只与算法有关的数据。 • 如果一个对象有很多种行为,如果不用恰当的模 式,这些行为就只有使用多重的条件选择语句。
• 环境角色类持有一个对策略角色的引用。其源代码:
• 抽象策略类规定所有具体策略略必须实现的接口。其源代 码:
• 具体策略类实现了抽象策略类所声明的接口。其源代码:
• 一般而言,有意义的策略模式的应用都会涉 及到多于一个的具体策略角色。这里只给出 了一个具体策略类,是策略模式的最小实现。
Java语言内部的例子
• 与模板方法(Template)模式的关系
模板方法模式结构图
模板方法模式与策略模式的不同在于,策略模式使用委派的方法提 供不同的算法行为,而模板方法模式使用继承的方法提供不同的算 法行为。 可以组合使用,模板方法重在封装算法骨架,策略模式重在分离并 封装算法的实现。
• 与状态(State)模式的关系
• AWT中的LayoutManager
java.awt类库需要在运行期间动态地由客户端决定 一个Container对象怎样排列它所有的GUI组件。 Java语言提供了几种不同的排列方式,包装在不 同的类里: •BorderLayout •FlowLayout •GridLayout •GridBagLayout •CardLayout
• 与装饰(Decorator)模式的关系
装饰模式的用意在于不改变 接口的情况下,增强一个对 象的功能。 策略模式在保持接口不变的 情况下,使具体算法可以互 换。策略模式只能处理客户 端从几个具体算法中选择一 个的情形,而不能处理客户 端同时选用一种一上算法的 情形。为处理后者,可以组 合使用。
装饰模式类图
策略模式简略类图
策略模式的实现步骤
• 1、定义抽象角色类,定义好各个实现的共 同抽象方法; • 2、定义具体策略类,具体实现父类的共同 方法; • 3、定义环境角色类,私有化申明抽象角色 变量,重载构造方法,执行抽象方法。
策略模式的结构
• 策略模式的类图:
这其中涉及到三个角色: • 环境(Context)角色:持有一个Strategy类的引用。 • 抽象策略(Strategy)角色:这是一个抽象角色,通常由一个接口或抽象类实 现。此角色给出所有的具体策略类所需的接口。 • 具体策略(ConcreteStrategy)角色:包装了相关的算法或行为。
最佳实践
• 诸葛亮给了他三个锦囊, 囊中有三条妙计(走乔国 老的后门、求孙国太放人、 和请孙夫人退兵)嘱咐赵 云“伺机”行事。
周瑜赔了夫人又折兵!!!
我X。。这都行! 伤不起啊!! 伤不起啊!!
Q&A
• From GOF
什么是策略模式
• 策略模式是对算法的包装,是把使用算法的责任和 算法本身分割开,委派给不同的对象管理。 • 策略模式通常把一个系统的算法包装到一系列的策 略类里面,作为一个抽象策略类的子类。 • 策略模式的用意在于把可选的策略或方案封装在不 同的类中,并在这些类中实现一个共同的操作。
排序系统设计如下:
• 客户端必须决定在何时使用哪一个排序算法,换言之,这 个决定不是在模式内部决定的, 客户端需要记住各种排 序方法的名字。
解决图书折扣的计算问题
• 对前述图书销售的问题,折扣是根据以下 几个算法中的一个进行的: 算法一:对有些图书没有折扣。折扣算法 对象返还0作为折扣值。 算法二:对有些图书提供一个固定量值为1 元的折扣。 算法三:对有些图书提供一个百分比的折 扣,比如一本书价格为20元,折扣百分比 为7%,那么折扣值就是20*7%=1.4元。
LayoutManager的类图
一个简单的例子
• 排序策略系统
假设要设计一个排序系统(Sorter System),动 态地决定采用二元排序(Binary Sort),泡沫排 序(Bubble Sort),堆栈排序(Heap Sort), 快速排序(Quick Sort),基数排序(Radix Sort)。 采用策略模式把几种排序算法包装到不同的算法 类里面,让所有的算法都具有相同的接口。