设计模式---策略模式
来源:互联网 发布:2012法治网络知识竞赛 编辑:程序博客网 时间:2024/06/05 05:18
前言:关于设计模式
在软件工程中,设计模式(design pattern)是对软件设计中普遍存在(反复现)的各种问题,所提出的解决方案。这个术语是由埃里希·伽玛(Erich Gamma)等人在1990年代从建筑设计领域引入到计算机科学的。
设计模式并不直接用来完成代码的编写,而是描述在各种不同情况下,要怎么解决问题的一种方案。面向对象设计模式通常以类别或对象来描述其中的关系和相互作用,但不涉及用来完成应用程序的特定类别或对象。设计模式能使不稳定依赖于相对稳定、具体依赖于相对抽象,避免会引起麻烦的紧耦合,以增强软件设计面对并适应变化的能力。
以上是维基百科关于设计模式的定义。
很长的一段时间里,我写代码都只会蛮干,对自己的要求也仅仅是实现功能。后来慢慢的,看到别人写的代码层次分明、逻辑清晰才发现自己弱爆了,也就开始试着抽层,有时候还觉得不赖。BUT,最近开始看设计模式了,哎,都是泪。。。
设计模式是前人开发经验总结出来的精华,是遇到某些问题时需要掌握的思维模式。是站在一个比较高的高度去审视、设计代码的逻辑、结构,让代码不光是写起来思路更清晰,日后的可扩展性和可维护性也会更好。
定义
策略模式定义了算法族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化独立与使用算法的客户。
定义通常就是这样,看起来很拗口也不容易看懂,当你理解了,又发现确实没毛病,真的就是这个样子。。。
理解
有一系列看起来很相似的类,比如红头鸭(RedHeadDuck)、绿头鸭(MallardDuck)、橡皮鸭(RubberDuck)。很明显他们能抽出一个基类Duck,但是呢,这几个对象的某些方法的实现又会完全不一样,比如fly()、Quack()。
通常的做法是这样:
abstract class Duck { public abstract void swim(); public abstract void fly(); public abstract void quack();}public class RedHeadDuck extends Duck{ @Override public void swim() { Log.e("ZXK","i can swim"); } @Override public void fly() { Log.e("ZXK","i can fly"); } @Override public void quack() { Log.e("ZXK","red red red"); }}public class MallardDuck extends Duck { @Override public void swim() { Log.e("ZXK","i can swim"); } @Override public void fly() { Log.e("ZXK","i can fly"); } @Override public void quack() { Log.e("ZXK","green green green"); }}public class RubberDuck extends Duck { @Override public void swim() { Log.e("ZXK","i can swim"); } @Override public void fly() { Log.e("ZXK","i can't fly"); } @Override public void quack() { Log.e("ZXK","rubber rubber rubber"); }}
首先,功能肯定是可以实现的,但是不够优雅,你会发现每次有新的鸭子类需要实现,都需要把所有的方法都重写一遍,共性的也会跟着倒霉,比如本例中的swim()方法。
如何改进呢?肯定有人很自然的就想到了抽象,将 fly 和 quack 抽象成接口,让各个类自己去实现好了。
但是如果这种类有很多呢?你每次实现起来依旧需要重写fly() 和 quack()方法。
这就需要用到策略模式了,策略模式的做法是:
1. 将需要变化的那一部分,比如 fly 、quack ,与不变的隔离开来:建立两组类,一组是”fly”相关 ,比如 “能飞”类和”不能飞”类;另一组是”quack”相关类,比如”叫声大”类,”叫声小”类,”不能叫”类。
2. 然后将 这两组类又抽象成接口:FlyBehavior,QuackBehavior,并实现他们。
3. 将接口作为Duck这个基类的属性。
4. 在Duck类的子类的构造函数中,通过多态,动态的改变flyBehavior和quackBehavior属性的实现类。以实现不同的效果。
代码
两个接口及其实现类:
public interface FlyBehavior { void fly();}public interface QuackBehavior { void quack();}public class FlyNoWings implements FlyBehavior { @Override public void fly() { Log.e("ZXK","i can't fly"); }}public class FlyWithWings implements FlyBehavior { @Override public void fly() { Log.e("ZXK","i can fly"); }}public class RedQuack implements QuackBehavior { @Override public void quack() { Log.e("ZXK","red red red"); }}public class GreenQuack implements QuackBehavior { @Override public void quack() { Log.e("ZXK","green green green"); }}public class RubberQuack implements QuackBehavior { @Override public void quack() { Log.e("ZXK","rubber rubber rubber"); }}
Duck及其子类:
public abstract class Duck { FlyBehavior flyBehavior; QuackBehavior quackBehavior; public void swim() { Log.e("ZXK", "i can swim"); } public void performFly() { flyBehavior.fly(); } public void performSwim() { quackBehavior.quack(); }}public class RedHeadDuck extends Duck{ public RedHeadDuck() { flyBehavior = new FlyWithWings(); quackBehavior = new RedQuack(); }}public class MallardDuck extends Duck { public MallardDuck() { flyBehavior = new FlyWithWings(); quackBehavior = new GreenQuack(); }}public class RubberDuck extends Duck { public RubberDuck() { flyBehavior = new FlyNoWings(); quackBehavior = new RubberQuack(); }}
UML图
看不清图的,右键“在新标签页中打开图片”
总结
- 策略模式主要用在:一系列相似对象的某些方法实现不相同。
- 策略模式用法:首先分析这些相似对象,构建基类。将变化的那部分方法分离出来,抽象成接口,不同的方法实现作为实现类来实现这些接口。然后将接口作为基类的属性。在构建新的子类的时候,利用多态,动态的改变接口的实现,以达到相应的实现效果。
- 多用组合,少用继承:利用继承去设计子类的行为,是在编译时静态决定的,而且所有的子类都会继承到相同得行为。然而,如果能利用组合去扩展对象的行为,就可以在运行时动态的进行扩展。添加新功能的时候无需修改旧代码,也就避免了新bug产生,更利于功能扩展。
- 分开变化和不会变化的部分:分别封装,互不干扰,利于后期维护和功能扩展。
- 针对接口编程,而不是针对实现:「针对接口编程」真正的意思是「针对超类型(supertype)编程」,可以是接口也可以是超类。关键在于利用多态,动态改变实现。
- 设计模式-策略模式
- 设计模式:策略模式
- 设计模式-策略模式
- 设计模式 - 策略模式
- 设计模式-策略模式
- 设计模式-----策略模式
- 设计模式 策略模式
- 设计模式-策略模式
- 设计模式-【策略模式】
- 设计模式-----策略模式
- 设计模式-策略模式
- 设计模式--策略模式
- 设计模式- 策略模式
- 设计模式- 策略模式
- 设计模式------策略模式
- 设计模式--策略模式
- 设计模式-策略模式
- 设计模式--策略模式
- __FILE__ 使用注意事项
- NOIP模拟9.20
- vue-cli中的webpack配置
- Illegal attempt to associate a collection with two open sessions.
- centos linux上 python3*和 python2.7*的安装
- 设计模式---策略模式
- mysql数据库表crash后解决办法
- leetcode 21. Merge Two Sorted Lists
- 频道拖拽配置
- Spring boot 使用 shiro做安全校验
- SSH项目搭建-01-使用idea创建Maven工程
- java EE开发之Servlet第四课:监听器(Listener)
- MySQL之自定义函数(可以不用DELIMITER)
- Fast DFS 基本简介