设计模式之策略模式、观察者模式浅析

来源:互联网 发布:魔兽7.0数据库app 编辑:程序博客网 时间:2024/05/17 23:57

               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.5class com.undergrowth.observer.StudentOTherMObserver最高分为:100 平均分为:98.5class 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


以上即是观察者模式





记录学习的脚步


0 0
原创粉丝点击