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

               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+"\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  阅读(327)  评论(0编辑  收藏  举报