设计模式之策略模式、观察者模式浅析
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(); }
潜水鸭
package com.undergrowth.strategy; /** * 潜水鸭 会飞 * @author Administrator * */ public class DivingDuck extends Duck { @Override public void display() { // TODO Auto-generated method stub System.out.println("我是潜水鸭,我全身是黑色的"); } }
会飞行为
package com.undergrowth.strategy; /** * 表示会飞 * @author Administrator * */ public class EnableFly implements FlyBehavior { @Override public void fly() { // TODO Auto-generated method stub System.out.println("我会飞,我可以飞得比刘翔高"); } }
不会飞行为
package com.undergrowth.strategy; public class DisableFly implements FlyBehavior { @Override public void fly() { // TODO Auto-generated method stub System.out.println("我太笨了,我不会飞"); } }会叫行为
package com.undergrowth.strategy; public class EnableQuack implements QuackBehavior { @Override public void quack() { // TODO Auto-generated method stub System.out.println("我身体好了,我会吱吱叫啊"); } }
不会叫行为
package com.undergrowth.strategy; public class DisableQuack implements QuackBehavior { @Override public void quack() { // TODO Auto-generated method stub System.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 { @Test public 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; @Override public void registerObserver(MObserver observer) { // TODO Auto-generated method stub if(!managerMObserver.contains(observer)){ managerMObserver.add(observer); } } @Override public void removeObserver(MObserver observer) { // TODO Auto-generated method stub if(managerMObserver.contains(observer)){ managerMObserver.remove(observer); } } /** * 拉数据 */ @Override public void notifyObservers() { // TODO Auto-generated method stub if(isChanged()){ for (MObserver observer : managerMObserver) { observer.update(this); } } } /** * 推数据 */ @Override public void notifyObservers(Object[] data) { // TODO Auto-generated method stub if (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); } @Override public void update() { // TODO Auto-generated method stub } @Override public void update(Object[] data) { // TODO Auto-generated method stub for (Object object : data) { System.out.println(StudentMObserver.class+"\t传递数据为:"+object); } } @Override public void update(Subject subject) { // TODO Auto-generated method stub if(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); } @Override public void update() { // TODO Auto-generated method stub } @Override public void update(Object[] data) { // TODO Auto-generated method stub for (Object object : data) { System.out.println(StudentOTherMObserver.class+"\t传递数据为:"+object); } } @Override public void update(Subject subject) { // TODO Auto-generated method stub if(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 { @Test public 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); } @Override public void update(Observable o, Object arg) { // TODO Auto-generated method stub if(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 { @Test public void test() { SubjectSys subject=new SubjectSys(); ObserverSys objectSys=new ObserverSys(subject); //改变状态 subject.setChangedStatus(); subject.notifyObservers(); } }
结果输出
class com.undergrowth.observer.util.ObserverSys 平均分:98.5 最高分:100
以上即是观察者模式
记录学习的脚步
posted on 2014-11-29 18:53 liangxinzhi 阅读(339) 评论(0) 编辑 收藏 举报