设计模式之策略模式、观察者模式浅析
head first 设计模式 这本书上学的时候就买了,一直没看,最近下班后实在是不想对着电脑,就翻了翻以前没看的书,看到《head first 设计模式》后,发现这本书写的真不错啊
强烈推荐 设计模式 入门级别书籍 《head first 设计模式》
本文主要是学习的一些感悟,关于策略模式与观察者模式,记录学习的脚步
1、先来看看策略模式,
策略模式强调的是封装变化,即将代码块中变化的部分封装起来,使之与使用变化的部分相隔离
/*** 设计原则:* 1、针对接口编程,而非实现* 2、多用组合,少用继承* 3、封装变化* * 策略模式:将算法簇封装起来,使使用算法的客体和算法之间相互独立* * 示例:鸭子游戏* * 每个鸭子都会游泳,都要显示自己的外观,但是每个鸭子还会有其他特定的行为,* 将变化的特定行为进行封装,抽象成接口,并提供变化行为的实现类,* 当每个鸭子有特定的行为时,只需实现特定的行为实现类即可,即可代码复用* 同时,每个鸭子可持有不同行为的接口,在运行时,可动态改变鸭子的行为,即是针对接口编程的好处* 当每个鸭子持有不同行为的接口作为成员变量时,鸭子和行为之间的耦合度减少了 ,* 当改变行为的操作时候,鸭子的原有代码都要不用变化,即算法簇变化,使用算法的客体不变,增强了软件的可维护性* * * 超类 鸭子* @author Administrator**/
策略模式 使用鸭子例子进行展示 详细描述如上
先看看超类 抽象类 Duck
package com.undergrowth.strategy;/*** 设计原则:* 1、针对接口编程,而非实现* 2、多用组合,少用继承* 3、封装变化* * 策略模式:将算法簇封装起来,使使用算法的客体和算法之间相互独立* * 示例:鸭子游戏* * 每个鸭子都会游泳,都要显示自己的外观,但是每个鸭子还会有其他特定的行为,* 将变化的特定行为进行封装,抽象成接口,并提供变化行为的实现类,* 当每个鸭子有特定的行为时,只需实现特定的行为实现类即可,即可代码复用* 同时,每个鸭子可持有不同行为的接口,在运行时,可动态改变鸭子的行为,即是针对接口编程的好处* 当每个鸭子持有不同行为的接口作为成员变量时,鸭子和行为之间的耦合度减少了 ,* 当改变行为的操作时候,鸭子的原有代码都要不用变化,即算法簇变化,使用算法的客体不变,增强了软件的可维护性* * * 超类 鸭子* @author Administrator**/
public abstract class Duck {private FlyBehavior flyBehavior;private QuackBehavior quackBehavior;/*** 游泳行为*/public void swim(){System.out.println("我是一只鸭子,,我会游泳");}/*** 显示鸭子的外观,因为不同的鸭子的外观是不同的,留给子类自己实现*/public abstract void display();public void setFlyBehavior(FlyBehavior flyBehavior) {this.flyBehavior = flyBehavior;}public void setQuackBehavior(QuackBehavior quackBehavior) {this.quackBehavior = quackBehavior;}public FlyBehavior getFlyBehavior() {return flyBehavior;}public QuackBehavior getQuackBehavior() {return quackBehavior;}}
看到其中分别有FlyBehavior(飞的动作)和QuackBehavior(叫的动作) 行为 因为这些行为是变化的 所以将其单独的封装成接口
因为运行时扩展远比编译时继承的威力更大 所以两个行为都是作为Duck的成员变量 这样在运行时 其行为可动态的改变
FlyBehavior接口
package com.undergrowth.strategy;/*** 飞的行为 可以是鸭子 也可是其他动物* @author Administrator**/
public interface FlyBehavior {public void fly();
}
QuackBehavior接口
package com.undergrowth.strategy;/*** 叫行为 可以使鸭子 也可是其他的* @author Administrator**/
public interface QuackBehavior {public void quack();
}
接着看一下Duck的子类和FlyBehavior、QuackBehavior的子类
潜水鸭
package com.undergrowth.strategy;/*** 潜水鸭 会飞* @author Administrator**/
public class DivingDuck extends Duck {@Overridepublic void display() {// TODO Auto-generated method stubSystem.out.println("我是潜水鸭,我全身是黑色的");}}
会飞行为
package com.undergrowth.strategy;/*** 表示会飞* @author Administrator**/
public class EnableFly implements FlyBehavior {@Overridepublic void fly() {// TODO Auto-generated method stubSystem.out.println("我会飞,我可以飞得比刘翔高");}}
不会飞行为
package com.undergrowth.strategy;public class DisableFly implements FlyBehavior {@Overridepublic void fly() {// TODO Auto-generated method stubSystem.out.println("我太笨了,我不会飞");}}
会叫行为
package com.undergrowth.strategy;public class EnableQuack implements QuackBehavior {@Overridepublic void quack() {// TODO Auto-generated method stubSystem.out.println("我身体好了,我会吱吱叫啊");}}
不会叫行为
package com.undergrowth.strategy;public class DisableQuack implements QuackBehavior {@Overridepublic void quack() {// TODO Auto-generated method stubSystem.out.println("哎,身体不好,不会吱吱叫啊");}}
测试类
package com.undergrowth.strategy.test;import static org.junit.Assert.*;import java.awt.dnd.DragGestureEvent;import org.junit.Test;import com.undergrowth.strategy.DisableFly;
import com.undergrowth.strategy.DisableQuack;
import com.undergrowth.strategy.DivingDuck;
import com.undergrowth.strategy.Duck;
import com.undergrowth.strategy.EnableFly;
import com.undergrowth.strategy.EnableQuack;public class DivingDuckTest {@Testpublic void test() {Duck dark=new DivingDuck();System.out.println("鸭子的共有行为:");dark.swim();dark.display();System.out.println("鸭子的特有行为,动态进行改变:");//动态进行改变鸭子的行为//设置潜水鸭 会飞dark.setFlyBehavior(new EnableFly());dark.getFlyBehavior().fly();//设置潜水鸭会叫dark.setQuackBehavior(new EnableQuack());dark.getQuackBehavior().quack();//动态进行改变鸭子的行为//设置潜水鸭不会飞dark.setFlyBehavior(new DisableFly());dark.getFlyBehavior().fly();//设置潜水鸭不会叫dark.setQuackBehavior(new DisableQuack());dark.getQuackBehavior().quack();}}
结果输出
鸭子的共有行为:
我是一只鸭子,,我会游泳
我是潜水鸭,我全身是黑色的
鸭子的特有行为,动态进行改变:
我会飞,我可以飞得比刘翔高
我身体好了,我会吱吱叫啊
我太笨了,我不会飞
哎,身体不好,不会吱吱叫啊
以上即是策略模式
策略模式:将算法簇封装起来,使使用算法的客体和算法之间相互独立
2、观察者模式
其实观察者模式中,最大的特点是松耦合,主题利用观察者接口进行通知 而观察者利用主题的接口进行注册 同时对于具体的主题与观察者而言,两者之间都是相互不干扰的,两者之间的交互最大程度的达到了松耦合的原则
/*** 设计原则:* 为交互对象之间的松耦合度而努力* * 观察者模式:* 当交互对象之间存在一对多的依赖,一的一方状态一旦发生改变,多的一方即会收到通知,进行状态的更新* 对应的即是:* 主题(1)与观察者(n) 或者说是可观察者(1)与观察者(n)* 主题的作用是 注册、移除、通知观察者* 观察者的作用是接收到特定主题的通知,进行状态或者数据的更新 * * 根据数据在主题与观察者之间的传递方向,又可分为* 推(push)--当主题的状态发生变化时,将数据推送给观察者* 拉(pull)--当主题的状态发生变化时,告知给观察者,由观察者自己来决定取什么数据* * 示例:* 使用课程成绩与学生来进行展示* 课程成绩作为主题 学生作为观察者* 当课程成绩被老师提交后 会通知每一个学生 这个班的平均分是多少 最高分是多少 当然 前提是学生必须选了这门课* * java类库中也有观察者模式 分别是Observable和Observer* * @author Administrator**/
先来看看主题接口 Subject
package com.undergrowth.observer;/*** 设计原则:* 为交互对象之间的松耦合度而努力* * 观察者模式:* 当交互对象之间存在一对多的依赖,一的一方状态一旦发生改变,多的一方即会收到通知,进行状态的更新* 对应的即是:* 主题(1)与观察者(n) 或者说是可观察者(1)与观察者(n)* 主题的作用是 注册、移除、通知观察者* 观察者的作用是接收到特定主题的通知,进行状态或者数据的更新 * * 根据数据在主题与观察者之间的传递方向,又可分为* 推(push)--当主题的状态发生变化时,将数据推送给观察者* 拉(pull)--当主题的状态发生变化时,告知给观察者,由观察者自己来决定取什么数据* * 示例:* 使用课程成绩与学生来进行展示* 课程成绩作为主题 学生作为观察者* 当课程成绩被老师提交后 会通知每一个学生 这个班的平均分是多少 最高分是多少 当然 前提是学生必须选了这门课* * java类库中也有观察者模式 分别是Observable和Observer* * @author Administrator**/
public interface Subject {/*** 注册观察者* @param observer*/public void registerObserver(MObserver observer);/*** 移除观察者* @param observer*/public void removeObserver(MObserver observer);/*** 通知观察者 拉的方式*/public void notifyObservers();/*** 通知观察者 推的方式* @param data*/public void notifyObservers(Object[] data);
}
再来看看观察者接口
package com.undergrowth.observer;/*** 观察者的作用即使更新自己的状态* @author Administrator**/
public interface MObserver {public void update();public void update(Object[] data);public void update(Subject subject);
}
接着是成绩主题类 GradeSubject
package com.undergrowth.observer;import java.util.ArrayList;
import java.util.List;public class GradeSubject implements Subject {/*** 存放观察者*/private List<MObserver> managerMObserver =new ArrayList<>();/*** 记录状态是否改变*/private boolean changed;private int gradeMax=100;private double averageGrade=98.5;@Overridepublic void registerObserver(MObserver observer) {// TODO Auto-generated method stubif(!managerMObserver.contains(observer)){managerMObserver.add(observer);}}@Overridepublic void removeObserver(MObserver observer) {// TODO Auto-generated method stubif(managerMObserver.contains(observer)){managerMObserver.remove(observer);}}/*** 拉数据*/@Overridepublic void notifyObservers() {// TODO Auto-generated method stubif(isChanged()){for (MObserver observer : managerMObserver) {observer.update(this);}}}/*** 推数据*/@Overridepublic void notifyObservers(Object[] data) {// TODO Auto-generated method stubif (isChanged()) {for (MObserver observer : managerMObserver) {observer.update(data);}}}public List<MObserver> getManagerMObserver() {return managerMObserver;}public void setManagerMObserver(List<MObserver> managerMObserver) {this.managerMObserver = managerMObserver;}public int getGradeMax() {return gradeMax;}public void setGradeMax(int gradeMax) {this.gradeMax = gradeMax;}public double getAverageGrade() {return averageGrade;}public void setAverageGrade(double averageGrade) {this.averageGrade = averageGrade;}public boolean isChanged() {return changed;}public void setChanged(boolean changed) {this.changed = changed;}}
最后分别是两个观察者学生类 StudentMObserver和StudentOTherMObserver
package com.undergrowth.observer;public class StudentMObserver implements MObserver {private Subject subject;public StudentMObserver(Subject subject){this.subject=subject;subject.registerObserver(this);}@Overridepublic void update() {// TODO Auto-generated method stub}@Overridepublic void update(Object[] data) {// TODO Auto-generated method stubfor (Object object : data) {System.out.println(StudentMObserver.class+"\t传递数据为:"+object);}}@Overridepublic void update(Subject subject) {// TODO Auto-generated method stubif(subject instanceof GradeSubject){GradeSubject gradeSubject=(GradeSubject) subject;System.out.println(StudentMObserver.class+"\t最高分为:"+gradeSubject.getGradeMax()+" 平均分为:"+gradeSubject.getAverageGrade());}}public Subject getSubject() {return subject;}public void setSubject(Subject subject) {this.subject = subject;}}
package com.undergrowth.observer;public class StudentOTherMObserver implements MObserver {private Subject subject;public StudentOTherMObserver(Subject subject){this.subject=subject;subject.registerObserver(this);}@Overridepublic void update() {// TODO Auto-generated method stub}@Overridepublic void update(Object[] data) {// TODO Auto-generated method stubfor (Object object : data) {System.out.println(StudentOTherMObserver.class+"\t传递数据为:"+object);}}@Overridepublic void update(Subject subject) {// TODO Auto-generated method stubif(subject instanceof GradeSubject){GradeSubject gradeSubject=(GradeSubject) subject;System.out.println(StudentOTherMObserver.class+"\t最高分为:"+gradeSubject.getGradeMax()+" 平均分为:"+gradeSubject.getAverageGrade());}}public Subject getSubject() {return subject;}public void setSubject(Subject subject) {this.subject = subject;}}
最后的测试类 StudentMObserverTest
package com.undergrowth.observer.test;import static org.junit.Assert.*;import org.junit.Test;import com.undergrowth.observer.GradeSubject;
import com.undergrowth.observer.StudentMObserver;
import com.undergrowth.observer.StudentOTherMObserver;
import com.undergrowth.observer.Subject;public class StudentMObserverTest {@Testpublic void test() {GradeSubject subject=new GradeSubject();StudentMObserver studentMObserver1=new StudentMObserver(subject);StudentOTherMObserver stu=new StudentOTherMObserver(subject);//改变成绩subject.setChanged(true);//拉数据 通知观察者subject.notifyObservers();//改变成绩subject.setAverageGrade(70);subject.setGradeMax(99);subject.notifyObservers(new String[]{"传递给通知者"});}}
结果输出
class com.undergrowth.observer.StudentMObserver 最高分为:100 平均分为:98.5
class com.undergrowth.observer.StudentOTherMObserver 最高分为:100 平均分为:98.5
class com.undergrowth.observer.StudentMObserver 传递数据为:传递给通知者
class com.undergrowth.observer.StudentOTherMObserver 传递数据为:传递给通知者
其实观察者模式中,最大的特点是松耦合,主题利用观察者接口进行通知 而观察者利用主题的接口进行注册 同时对于具体的主题与观察者而言,两者之间都是相互不干扰的,两者之间的交互最大程度的达到了松耦合的原则
在java的类库中,有很多观察者模式的例子,例如按钮的监听与事件处理 Observable与Observer
上面是我们自己建立主题(可观察者)和观察者 现在利用util包中的观察者模式 进行代码的构建
主题类 SubjectSys继承Observable
package com.undergrowth.observer.util;/*** java 来库中自带的观察者模式 可观察者(Observable)和观察者(Observer)* Observable 实现了 观察者的注册、移除、通知 但是它是类,而不是接口,并且状态的变化只能通过继承它才能改变* Observer 提供了更新操作*/
import java.util.Observable;public class SubjectSys extends Observable {private int gradeMax=100;private double averageGrade=98.5;public int getGradeMax() {return gradeMax;}public void setGradeMax(int gradeMax) {this.gradeMax = gradeMax;}public double getAverageGrade() {return averageGrade;}public void setAverageGrade(double averageGrade) {this.averageGrade = averageGrade;}public void setChangedStatus(){setChanged();}
}
会看到可观察者替我们管理观察的注册 移除 通知 及状态的管理
观察者 ObserverSys实现 Observer接口
package com.undergrowth.observer.util;import java.util.Observable;
import java.util.Observer;public class ObserverSys implements Observer {public ObserverSys(Observable observable){observable.addObserver(this);}@Overridepublic void update(Observable o, Object arg) {// TODO Auto-generated method stubif(o instanceof SubjectSys){SubjectSys sys=(SubjectSys) o;System.out.println(ObserverSys.class+"\t平均分:"+sys.getAverageGrade()+"\t最高分:"+sys.getGradeMax());}}}
测试类 ObserverSysTest
package com.undergrowth.observer.util.test;import static org.junit.Assert.*;import org.junit.Test;import com.undergrowth.observer.util.ObserverSys;
import com.undergrowth.observer.util.SubjectSys;public class ObserverSysTest {@Testpublic void test() {SubjectSys subject=new SubjectSys();ObserverSys objectSys=new ObserverSys(subject);//改变状态subject.setChangedStatus();subject.notifyObservers();}}
结果输出
class com.undergrowth.observer.util.ObserverSys 平均分:98.5 最高分:100
以上即是观察者模式
记录学习的脚步
设计模式之策略模式、观察者模式浅析相关推荐
- 设计模式:策略模式+观察者模式
以游戏情景举例: 情景:一个boss发动一个技能时会让自己的喽啰收到随机的增益效果. 提取一下主要需求: 1:随机增益效果 2:通知多个对象 其中1用策略模式+工厂模式来解决,2用观察者模式来解决 先 ...
- JavaScript设计模式之策略模式(学习笔记)
在网上搜索"为什么MVC不是一种设计模式呢?"其中有解答:MVC其实是三个经典设计模式的演变:观察者模式(Observer).策略模式(Strategy).组合模式(Composi ...
- Java设计模式之策略模式与状态模式
一.策略模式定义 定义:策略模式定义了一系列的算法,并将每一个算法封装起来,而且使他们之间可以相互替换,策略模式可以在不影响客户端的情况下发生变化. 好了,定义看看就完了,我知道你很烦看定义. 二.策 ...
- 换个姿势学设计模式:策略模式
点击上方蓝色"程序猿DD",选择"设为星标" 回复"资源"获取独家整理的学习资料! 来源:公众号「闻人的技术博客」 前言 前段时间,接到一个 ...
- 研磨设计模式之 策略模式--转
http://www.uml.org.cn/sjms/201009092.asp 研磨设计模式之 策略模式 2010-09-09 作者:云飞龙行 来源:云飞龙行的blog 先感谢众多朋友的支持 ...
- 设计模式:策略模式(Strategy)
定 义:它定义了算法家族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化, 不会影响到使用算法的客户. 示例:商场收银系统,实现正常收费.满300返100.打8折.......等不同收费 ...
- C++设计模式之策略模式(Strategy)
Strategy策略模式 作用:定义了算法家族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化,不会影响到使用算法的客户. UML图: 代码实现 #include <iostream& ...
- python策略模式包含角色_详解Python设计模式之策略模式
虽然设计模式与语言无关,但这并不意味着每一个模式都能在每一门语言中使用.<设计模式:可复用面向对象软件的基础>一书中有 23 个模式,其中有 16 个在动态语言中"不见了,或者简 ...
- 一篇博客读懂设计模式之-----策略模式
设计模式之策略模式 在策略模式中,我们创建表示各种策略的对象和一个行为随着策略对象改变而改变的对象 定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换. 主要解决:在有多种算法相似的情况下 ...
- 面向对象设计模式之策略模式
面向对象设计模式之策略模式 1.策略模式定义了算法族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化独立于使用算法的客户 2.抽象鸭子类,鸭子飞行行为在此处类似于算法族 1 package ...
最新文章
- [转]ORACLE日期时间函数大全
- 在html怎么使用php函数,php htmlentities函数讲解及使用实例
- 富人为什么会富,穷人为什么穷?看完你就懂
- [渝粤教育] 西南科技大学 复习资料 法理学
- leetcode468. 验证IP地址
- 【CodeForces - 27E】Number With The Given Amount Of Divisors (数论,数学,反素数)
- 推荐引擎内部的秘密3
- WIN7(VISTA)系统无法上网问题排查方法
- 对Python的初认识以及期待
- 使用升级版的 Bootstrap typeahead v1.2.2
- win7企业版怎么都激活不了,看这里
- mysql无法加载主类_错误: 找不到或无法加载主类 JDBC
- 基于Multisim的简易数字钟
- 舞蹈迁移:EverybodyDanceNow reproduced in pytorch
- 2015 上海邀请赛c题 calculator hdu5238
- web 微信与基于node的微信机器人实现
- 网盘搜索插件php源码,百度云网盘搜索引擎 PHP版 v1.0
- 如何通过技术手段批量删除公众号文章?
- java计算机毕业设计旧货网上交易系统源程序+mysql+系统+lw文档+远程调试
- 【重点案例】b站pink老师JavaScript的PC端网页特效 案例代码——网页轮播图