【Java】Strategy Pattern
前言
如果说,商场打折针对不同的时节,比如双十一、圣诞节、春节这些值得促销的好日子,进行不同程度的降价打折从而获得最大程度上的收益,如果有一群鸭子,只会游泳、嘎嘎叫,但是某一天某种类型的鸭子学会了飞,那群里面的鸭子并不会飞。这样的话还有修改以前的封装好的算法,然后添加飞翔的功能,这个时候,就得考虑一下设计原则。对扩展开放,对修改封闭。针对这种算法经常变化的情况,将这些算法封装起来,独立于不变的成分,保证增加新的算法的同时,对不变的地方不添加修改。下面采用 Strategy
Pattern 进行实现。分别从UML图分析和代码两个方面进行分析。
内容
精华:
定义了算法族,分别封装起来,让它们之间相互替换,此模式让算法的变化独立于使用算法的客户。
原则:
·将变化的地方封装起来了(封装变化)。
·多用组合,少用继承。
·针对接口编程,不针对实现。
UML图
DEMO部分:
说明:以下的代码为左半部分抽象类与子类继承抽象类,从而子类继承抽象类的属性和行为,其中的setFlyBehavior和setQuackBehavior方法作用可以在客户端调用该对象的时候动态添加鸭子的行为。
<span style="font-family:KaiTi_GB2312;font-size:18px;">package Duck; /*
* author:zhoulitong
*/
abstract class Duck{
FlyBehavior flyBehavior;
QuackBehavior quackBehavior; //表演一个叫的动作
public void performQuack(){
quackBehavior.quack();
} //表演一个飞的动作
public void performFly(){
flyBehavior.fly();
} public abstract void display(); //有了这个方法可以动态改变鸭子的行为了
public void setFlyBehavior(FlyBehavior fb){
flyBehavior = fb;
} public void setQuackBehavior(QuackBehavior qb){
quackBehavior = qb;
}
} class MallardDuck extends Duck{
public MallardDuck(){
quackBehavior = new Quack();//实例化叫的实例
flyBehavior = new FlyWithWings();//实例化飞的实例
} public void display(){
System.out.println("小鸭是一个真正的鸭子!不是白天鹅");
}
}</span>
说明:接口部分,这部分的代码是封装了变化的部分,从而让变化的部分独立于不变的部分,让这个设计模式更加的符合开闭原则,在这里,接口部分盛放的是鸭子的功能,鸭子表现行为的时候,分别利用多态进行按需求实例化自己想要的那部分功能行为。
<span style="font-family:KaiTi_GB2312;font-size:18px;">/*
* author:zhoulitong
*/
//声明一个公共接口(类似于抽象类的功能)
interface QuackBehavior {
void quack();//声明一个呱呱叫的方法
} class Quack implements QuackBehavior{
public void quack(){
//实现鸭子呱呱叫
}
} class Squeak implements QuackBehavior{
public void quack(){
//实现橡皮鸭吱吱叫的方法
}
} class MuteQuack implements QuackBehavior{
public void quack(){
//什么都不做,不会叫
}
} interface FlyBehavior{
void fly();//声明一个飞的接口方法
} class FlyWithWings implements FlyBehavior{
public void fly(){
//实现鸭子的飞行动作
}
} class FlyNoWay implements FlyBehavior{
public void fly(){
//什么都不做,不会飞
}
} class FlyRocketPowered implements FlyBehavior{
public void fly(){ }
}</span>
说明:客户端代码部分,申请一个对象的实例,采用了多态机制,实例化了一个实际存在的鸭子对象,分别执行行为。
<span style="font-family:KaiTi_GB2312;font-size:18px;">public class MiniDuckSimulator{
public static void main (String[] args){
Duck mallard = new MallardDuck();//实例化一个鸭子
mallard.performFly();//飞的动作
mallard.performQuack();//叫的动作
//如果又增加了一个动作,可以通过Duck父类中的set方法对实例化的对象进行附加
//在运行时想要改变鸭子的行为,只需要调用鸭子的setter方法就可以了。
mallard.setFlyBehavior(new FlyRocketPowered());
mallard.performFly();
}
}</span>
小结
上面就是策略模式一个小小的应用,希望在后期有更多实践。
感谢您的宝贵时间···
【Java】Strategy Pattern的更多相关文章
- 【Java】Observer Pattern
前言 代码来源于生活,更加高于生活.设计模式让我们的生活更加的方便.观测一个东西,盯着一个东西,关注一个公众号,这些东西,如果没有即时通知的话,我们又特别想了解这方面的内容,那么我们除了一直耗着时间找 ...
- 【Java】-NO.20.Exam.1.Java.1.001- 【1z0-807】- OCEA
1.0.0 Summary Tittle:[Java]-NO.20.Exam.1.Java.1.001-[1z0-807] Style:EBook Series:Java Since:2017-10- ...
- 【Java】-NO.16.EBook.4.Java.1.007-【疯狂Java讲义第3版 李刚】- Java基础类
1.0.0 Summary Tittle:[Java]-NO.16.EBook.4.Java.1.007-[疯狂Java讲义第3版 李刚]- Java基础类 Style:EBook Series:J ...
- 【Java】-NO.11.Java.1.Log4j.1.001-【Log4j Manual】-
1.0.0 Summary Tittle:[Java]-NO.11.Java.1.Log4j.1.001-[Log4j2 Manual]- Style:Java Series:Log4j Since: ...
- 数据结构与算法【Java】03---栈
前言 数据 data 结构(structure)是一门 研究组织数据方式的学科,有了编程语言也就有了数据结构.学好数据结构才可以编写出更加漂亮,更加有效率的代码. 要学习好数据结构就要多多考虑如何将生 ...
- 【Java】代处理?代理模式 - 静态代理,动态代理
>不用代理 有时候,我希望在一些方法前后都打印一些日志,于是有了如下代码. 这是一个处理float类型加法的方法,我想在调用它前打印一下参数,调用后打印下计算结果.(至于为什么不直接用+号运算, ...
- 【Java】推断文件的后缀名
这本来不是一个问题,利用框架本来有的方法.或者File类的getPath()方法,取出要推断文件路径.或者getName()方法取出文件路径,成为一个String字符串如果为fileName之后,再对 ...
- 【JAVA】【NIO】3、Java NIO Channel
Java NIO和流量相似,但有些差异: ·通道可读写,流仅支持单向.读或写 ·异步通道读取 ·通道读写器,他们是和Buffer交替 道的实现 下面是Java NIO中最重要的通道的实现: ·File ...
- 【JAVA】【NIO】5、Java NIO Scatter / Gather
标题手段Java NIO该分散体浓缩 Java NIO内置支持分散与收集.的概念主要用于信道分散聚集的读写. 读出的分散体的一个通道被读多个数据buffer在.因此.数据分散到多个buffer中. 对 ...
随机推荐
- LdapContext获取对象的属性
// dn = "cn=1,cn=Users,DC=域名,DC=COM";// Attributes answer = ctx.getA ...
- [转载]get_fs()和set_fs()
其实内核里面也可以用系统调用的,直接用read/write是可以的.但要注意几个问题:一个是要记得编译的时候加上-D__KERNEL_SYSCALLS__另外源文件里面要#include如果报错,很可 ...
- Java并发 两个线程交替执行和死锁
今天看到一个题:两个线程交替打印奇数和偶数,即一个线程打印奇数,另一个打印偶数,交替打印从1到100.想了下有多重实现方法. wait和notify方法: public class OddEven { ...
- Celery-4.1 用户指南: Routing Tasks (路由任务)
注意: 像主题和扇出之类的路由概念并不对所有传输介质都可用,请翻阅”传输比较表”. 基础 自动路由 路由最简单的方式是使用 task_create_missing_queues 设置(默认启用). 使 ...
- Python中str.format()字典及list传入详解
- c++如何编写线程安全的DLL
DLL有个共同的特点就是都有一个初始化函数,一个资源释放函数,其他几个函数都是核心功能函数.而且这些DLL有时会被多个进程同时调用,这就牵扯到多进程的多线程调用DLL的问题.有点绕口,以下我根据我实践 ...
- Struts1使用技巧
转自:https://blog.csdn.net/chjttony/article/details/6099101 1.Struts1是Apache推出的java web开发领域一个比较早,同时也是使 ...
- docker 笔记(4) Dockerfile 常用的指令
下面列出了 Dockerfile 中最常用的指令,完整列表和说明可参看官方文档. FROM指定 base 镜像. MAINTAINER设置镜像的作者,可以是任意字符串. COPY将文件从 build ...
- ffmpeg: ‘UINT64_C’ was not declared in this scope (转)
ffmpeg 默认是用C文件来编译的,如果某个CPP文件想引用ffmpeg中的某些函数或者头文件,有可能出现 ‘UINT64_C’ was not declared in this scope的错误 ...
- 1-EasyNetQ介绍(黄亮翻译)
EasyNetQ 是一个容易使用,坚固的,针对RabbitMQ的 .NET API. 假如你尽可能快的想去安装和运行RabbitMQ,请去看入门指南. EasyNetQ是为了提供一个尽可能简洁的适用与 ...