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


                   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 {
    	
    	@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+"	传递数据为:"+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+"	最高分为:"+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+"	传递数据为:"+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+"	最高分为:"+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+"	平均分:"+sys.getAverageGrade()+"	最高分:"+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
    


    以上即是观察者模式





    记录学习的脚步


  • 相关阅读:
    如何使用Orchard搭建敏捷个人的网站(1)
    英语:敏捷英语学习开始了
    英语:普特三步听写法(转载)
    色拉英语第一集第五幕:好胖的一只鸟
    介绍一个基于ASP.NET MVC的框架Catharsis
    色拉英语第2集第3幕:He’s my favorite
    Orchard:如何生成Hello World模块
    如何使用Orchard搭建敏捷个人的网站(2)
    色拉英语第一集第四幕:我不喜欢北京烤鸭
    色拉英语第一集第二幕:请问南京路怎么走?
  • 原文地址:https://www.cnblogs.com/liangxinzhi/p/4275546.html
Copyright © 2020-2023  润新知