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
以上即是观察者模式
记录学习的脚步