黑马程序员浅谈设计模式-策略模式
深入浅出设计模式之策略模式
分析
• 上面我们采用继承的来解决程序的开放性 和可扩充性;遇到了问题;为什么会这样
• 因为超类作为所有类的父类;拥有所有子类 的共性;但未来会出现什么子类;无从得知; 因此;无法确定哪些是共性方法和共性属性
ቤተ መጻሕፍቲ ባይዱ
继承
• 继承本是为了代码的复用;节省子类的代码 • 但由于未来的不确定性;无法预知子类的多
产生一个新的飞行类
• public class FlyRocketPowered implements FlyBehavior
• public void fly • System out printlnI am flying with
rocket ; •
动态改变行为
Duck model = new ModelDuck; model performFly; model setFlyBehaviornew FlyRocketPowered;
少 • 继承必须有父类和子类;确定父类的属性和
方法很关键
继承的问题
• 代码在多个子类出现不必要的重复 • 无法事先预知所有的子类的所有行为 • 改变父类;会同时改变子类
采用接口
• 接口在Java中是一个非常重要的概念 • Java不支持多继承;但一个类可以实现多个
接口 • 采用接口覆盖鸭子飞和叫的方法;每一个会
• 优秀的OO设计必须具备可复用;可扩充;可 维护的特性
• 模式可以让我们建造更好的质量的软件 • 模式也可以认为是历经考验的OO设计经验
本章要点
• 模式不是具体的代码;是解决问题的思想 • 模式允许软件改变;但改变对软件影响减小 • 系统中变化的部分进行封装 • 模式让高级开发者具有共同语言
– 需求改变 – 平台改变 – 数据改变
策略模式详解
策略模式详解
策略模式是一种行为型设计模式,它定义了一系列算法,并将每一个算法封装起来,使它们可以相互替换。
策略模式使得算法可以独立于使用它的客户端而变化。
策略模式适用于那些需要使用多种算法的问题。
由于每种算法都有其特殊的用途,因此客户端需要根据当前的情况选择最合适的算法。
在这种情况下,策略模式提供了一个灵活且可扩展的框架,使得算法的选择和使用变得简单且易于维护。
在策略模式中,有三个主要的参与者:
1. Strategy:策略接口定义了所有算法的公共接口,客户端通过这个接口来调用算法。
这样,客户端就不需要关心具体的算法实现,只需要根据需要选择相应的策略即可。
2. ConcreteStrategy:具体策略类实现了策略接口,并提供了具体的算法实现。
每个具体策略类都代表了一种特定的算法。
3. Context:上下文对象负责维护策略对象的实例,并根据需要切换不同的策略。
上下文对象通常会根据客户端的请求选择合适的策略对象,并将这个策略对象传递给客户端。
策略模式的优点在于它能够提供一种灵活且可扩展的解决方案,使得算法的选择和使用变得简单且易于维护。
由于策略对象是独立的,因此可以很容易地添加新的策略,而不需要修改现有的代码。
此外,策略模式还可以提供一种替换算法的方式,使得系统能够根据需要进
行动态的调整。
总之,策略模式是一种非常有用的行为型设计模式,它能够提供一种灵活且可扩展的解决方案来解决那些需要使用多种算法的问题。
设计模式之策略模式浅谈以及简单例子
设计模式之策略模式浅谈以及简单例⼦设计模式之策略模式策略模式定义了算法类,分别封装起来,让他们之间可以相互替换,此模式让算法的变化独⽴于使⽤算法的客户。
策略模式是对算法的包装,是把使⽤的责任和算法本⾝分割开来,委派给不同的对象管理。
策略模式通常把⼀个系列的算法包装到⼀系列的策略类⾥⾯,作为⼀个抽象策略类的⼦类。
策略模式涉及到三个⾓⾊:环境(Context)⾓⾊:持有⼀个Strategy的引⽤,也称策略上下⽂。
抽象策略(Strategy)⾓⾊:这是⼀个抽象⾓⾊,通常使⽤抽象类或者接⼝来实现。
此⾓⾊给出所有的具体策略类所需要的接⼝。
具体策略(ConcreteStrategy)⾓⾊:此⾓⾊包装了所有的算法和⾏为。
Eg:商场搞促销,促销⽅式有打折、满100减50等。
在本例中,抽象策略⾓⾊⽤⼀个结果实现,接⼝中有⼀个计算价格的⽅法。
接⼝实现如下:1namespace Strategy_Pattern23 {45///<summary>67///策略接⼝89///</summary>1011interface IPromotion1213 {1415///<summary>1617///根据原价和策略计算新价格1819///</summary>2021///<param name="originalPrice">原价</param>2223///<returns></returns>2425double GetPrice(double originalPrice);2627 }2829 }具体策略⾓⾊有两个,分别表⽰打折类和满100减50,都实现策略接⼝。
打折类实现如下:1 using System;2345 namespace Strategy_Pattern67 {89 /// <summary>1011 /// 打折策略类1213 /// </summary>1415 class Discount : IPromotion1617 {181920212223 #region Public Methods2425 public double GetPrice(double originalPrice) 2627 {2829 Console.WriteLine("打⼋折");3031 return originalPrice * 0.8;3233 }3435 #endregion36373839 }4041 }满100减50类实现如下:/// <summary>/// 返现策略类:满100返50/// </summary>class MoneyBack : IPromotion{#region Public Methodspublic double GetPrice(double originalPrice){Console.WriteLine("满100返50");return originalPrice - (int)originalPrice / 100 - 50; }#endregion}环境(Context)⾓⾊类如下:/// <summary>/// 策略上下⽂类/// </summary>class PromotionContext{#region Fieldsprivate IPromotion m_promotion = null;#endregion#region Constructorspublic PromotionContext(IPromotion iPromotion){this.m_promotion = iPromotion;}#endregion#region Public Methods/// <summary>/// 默认策略⽅法/// </summary>/// <param name="originalPrice"></param>/// <returns></returns>public double GetPrice(double originalPrice){if (this.m_promotion == null){this.m_promotion = new Discount();}return this.m_promotion.GetPrice(originalPrice);}/// <summary>/// 更改策略的⽅法/// </summary>/// <param name="iPromotion"></param>public void ChangePromotion(IPromotion iPromotion){this.m_promotion = iPromotion;}#endregion}然后再主类中调⽤相应的策略,主类实现如下:class Program{static void Main(string[] args){//默认策略:打⼋折的策略PromotionContext promotionContext=new PromotionContext(null);Console.WriteLine(promotionContext.GetPrice(300));//更改策略:满100减50的策略promotionContext.ChangePromotion(new MoneyBack()); Console.WriteLine(promotionContext.GetPrice(100));Console.ReadLine();}}。
java设计模式--策略模式详解
java设计模式--策略模式详解⽬录策略模式Demo代码:总结策略模式策略模式(Strategy Pattern)属于⾏为型模式,指对象有某个⾏为,但是在不同的场景中,该⾏为有不同的实现算法。
⽤算法族分别封装起来,实现同⼀个接⼝,让他们之间可以互相替换,让算法的变化独⽴于使⽤算法的客户。
主要解决:在有多种算法相似的情况下,使⽤ if…else 所带来的复杂和难以维护。
如何解决:将这些算法封装成⼀个⼀个的类,任意地替换。
何时使⽤:⼀个系统有许多许多类,⽽区分它们的只是他们直接的⾏为。
使⽤场景:如果在⼀个系统⾥⾯有许多类,它们之间的区别仅在于它们的⾏为,那么使⽤策略模式可以动态地让⼀个对象在许多⾏为中选择⼀种⾏为。
⼀个系统需要动态地在⼏种算法中选择⼀种。
如果⼀个对象有很多的⾏为,如果不⽤恰当的模式,这些⾏为就只好使⽤多重的条件选择语句来实现。
优点缺点算法可以⾃由切换策略类会增多避免使⽤多重条件判断所有策略类都需要对外暴露扩展性良好环境类(Context):持有抽象策略类的引⽤,⽤来操作策略的上下⽂环境。
抽象策略类(Strategy):策略的抽象类或接⼝,给出所需实现接⼝。
具体策略类(ConcreteStrategy):具体的策略实现。
Demo有⼏种鹅:天鹅、野鹅、灰鹅,鹅有各种⾏为,如飞、游泳、叫等。
假设天鹅灰鹅飞⾏能⼒⼀般,野鹅飞⾏能⼒优秀;天鹅野鹅游泳能⼒⼀般,灰鹅游泳能⼒优秀。
⾸先看第⼀种⽅法:这种⽅法固然可以实现⽬的,但问题显⽽易见,⼦类过多覆盖⽗类⽅法,代码未复⽤,耦合度很⾼。
使⽤策略模式,简单来说,就是封装⼦类⾏为成接⼝,⽗类包含该接⼝即可。
代码:public interface FlyBehavior {void fly();}public class FlyGood implements FlyBehavior {@Overridepublic void fly() {System.out.println("飞⾏能⼒优秀");}}public class FlyNormal implements FlyBehavior {@Overridepublic void fly() {System.out.println("飞⾏能⼒⼀般");}}public interface SwimBehavior {void swim();}public class SwimGood implements SwimBehavior {@Overridepublic void swim() {System.out.println("游得好");}}public class SwimNormal implements SwimBehavior {@Overridepublic void swim() {System.out.println("游得⼀般");}}public abstract class Goose {//策略接⼝FlyBehavior flyBehavior;SwimBehavior swimBehavior;//其他属性等...public void setFlyBehavior(FlyBehavior flyBehavior) {this.flyBehavior = flyBehavior;}public void setSwimBehavior(SwimBehavior swimBehavior) {this.swimBehavior = swimBehavior;}}public class Swan extends Goose{public Swan() {flyBehavior=new FlyNormal();swimBehavior=new SwimNormal();}}public class WildGoose extends Goose{public WildGoose() {flyBehavior=new FlyGood();swimBehavior=new SwimNormal();}}public class GreyGoose extends Goose{public GreyGoose() {flyBehavior=new FlyNormal();swimBehavior=new SwimGood();}}public class Client {public static void main(String[] args) {Swan swan=new Swan();swan.flyBehavior.fly();WildGoose wildGoose=new WildGoose();wildGoose.swimBehavior.swim();GreyGoose greyGoose=new GreyGoose();greyGoose.flyBehavior.fly();greyGoose.setFlyBehavior(new FlyGood()); //改变某个对象的⾏为greyGoose.flyBehavior.fly();}}运⾏结果:总结本篇⽂章就到这⾥了,希望能给你带来帮助,也希望您能够多多关注的更多内容!。
设计模式——策略模式
设计模式——策略模式⼀、定义与简单实现1、定义策略模式的定义包含三点:定义⼀类算法(接⼝)。
封装每个算法(实现类)。
这类算法的算法可互相替换(实现类之间可互相替换)。
2、UML类图前两点已经成了我们的职业习惯(项⽬中⼀般都是⼀接⼝对应⼀实现类),重点是要弄清楚后⾯的算法互相替换,这个替换是在哪⾥实现的,需要达到什么效果?下⾯是⼀个简单的策略模式的UML图。
定义⼀类算法(接⼝FlyBehavior)封装每个算法(实现类CanFly + NotFly)Duck中定义⼀个FlyBehavior变量,然后运⽤组合的⽅式,CanFly、NotFly可以互换定义算法族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化独⽴于使⽤算法的客户,使Duck与Fly()解耦,运⽤的设计模式原则:封装变化多⽤组合,少⽤继承针对接⼝编程,不针对实现编程3、简单代码实现/** 飞翔⾏为*/public interface FlyBehavior {void fly();}public class CanFly implements FlyBehavior {@Overridepublic void fly() {System.out.println("I can fly!");}}public class NotFly implements FlyBehavior{@Overridepublic void fly() {System.out.println("I cant fly!");}}/** 叫声*/public interface QuackBehavior {void quack();}public class GaGa implements QuackBehavior{@Overridepublic void quack() {System.out.println("ga ga ...");}}public class GuaGua implements QuackBehavior {@Overridepublic void quack() {System.out.println("gua gua ...");}}public class NotQuack implements QuackBehavior {@Overridepublic void quack() {System.out.println("...... ??");}}/** 鸭⼦*/public interface DuckInterface {void swim();void display();void performFly();void performQuack();void setFlyBehavior(FlyBehavior flyBehavior);void setQuackBehavior(QuackBehavior quackBehavior); }public class Duck implements DuckInterface {private FlyBehavior flyBehavior;private QuackBehavior quackBehavior;@Overridepublic void swim() {System.out.println("I am swimming!");}@Overridepublic void display() {System.out.println("I have white feathers!");}@Overridepublic void performFly() {if (flyBehavior == null){System.out.println("no flyBehavior!");return;}flyBehavior.fly();}@Overridepublic void performQuack() {if (quackBehavior == null){System.out.println("no quackBehavior!");return;}quackBehavior.quack();}@Overridepublic void setFlyBehavior(FlyBehavior flyBehavior) {this.flyBehavior = flyBehavior;}@Overridepublic void setQuackBehavior(QuackBehavior quackBehavior) {this.quackBehavior = quackBehavior;}}public class Main {public static void main(String[] args) {FlyBehavior canFly = new CanFly();FlyBehavior notFly = new NotFly();//⼀个会飞的鸭⼦DuckInterface duck = new Duck();duck.setFlyBehavior(canFly);duck.performFly();//现在翅膀断了duck.setFlyBehavior(notFly);duck.performFly();}}⼆、框架中的策略模式框架中实现最明显的就是Mybatis中的执⾏器Executor,UML图虽然与给出的标准的策略模式UML有所差异,但是实现的效果⼀致。
设计模式之策略模式(Strategy)详解及代码示例
设计模式之策略模式(Strategy)详解及代码⽰例⼀、策略模式的定义 策略(Strategy)模式的定义:该模式定义了⼀系列算法,并将每个算法封装起来,使它们可以相互替换,且算法的变化不会影响使⽤算法的客户。
策略模式属于对象⾏为模式,它通过对算法进⾏封装,把使⽤算法的责任和算法的实现分割开来,并委派给不同的对象对这些算法进⾏管理。
⼆、策略模式优缺点 策略模式的主要优点如下。
多重条件语句不易维护,⽽使⽤策略模式可以避免使⽤多重条件转移语句。
符合开闭原则,可以在不修改原代码的情况下,灵活增加新算法。
算法使⽤和实现隔离分离,提⾼算法的保密性和安全性。
策略模式提供了⼀系列的可供重⽤的算法族,恰当使⽤继承可以把算法族的公共代码转移到⽗类⾥⾯,从⽽避免重复的代码。
策略模式可以提供相同⾏为的不同实现,客户可以根据不同时间或空间要求选择不同的。
其主要缺点如下。
客户端必须理解所有策略算法的区别,以便适时选择恰当的算法类。
策略模式造成很多的策略类。
三、策略模式的结构与实现 策略模式是准备⼀组算法,并将这组算法封装到⼀系列的策略类⾥⾯,作为⼀个抽象策略类的⼦类。
策略模式的重⼼不是如何实现算法,⽽是如何组织这些算法,从⽽让程序结构更加灵活,具有更好的维护性和扩展性,现在我们来分析其基本结构和实现⽅法。
策略模式的主要⾓⾊如下。
抽象策略(Strategy)类:定义了⼀个公共接⼝,各种不同的算法以不同的⽅式实现这个接⼝,环境⾓⾊使⽤这个接⼝调⽤不同的算法,⼀般使⽤接⼝或抽象类实现。
具体策略(Concrete Strategy)类:实现了抽象策略定义的接⼝,提供具体的算法实现。
环境(Context)类:持有⼀个策略类的引⽤,最终给客户端调⽤。
其结构图如图所⽰: 代码实现如下:public class StrategyPattern{public static void main(String[] args){Context c=new Context();Strategy s=new ConcreteStrategyA();c.setStrategy(s);c.strategyMethod();System.out.println("-----------------");s=new ConcreteStrategyB();c.setStrategy(s);c.strategyMethod();}}//抽象策略类interface Strategy{public void strategyMethod(); //策略⽅法}//具体策略类Aclass ConcreteStrategyA implements Strategy{public void strategyMethod(){System.out.println("具体策略A的策略⽅法被访问!");}}//具体策略类Bclass ConcreteStrategyB implements Strategy{public void strategyMethod(){System.out.println("具体策略B的策略⽅法被访问!");}}//环境类class Context{private Strategy strategy;public Strategy getStrategy(){return strategy;}public void setStrategy(Strategy strategy){this.strategy=strategy;}public void strategyMethod(){strategy.strategyMethod();}} 测试结果如下:具体策略A的策略⽅法被访问!-----------------具体策略B的策略⽅法被访问! 如下补充⼀个促销策略模式:interface PromotionStrategy {void doPromotion();}class FanXianPromotionStrategy implements PromotionStrategy{@Overridepublic void doPromotion() {System.out.println("返现促销");}}class LiJianPromotionStrategy implements PromotionStrategy {@Overridepublic void doPromotion() {System.out.println("⽴减促销");}}class ManJianPromotionStrategy implements PromotionStrategy{@Overridepublic void doPromotion() {System.out.println("满减促销");}}class PromotionActivity {private PromotionStrategy promotionStrategy;public PromotionActivity(PromotionStrategy promotionStrategy) {this.promotionStrategy = promotionStrategy;}public void executePromotionStrategy(){promotionStrategy.doPromotion();}}public class Test {public static void main(String[] args) {PromotionActivity promotionActivity618 = new PromotionActivity(new LiJianPromotionStrategy());PromotionActivity promotionActivity1111 = new PromotionActivity(new FanXianPromotionStrategy());promotionActivity618.executePromotionStrategy();promotionActivity1111.executePromotionStrategy();}}四、策略模式的应⽤场景 策略模式在很多地⽅⽤到,如 Java SE 中的容器布局管理就是⼀个典型的实例,Java SE 中的每个容器都存在多种布局供⽤户选择。
策略模式在运行时选择算法的设计模式
策略模式在运行时选择算法的设计模式设计模式是一种被广泛应用于软件开发中的解决问题的方案。
其中,策略模式是一种在运行时选择算法的设计模式,它允许在不改变对象的结构的情况下,动态地选择需要执行的算法。
一、策略模式的定义和原则策略模式是一种行为型设计模式,它通过定义一系列的算法,封装每个算法,并使它们可以互换。
策略模式使得算法的选择与使用的客户端代码分离,实现了代码的解耦。
策略模式遵循以下原则:1. 将变化的部分独立出来:策略模式将算法封装成策略类,将变化的部分(不同的算法)与不变的部分(调用算法的代码)分离开来。
2. 面向接口编程:策略模式通过定义统一的接口或抽象类,让具体的策略类实现该接口或继承该抽象类,确保所有的策略类都具有一致的行为。
3. 运行时选择算法:策略模式允许在运行时动态地选择要使用的算法,而不是在编译时固定地选择。
二、策略模式的结构策略模式由三个核心部分组成:上下文(Context)、策略(Strategy)和具体策略(Concrete Strategy)。
1. 上下文(Context):上下文是一个包含策略的引用的类,它在运行时通过策略的具体实现来执行某个算法。
2. 策略(Strategy):策略是一个抽象类或接口,它定义了算法的公共接口。
3. 具体策略(Concrete Strategy):具体策略是策略的具体实现,它实现了策略接口或抽象类中定义的算法。
三、策略模式的应用场景策略模式通常在以下情况下使用:1. 当一个系统需要多个算法中的一种来执行特定任务时,可以使用策略模式。
2. 当一个系统需要动态地切换算法时,可以使用策略模式。
3. 当一个对象需要根据不同的情况执行不同的算法时,可以使用策略模式。
四、策略模式的优缺点策略模式具有以下优点:1. 算法的选择与使用的客户端代码分离,增强了代码的灵活性和可维护性。
2. 策略模式将每个算法封装成独立的类,方便了算法的复用和扩展。
3. 策略模式符合开闭原则,增加新的策略不需要修改现有代码。
黑马程序员C语言教程:常见的六种设计模式
常见的六种设计模式以及应用场景设计模式是对设计原则的具体化。
用江湖话说就是武林秘籍,总结出来的一些固定套路,可以帮助有根基的程序员迅速打通任督二脉,从此做什么都特别快。
常用的模式及其场景如下。
1) 单例模式。
单例模式是一种常用的软件设计模式。
在它的核心结构中只包含一个被称为单例类的特殊类。
通过单例模式可以保证系统中一个类只有一个实例而且该实例易于外界访问,从而方便对实例个数的控制并节约系统资源。
应用场景:如果希望在系统中某个类的对象只能存在一个,单例模式是最好的解决方案。
2) 工厂模式。
工厂模式主要是为创建对象提供了接口。
应用场景如下:a. 在编码时不能预见需要创建哪种类的实例。
b. 系统不应依赖于产品类实例如何被创建、组合和表达的细节。
3) 策略模式。
策略模式:定义了算法族,分别封装起来,让它们之间可以互相替换。
此模式让算法的变化独立于使用算法的客户。
应用场景如下。
a. 一件事情,有很多方案可以实现。
b. 我可以在任何时候,决定采用哪一种实现。
c. 未来可能增加更多的方案。
d. 策略模式让方案的变化不会影响到使用方案的客户。
举例业务场景如下。
系统的操作都要有日志记录,通常会把日志记录在数据库里面,方便后续的管理,但是在记录日志到数据库的时候,可能会发生错误,比如暂时连不上数据库了,那就先记录在文件里面。
日志写到数据库与文件中是两种算法,但调用方不关心,只负责写就是。
4) 观察者模式。
观察者模式又被称作发布/订阅模式,定义了对象间一对多依赖,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新。
应用场景如下:a.对一个对象状态的更新,需要其他对象同步更新,而且其他对象的数量动态可变。
b.对象仅需要将自己的更新通知给其他对象而不需要知道其他对象的细节。
5) 迭代器模式。
应用场景如下:当你需要访问一个聚集对象,而且不管这些对象是什么都需要遍历的时候,就应该考虑用迭代器模式。
其实stl容器就是很好的迭代器模式的例子。
黑马程序员浅谈设计模式-单例设计模式
【黑马程序员济南】单例设计模式我们一般在学习的第一个设计模式都是单例设计模式,因为单例设计模式广泛的应用在我们程序开发中。
黑马程序员济南校区的小鲁哥哥从今天就和大家简单的聊一聊设计模式的那些事,不专业仅是个人观点。
我们今天就先聊一聊单例设计模式,因为在我们刚开始学习Java基础时,就了解了单例,有的同学在学习时非常困惑,不明白什么是单例,不明白在什么场景下会用到单例设计模式。
我们先说一下单例的概念:保证一个类仅有一个实例,并提供一个访问它的全局访问点。
通过概念我们可以简单的知道,所谓的单例模式就是保证我们定义的类在我们的程序中只能new出一个对像(实例)。
在一些特定情况下,我们只允许类只能实例化一次,这种情况下我们就需要用到了单例设计模式。
说了这么多,我们写一个初级的单例给大家展示一下:Class Single{private static Single instance;Private Singleton(){}Public static Single getInstance(){If(instance == null){Instance = new Single();}Return instance;}}大家可以看到,我们是如何保证这个类只能被实例化一次的,首先1、我们对它的构造函数进行私有化,确保外部的类不能对他进行实例化。
2、提供一个静态方法来获取当前类对象。
如果外部类想访问这个类对象,我们可以通过类名.getInstance()的方法来获取Single的类对象。
单例设计模式又分为两种,饱汉式和饿汉式。
饱汉式:package com.lxk.designPattern.singleton;/*** 饱汉式(懒汉式)----就是有钱,豪,用的时候再new(线程不安全)* <p>* Created by lxk on 2017/3/23*/public class Single1 {//这个就不能加final,因为要在其他地方给他再次赋值呢。
设计模式(一):策略模式
设计模式(⼀):策略模式 现实⽣活中,我们要做⼀件事情或者完成某项⼯作,往往有很多种途径。
⽐如我们出游,可以选择坐汽车,坐⽕车,⼟豪点的选择是坐飞机。
还有我们现在线下的⽀付⽅式也有了很多种选择,以前在外⾯忘了带钱的话可能⼀瓶⽔都难以买到,现在只要我们⼿机在⾝上,可以⽤微信或者⽀付宝。
在软件设计层⾯,我们把各种⽀付⽅式叫做策略。
如果不考虑设计模式的话,我们可能会在⼀个类中⽤if..else⽅式来选择⽀付⽅式,即if(type == 1){//微信⽀付}else if(type == 2){// ⽀付宝⽀付}else if(type == 3){//现⾦⽀付}但如果以后要改变⽀付⽅式,⽐如不能⽤微信⽀付了,或者新增了其他⽀付⽅式,我们就要改变这个类,这会带来代码维护的⿇烦。
.模式结构和定义 下图为策略模式的结构: 从图中我们看到,客户context拥有成员变量strategy(策略),⾄于需要⽤到那种策略,我们可以在构造器中指定。
策略模式的定义是:定义算法族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化独⽴于使⽤算法的客户。
这算法体现了⼏个设计原则,第⼀、把变化的代码从不变的代码中分离出来;第⼆、针对接⼝编程⽽不是具体类(定义了策略接⼝);第三、多⽤组合,少⽤继承(客户通过组合⽅式使⽤策略)。
.应⽤实例 下⾯以公司职员的⼯作内容为例介绍策略模式 定义策略接⼝,就是⼯作内容interface DoWorking{public void comeOn();} 编码类实现策略接⼝DoWorkingclass Coding implements DoWorking{public void comeOn(){System.out.println("I'm coding....");}} 审计类实现策略接⼝DoWorkingclass auditing implements DoWorking{public void comeOn(){System.out.println("我正在审计财务报表....");}} 招聘类实现策略接⼝DoWorkingclass recruiting implements DoWorking{public void comeOn(){System.out.println("I'm recruting new employees...");}} 定义客户端职员类,其中包含成员变量doWorking(策略),以及开展⼯作的⽅法startWork() class Employee{public DoWorking doWorking;//组合的⽅式使⽤策略public void startWork(){eOn();}} 客户端程序员继承职员类class Coder extend Employee{public Coder(){doWorking = new Coding();//使⽤编码策略}} 测试程序员调⽤策略public class StrategyClient {public static void main(String[] args){Employee coder = new Coder();coder.startWork();}} 运⾏结果: I'm coding.... 1.优点 (1).体现了“对修改关闭,对扩展开放”原则,客户端增加⾏为不⽤修改原有代码,只要添加⼀种策略即可。
黑马程序员:IOS面试宝典之设计模式
黑马程序员:IOS面试宝典之设计模式1. 什么是设计模式设计模式是为特定场景下的问题而定制的解决方案。
特定场景指问题所在的重复出现的场景,问题指特定环境下你想达成的目标。
同样的问题在不同的环境下会有不同的限制和挑战。
定制的解决方案是指在特定环境下克服了问题的限制条件而达成目标的一种设计。
2. 设计模式的分类设计模式分为三种类型,共23种。
创建型模式:单例模式、抽象工厂模式、建造者模式、工厂模式、原型模式。
结构型模式:适配器模式、桥接模式、装饰模式、组合模式、外观模式、享元模式、代理模式。
行为型模式:模版方法模式、命令模式、迭代器模式、观察者模式、中介者模式、备忘录模式、解释器模式(Interpreter模式)、状态模式、策略模式、职责链模式(责任链模式)、访问者模式。
3. 类工厂方法是什么?类工厂方法的实现是为了向客户提供方便,它们将分配和初始化合在一个步骤中,返回被创建的对象,并进行自动释放处理。
这些方法的形式是+ (type)className...(其中className不包括任何前缀)。
工厂方法可能不仅仅为了方便使用。
它们不但可以将分配和初始化合在一起,还可以为初始化过程提供对象的分配信息。
类工厂方法的另一个目的是使类(比如NSWorkspace)提供单件实例。
虽然init...方法可以确认一个类在每次程序运行过程只存在一个实例,但它需要首先分配一个“生的”实例,然后还必须释放该实例。
工厂方法则可以避免为可能没有用的对象盲目分配内存。
4. 单件实例是什么?Foundation 和Application Kit 框架中的一些类只允许创建单件对象,即这些类在当前进程中的唯一实例。
举例来说,NSFileManager 和NSWorkspace 类在使用时都是基于进程进行单件对象的实例化。
当向这些类请求实例的时候,它们会向您传递单一实例的一个引用,如果该实例还不存在,则首先进行实例的分配和初始化。
Java设计模式之(十四)——策略模式
Java设计模式之(⼗四)——策略模式1、什么是策略模式?Define a family of algorithms, encapsulate each one, and make them interchangeable. Strategy lets the algorithm vary independently from clients that use it.策略模式(Strategy Pattern):定义⼀族算法类,将每个算法分别封装起来,让它们可以互相替换。
2、策略模式定义①、Context封装⾓⾊它也叫做上下⽂⾓⾊,起承上启下封装作⽤,屏蔽⾼层模块对策略、算法的直接访问,封装可能存在的变化。
②、Strategy 抽象策略⾓⾊策略、算法家族的抽象,通常为接⼝,定义每个策略或算法必须具有的⽅法和属性。
③、ConcreteStrategy 具体策略⾓⾊实现抽象策略中的操作,该类含有具体的算法。
3、策略模式通⽤代码public class Context {// 抽象策略private Strategy strategy = null;// 构造函数设置具体策略public Context(Strategy strategy) {this.strategy = strategy;}// 封装后的策略⽅法public void doAnything(){this.strategy.doSomething();}}public interface Strategy {// 策略模式的运算法则public void doSomething();}public class ConcreteStrategy1 implements Strategy{@Overridepublic void doSomething() {System.out.println("ConcreteStrategy1");}}public class ConcreteStrategy2 implements Strategy{@Overridepublic void doSomething() {System.out.println("ConcreteStrategy2");}}测试:public class StrategyClient {public static void main(String[] args) {// 声明⼀个具体的策略Strategy strategy = new ConcreteStrategy1();// 声明上下⽂对象Context context = new Context(strategy);// 执⾏封装后的⽅法context.doAnything();}}4、⽤策略模式改写if-else假设我们要处理⼀个office⽂件,分为三种类型 docx、xlsx、pptx,分别表⽰Word⽂件、Excel⽂件、PPT⽂件,根据⽂件后缀分别解析。
黑马程序员浅谈设计模式-工厂设计模式
【黑马程序员济南】简单工厂设计模式我们都知道面向对象编程有三大特征:封装,集成和多态,那我们如何在实际开发中去灵活运用它呢,今天我给大家聊一聊简单工厂设计模式。
简单工厂设计模式的一个核心思想就是高内聚,低耦合,使具体的业务逻辑实现功能和效果展示分离开来。
先给大家举一个没有应用到工厂设计模式的例子:题目:要求设计一个计算器程序,输入两个数和一个运算符号,计算出结果。
我们先写一个没有用到简单工厂设计模式的代码:publicclass Progrtam {publicstaticvoid main(String[] args){Console console = System.console();try{console.printf("输入数字A");String strNumberA = console.readLine();console.printf("请选择运算符号(+,-,*,/)");String strOperate = console.readLine();String strNumberB = console.readLine();String strResult = "";switch(strOperate){case"+":strResult = String.valueOf(strNumberA+strNumberB);break;case"-":strResult =String.valueOf(Double.valueOf(strNumberA)-Double.valueOf(strNumberB));case"*":strResult =String.valueOf(Double.valueOf(strNumberA)*Double.valueOf(strNumberB));break;case"/":strResult =String.valueOf(Double.valueOf(strNumberA)/Double.valueOf(strNumberB));break;}console.printf("结果是:"+strResult);console.readLine();}catch(Exception ex){console.printf("您输入有误:"+ex.getMessage());}}}大家可以看到,业务逻辑和效果展示都在一个类里边,这样就是高耦合的体现,如果我们创建一个其他的预算符号是,就需要在写一个类,或者在这个类里直接修改,这在我们的编程思想中使非常不合理的,需要浪费大量的时间去做重复的代码工作,影响我们的效率。
设计模式之策略模式详细介绍
设计模式之策略模式详细介绍嘿,大家好,今天咱们聊聊一个超级实用的设计模式——策略模式。
别担心,听起来复杂,但其实它就像生活中的调味料,适时加点,味道立马就不一样了!那么,什么是策略模式呢?简单来说,就是把算法封装起来,让它们可以互相替换,简直就是为程序设计量身定做的灵活性!1. 策略模式的基本概念1.1 策略模式的定义首先,咱们得搞明白什么是策略模式。
想象一下,你去餐馆点菜,菜单上有各种各样的选择,你可以根据自己的口味、心情甚至天气来决定。
策略模式就像这个菜单,让你可以在运行时自由选择用什么“策略”来完成任务。
也就是说,把实现某个功能的具体方法放在不同的策略类中,这样用的时候只要挑一个就行,省时省力,简单明了!1.2 策略模式的构成在策略模式中,主要有三个角色:环境(Context)、策略接口(Strategy)和具体策略(ConcreteStrategy)。
环境就像你去餐馆的服务员,策略接口就像菜单上所有的菜名,而具体策略就是菜品的具体做法。
比如,你要点一个“红烧肉”,那“红烧肉”的具体做法就是“具体策略”,而“红烧肉”这个名字就是“策略接口”。
哎呀,听起来是不是感觉肚子饿了呢?2. 策略模式的优缺点2.1 策略模式的优点说到优点,策略模式简直就是如鱼得水,优势多多。
首先,它提高了代码的灵活性和可读性。
你可以很方便地添加新的策略而不影响现有的代码,简直就像给你的程序加了新菜单一样!其次,策略模式能有效地减少条件语句,避免了“ifelse”地狱。
谁还想每天面对成堆的条件判断,真是烦死人了。
2.2 策略模式的缺点当然,策略模式也不是完美无瑕的,缺点也得提一提。
首先,策略类的数量可能会暴涨,管理起来就像打理一堆杂乱的花园,容易让人头疼。
其次,使用策略模式可能会增加系统的复杂性,特别是当策略类和环境类的关系比较复杂时。
就像有时候你不太确定自己点的是什么菜,搞得一头雾水。
3. 策略模式的应用场景3.1 策略模式在电商中的应用接下来,咱们聊聊策略模式在实际开发中的应用吧!以电商网站为例,购物车的计算就可以用策略模式来处理。
设计模式之==策略设计模式
设计模式之==策略设计模式⼀、什么是策略设计模式 策略设计模式(Strategy Pattern)定义了⼀系列的算法,并将每⼀个算法封装起来,⽽且使它们之间可以互相替换。
策略模式让算法的变化不会影响到使⽤算法的客户。
分析下定义,策略模式定义和封装了⼀系列的算法,它们是可以相互替换的,也就是说它们具有共性,⽽它们的共性就体现在策略接⼝的⾏为上,另外为了达到最后⼀句话的⽬的,也就是说让算法独⽴于使⽤它的客户⽽独⽴变化,我们需要让客户端依赖于策略接⼝。
⼆、策略设计模式结构图这个类图并不复杂,右边是策略接⼝以及它的实现类,左边会有⼀个上下⽂,这个上下⽂会拥有⼀个策略,⽽具体这个策略是哪⼀种,我们是可以随意替换的三、策略模式写法举例我们需要实现这样⼀个功能:我们需要对⼀批不同格式的⽂件进⾏处理⽂件类型有 mp4,avi,rmvb,不同格式的⽂件使⽤不同的⽂件解析器来解析⽂件⽂件类型可不⼀定只有这⼏种,随着业务的扩展会不断增加,⽐如 : txt, jpg,png等等下⾯,我们使⽤策略设计模式来实现这个功能:⾸先,先来定义⼀个⽂件类型的枚举和⾃定义的⼀个⽂件类,⽤于描述我们处理的⽂件类型public class MyFile {private FileType fileType;private String fileName;private String filePath;public MyFile(Builder builder) {this.fileType = builder.fileType;this.fileName = builder.fileName;this.filePath = builder.filePath;}public static Builder builder() {return new Builder();}public static class Builder {private FileType fileType;private String fileName;private String filePath;public Builder fileType(FileType fileType) {this.fileType = fileType;return this;}public Builder fileName(String fileName) {this.fileName = fileName;return this;}public Builder filePath(String filePath) {this.filePath = filePath;return this;}public MyFile build() {return new MyFile(this);}}public FileType getFileType() {return fileType;}public String getFileName() {return fileName;}public String getFilePath() {return filePath;}@Overridepublic String toString() {return "MyFile{" +"fileType=" + fileType +", fileName='" + fileName + '\'' +", filePath='" + filePath + '\'' +'}';}}MyFilepublic enum FileType {MP4,AVI,RMVB,PNG}FileType再来,定义策略接⼝,相当于结构图中的 Strategy 接⼝public interface IStrategy<T> {void parse(T t);}这⾥也可以不使⽤泛型,因为我们在前⾯定义了⽂件描述的类 MyFile然后,是三个具体的策略类,分别是 mp4,avi,rmvb 三种格式⽂件的解析器,相当于结构图中的 ConcreteStrategypublic class Mp4ParserStrategy implements IStrategy<MyFile> {@Overridepublic void parse(MyFile file) {System.out.println("Mp4ParserStrategy.parse file=" + file);}}Mp4ParserStrategypublic class AviParserStrategy implements IStrategy<MyFile> {@Overridepublic void parse(MyFile file) {System.out.println("AviParserStrategy.parse file=" + file);}}AviParserStrategypublic class RmvbParserStrategy implements IStrategy<MyFile> {@Overridepublic void parse(MyFile file) {System.out.println("RmvbParserStrategy.parse file=" + file);}}RmvbParserStrategy这⾥没有实现解析器的功能,只是进⾏了简单的描述再下来是上下⽂,⼜或者叫策略管理的类,相对于结构图中的 Contextpublic final class ParserStrategyManager {private final Map<FileType, IStrategy<MyFile>> strategyMap;private ParserStrategyManager() {this.strategyMap = Maps.newConcurrentMap();this.strategyMap.put(FileType.AVI, new AviParserStrategy());this.strategyMap.put(FileType.MP4, new Mp4ParserStrategy());this.strategyMap.put(FileType.RMVB, new RmvbParserStrategy());}public void doParser(MyFile file) {if (!strategyMap.containsKey(file.getFileType())) {throw new IllegalStateException("⽆法处理这种格式的⽂件");}this.strategyMap.get(file.getFileType()).parse(file);}private static class ClassHolder {private static final ParserStrategyManager INSTANCE = new ParserStrategyManager();}public static ParserStrategyManager getInstance() {return ClassHolder.INSTANCE;}}ParserStrategyManager在这个类中,我们将⽂件类型和策略解析器以 Key,Value的形式存⼊⼀个Map当中,这样客户端在调⽤时只需传⼊⽂件的相关属性(包括⽂件类型),我们就根据⽂件类型找到⽂件对应的解析器进⾏解析,后续如果增加了其他的⽂件类型,只需要在 FileType 中增加类型并且增加具体的解析策略类,最后在 ParserStrategyManager 类中将⽂件类型和对应的解析策略类维护进 Map当中就可以了。
设计模式四:策略模式
设计模式四:策略模式策略模式所谓策略其实就是做⼀件事情有很多很多的⽅法,⽐如说⼀个商场要搞促销,促销的⽅式有可能有很多:打折啊,满100返50啊、积分等等之类的。
这种不同的促销⽅式在我们系统中表⽰就是⼀个⼀个的策略,并且策略是可以随时更换的,这个时候在设计系统时就可以使⽤策略模式。
商场有可能会更换或追加新的促销模式,也就是策略存在调整,也就是会更改以前的代码,为了满⾜开闭原则,这时就要使⽤抽象类和接⼝,这⾥我们偏向使⽤接⼝。
在接⼝⾥⾯定义策略的⽅法,根据不同的情况编写不同的实现类,实现不同的策略,策略模式⽐较适⽤于算法经常变化的情况,⽐如计算⼯资的⽅式、出⾏⽅式的选择等等。
如图所⽰,我们先定义策略的接⼝(Promotion),然后在这个策略接⼝⾥定义策略的⽅法(GetPrice()),接着我们定义了两种具体的策略(Discount打折)和(MoneyBack返现)。
策略模式会专门有⼀个上下⽂对象(PromotionContext)专门管理策略类,并且上下⽂对象和策略接⼝之间是聚合的关系,也就是整体和部分的关系,因此在上下⽂对象⾥应该保存⼀个促销类型的引⽤,另外上下⽂对象⾥⼀般会有⼀些⽅便客户端调⽤的⽅法,如GetPrice()。
客户端程序可以通过上下⽂对象得到价格,这个GetPrice()⾥会根据不同的策略,执⾏不同的策略⽅法。
如果客户端不想使⽤上下⽂中定义的默认的策略,也可以去修改策略类,因为上下⽂中有⼀个ChangePromotion()的⽅法,客户端主要使⽤上下⽂对象,如果需要修改策略,他还要依赖于具体的策略对象。
⽰例:1、策略接⼝:1using System;2using System.Collections.Generic;3using System.Linq;4using System.Text;5using System.Threading.Tasks;67namespace策略模式8 {9/*10策略接⼝11*/12public interface IPromotion13 {14///<summary>15///根据原价和策略计算新价格16///</summary>17///<param name="originPrice">原价</param>18///<returns></returns>19double GetPrice(double originPrice);20 }21 }2、Discount打折策略类1using System;2using System.Collections.Generic;3using System.Linq;4using System.Text;5using System.Threading.Tasks;67namespace策略模式8 {9///<summary>10///打折策略类11///</summary>12public class Discount :IPromotion13 {1415public double GetPrice(double originPrice)16 {17 Console.WriteLine("打⼋折:");18return originPrice * 0.8;19 }20 }21 }3、MoneyBack返现类1using System;2using System.Collections.Generic;3using System.Linq;4using System.Text;5using System.Threading.Tasks;67namespace策略模式8 {9/*10返现策略类:满100返50的策略11*/12class MoneyBack :IPromotion13 {14public double GetPrice(double originPrice)15 {16 Console.WriteLine("满100返50");17return originPrice - (int)originPrice / 100 * 50;18 }19 }20 }4、策略上下⽂类1using System;2using System.Collections.Generic;3using System.Linq;4using System.Text;5using System.Threading.Tasks;67namespace策略模式8 {9/*10策略上下⽂,为客户选择合适的策略11*/12public class PromotionContext13 {14private IPromotion p = null;1516public PromotionContext(IPromotion p)17 {18this.p = p;19 }2021public double GetPrice(double originPrice)22 {23// 默认策略24if (this.p == null)25 {26this.p = new Discount();27 }28return this.p.GetPrice(originPrice);29 }3031///<summary>32///更改策略的⽅法33///</summary>34///<param name="p"></param>35public void ChangePromotion(IPromotion p)36 {37this.p = p;38 }39 }40 }5、主程序调⽤1using System;2using System.Collections.Generic;3using System.Linq;4using System.Text;5using System.Threading.Tasks;67namespace策略模式8 {9class Program10 {11static void Main(string[] args)12 {13// 默认策略:打⼋折的策略14 PromotionContext pc = new PromotionContext(null);15 Console.WriteLine(pc.GetPrice(200)) ;1617// 更改策略:满100返50的策略18 pc.ChangePromotion(new MoneyBack());19 Console.WriteLine(pc.GetPrice(155.9));20 Console.ReadKey();21 }22 }23 }代码连接地址:https:///files/dotnet261010/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F.rar。
黑马程序员的经验结晶-设计模式讲义
黑马程序员设计模式之装饰者与工厂方法内容简介设计模式(Design pattern)代表了最佳的实践,是软件开发人员在软件开发过程中面临一般问题的解决方案,是优秀程序猿的经验结晶. 本次课程我们重点介绍设计模式中装饰者和工厂方法.装饰者设计模式动态给一个对象增加额外功能;若要扩展对象的功能,装饰者提供了比继承更具有弹性的方案.工厂方法设计模式精髓在于封装类中不变的部分,提取其中个性化善变的部分为独立类,降低程序的耦合度,提高了程序扩展性.知识点●面对对象编程原则之少用继承多用组合●面向对象编程原则之面向接口编程●设计模式之装饰者●简单工厂●面向对象编程原则之封装变化●设计模式之工厂方法第一章:设计模式之装饰者欢迎来到喜茶店喜茶店只供应两种饮料茗茶和咖啡,他们最初系统是这样的}为了吸引顾客,喜茶店提供了两种配料:芝士(Cheese),火腿(Ham),可以组合搭配每一种饮料. 通过继承来实现吗? 我们试试看,来看类图。
这只有两种饮料,两种配料就产生这么多类,每增加一种饮料或配料,类就呈几何级增长. 有的哥们会说这么烂的设计,干嘛不使用组合呢? 我们接下来组合一下.面向对象原则:少用继承,多用组合继承是是一个(is a) 关系,而组合是有一个(has a) 关系,也就是一个类中有另外一个类的引用. 为什么要少用继承,多用组合呢?1.继承可能会导致类的无限膨胀.2.继承关系是一种耦合度非常高的关系,因为一旦父类行为发生变化,子类也将受到影响。
3.而组合关系耦合度就没有那么高,尤其在组合“接口”时候,程序会变得更加灵活.注意: 我在这里讲的接口都是指的抽象类或接口.使用组合实现需求public class Cheese {public String desc(){return"芝士";}public double cost(){return 2.5;}}public class Ham {// 来一份双芝士的咖啡. 本店不提供!!!}}出现无法实现双份芝士的需求,并且如果增加一种配料必须修改原有的类,饮料类严重依赖具体配料类.面向对象原则:面向接口编程面向接口编程: 不要针对具体的类,而要针对接口; 因为具体的类总是善变的,而抽象的接口是相对稳定的.认识装饰者模式我们现在了解直接使用继承会产生类爆炸,直接组合也无法实现双份芝士的需求,并且让每一种饮料对配料都特别的依赖.我们来换一种思路,我们可不可以使用配料对饮料进行装饰(decorate)呢? 比如: 顾客要一份芝士火腿茗茶.1.创建一个茶(Tea)对象2.使用火腿(Ham)对它装饰3.使用芝士(Cheese)对它装饰那么如何计算最终价格,我们可以一层一层的加上去. 来看图装饰者模式的特点●装饰者与被装饰者要有相同的超类●你可以使用一个或多个装饰者装饰一个对象●由于装饰者和被装饰者相同的超类,所以在使用被装饰者的地方都可以使用装饰者替代●装饰者可以在调用被装饰者的方法之前或之后加上自己行为,已达到特定的目的.●你可以在运行时,不限量使用你喜欢的装饰者来装饰对象装饰者模式的定义装饰者模式: 动态给对象增加功能,若要扩展功能,装饰者提供了比继承更有弹性的方案.我们现在知道了装饰者模式的特点和定义,怎么把装饰应用起来呢? 我们来看装饰者类图接下来装饰我们的饮料.接下来我们来使用装饰者完成我们代码.◆从Beverage(饮料)开始,Beverage是一个接口不用动.}装饰者在实际开发中的应用装饰者在实际开发中有很多的应用场景,比如IO流中应用,Web中解决程序的乱码问题等. 我们接下看一下,IO流中是如何使用装饰者模式的呢?. 来看类图我们接下给InputStream增加一个装饰者,用于把读取数据中的大写转换为小写. 比如:data.txt中内容为“I Love Java,I Love HeiMa.”转换后为“i love java, i love heima.”代码实现public class LowercastInputStream extends FilterInputStream {protected LowercastInputStream(InputStream in) { super(in);}@Overridepublic int read() throws IOException {int ch = super.read();// 如果是大写,就转换为小写if(ch >= 'A' && ch <= 'Z'){ch = Character.toLowerCase(ch);}return ch;装饰者的缺陷①可能会产生大量的小类,增加了系统复杂性.②采用装饰这模式的时候,实例化“组件”的时候,可能还需要实例化“装饰者”天晓得实例化多少个!你的代码就特别依赖这些装饰类,从导致程序不容易维护, 但是这个通过工厂模式加以解决!第二章:工厂模式简单工厂我们再回头看一下之前的TeaStore类你有没有发现什么问题啊? 是不是出现了很多new啊,new 有问题吗? 凡是new的是不是都是具体的类啊. 这样TeaStore是不是依赖每一个具体的饮料类和装饰类啊. 这样一旦我减少或增加一种饮料或配料都要修改这个类,是不是很烦啊. 我们可不可以把这些创建对象的操作封装到一个其他类中,创建完毕后返回一个抽象的接口类型的对象.定义简单工厂类我们希望,只要TeaStore(茶店)给工厂下一个订单,工厂就可以把TeaStore需要的饮料生产出来. 订单格式为: 芝士火腿咖啡,如果是双芝士,就是芝士芝士咖啡.在TeaStore中使用简单工厂类但是我觉得对TeaStore来说还是太麻烦了,我希望TeaStore直接给工厂下一个订单,工厂就能生产出对应产品出来.Beverage t = bf.order("茶");System.out.println(t.desc() + "\t" + t.cost());// 来一杯芝士咖啡Beverage c1 = bf.order("芝士咖啡");System.out.println(c1.desc() + "\t" + c1.cost());// 来一份双芝士的咖啡.Beverage c2 = bf.order("芝士芝士咖啡");System.out.println(c2.desc() + "\t" + c2.cost());// 来一份芝士火腿茶Beverage c3 = bf.order("芝士火腿茶");System.out.println(c3.desc() + "\t" + c3.cost());}}◆来看一下现在依赖关系图有的人可能会觉得,你这样搞完只是TeaStore不依赖具体的类了,但是BeverageFactory还是依赖具体的类啊,没错,确实是这样。
黑马程序员浅谈设计模式-单一职责模式
【黑马程序员济南】单一职责模式今天和大家聊一聊单一职责模式,大家从名字应该就能想到这个设计模式的核心思想就是降低耦合性,强调一个类/整体只做一件事。
今天就不给大家代码举例子了,因为这个会很好理解,你只要写一个类,强调一个方法,方法只实现一种功能举行啦!单一职责模式:就一个类而言,应该仅有一个引起它变化的原因。
有的同学会问,一个类如果只是有且仅有一个因素来引起他的变化,岂不是我们的程序的代码会非常臃肿?这个情况我们要视情况而定,其实在生活中也是,我们如果做到一件事情的专精,那就要舍弃一些其他方面的功能。
例如我们的手机可以照相,但是他的专业程度不如数码摄像机,再比如我们的交通工具,汽车负责马路,轮船负责大海,飞机负责天空一样,我们要做到一件事情让他专精一个功能。
在一些特定的情况下,一个类我们只让他承担一个特定的职责,如果一个类承担的职责过多,就等于把这些职责耦合在一起,这是我们编程思想中所忌讳的,程序员一直都再致力于使我们的代码简洁化,我们常说的就是让代码高内聚低耦合,降低代码的耦合性,这样我们在如果对代码中的一个功能模块进行修改时,我们只需要修改特定功能的类即可,从而不会影响其他功能的代码。
如果我们提高功能代码的耦合性,那我们设计的代码就会非常脆弱,当一个功能代码发生变化时,我们的代码设计就会招到破坏,影响是非常大的。
我们在实际开发中,会发现软件的功能是非常多的,我们不能盲目的去分离代码和职能,我们一定要去判断这些功能是否需要分离,我们的分离原则就是相同功能的类我们提取使用工厂和策略模式,如果功能不同我们可以让这个类职责单一化,即分离出来。
还有一个就是如果这个类有很多的动机或者因素来改变它,我们就需要考虑分离它,使它的功能单一化。
今天的单一职责模式不太好写代码或者太容易写出代码,我们要根据我们的项目区思考,什么时候会去用到它,什么时候是不需要分离类的。
作为一个程序员,我们一定要加入自己的思考,而不只是作为一个代码的搬运工。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
【黑马程序员济南】策略设计模式
上一次我们聊了简单工厂模式,让大家了解到了如何使程序具备更高的解耦性,使每一个功能代码都独立出来,今天我们和大家聊一下另一种解耦的设计模式,它就是策略设计模式。
什么是策略设计模式:它定义了算法家族,分别封装起来,让他们之间可以项目替换,此模式让算法的变化,不会影响到算法的客户。
我们可以这样理解,工厂模式是让我们内部的构造变得高内聚低耦合,而策略模式是让我们的内部代码和外部客户端代码不直接进行联系,而是通过一个桥梁来进行沟通,并且使相同算法或功能的代码进行封装。
给大家用UML图
大家通过上方的UML图可以看出,策略设计模式的思想为封装算法类,通过一个上下文的类,来沟通客户端和服务器端的逻辑代码。
给大家代码演示一下:
/**
* 此类为抽象的基类,用于具体的代码来继承使用
* @author zhe
*
*/
publicabstractclass StragerySuper {
//算法方法,用于具体的逻辑算法来实现
publicabstractvoid AlphInterfact();
}
具体的实现代码类:
/**
*具体的算法实现代码A
*
**/
class ConcreteA extends StragerySuper{
@Override
publicvoid AlphInterfact() {
System.out.print("算法A的实现类");
}
}
/**
*具体的算法实现代码B
*
**/
class ConcreteB extends StragerySuper{
@Override
publicvoid AlphInterfact() {
System.out.print("算法B的实现类");
}
}
/**
*具体的算法实现代码C
*
**/
class ConcreteC extends StragerySuper{
@Override
publicvoid AlphInterfact() {
System.out.print("算法c的实现类");
}
}
上下文类,作为连接客户端和后台代码端的桥梁
/**
*Context类,用于和外界进行联系的类,用来对StrategySuper的引用
***/
class Context{
StragerySuper stragerySuper;
public Context(StragerySuper stragerySuper){
//初始化构造函数,传递具体的策略对象
this.stragerySuper = stragerySuper;
}
//上下文接口,根据具体的策略对象,调用其算法的方法,执行具体的逻辑方法publicvoid ContextInterface(){
stragerySuper.AlphInterfact();
}
}
客户端代码:
/**
*客户端代码,通过Context中间类,来实现对具体实现类的调用
**/
class Client{
Context context;
publicvoid main(){
//客户端通过context执行具体的逻辑代码
context = new Context(new ConcreteA());
context.ContextInterface();
context = new Context(new ConcreteB());
context.ContextInterface();
context = new Context(new ConcreteC());
context.ContextInterface();
}
}
大家看策略模式是不是和简单工厂模式有点雷同,下一次我们把两个设计模式结合起来去实现,大家会发现我们的代码会更简洁和高效,每一种设计模式不是独立,他们都是可以交叉使用的。
我们只有不断的在我们的代码中去应用到这些设计模式,那么我们的编程思想会越来越灵活。