软件设计模式-简介-策略模式-观察者模式

本文介绍了软件设计模式的核心思想,强调将变化部分封装以实现代码复用和面向接口编程。通过鸭子行为的例子,详细解释了策略模式的应用,展示如何通过组合而非继承来实现多态。同时,还探讨了观察者模式,提供了一个气象站与气象显示设备的案例,说明了观察者模式如何实现低耦合的主体-观察者关系。
摘要由CSDN通过智能技术生成

题外话

博主学习软件设计模式参考的是head first软件设计模式这本书 例题代码是本人自己所敲(仅供参考 里面并不是与书中完全一致 而是博主结合自己的经验而设置的)

软件设计模式核心思想

软件设计模式的一个最核心,最基础的思想是将会变化的部分取出来并进行封装 这样的话以后需要扩充 或需要进行改变的时候就很方便了, 而不至于影响到不需要变化的那部分

在这里插入图片描述

第二个原则是我们针对的是面向接口编程 即我们不要针对具体的实现 就像造汽车 我们需要的是生产组件 组装的组合有千万种 但是组件是一定的! 所以我们是面向接口编程
在这里插入图片描述

例如经典的鸭子叫 针对飞和叫两种行为 进行编程!
在这里插入图片描述
通过使用接口继承 而不是针对鸭子类进行继承 我们可以实现分离 这样就实现最大幅度的代码复用!
在这里插入图片描述

鸭子行为和多态的结合 通过在Duck加上两个实例变量 这样在运行时就会动态的改变鸭子状态 然后我们实现两个方法 里面交给对应实例变量来操作!
在这里插入图片描述

鸭子例子通过委托的形式 交给了两个行为类进行处理 这是对类的一种组合(compositoin) 而不是继承鸭子的行为并不是继承而来! 而是与适当的对象组合而成 ** 本例中使用了委托行为类** 而不是让鸭子继承行为类! 将变化的部分我们通过组合的形式来近似于继承~
在这里插入图片描述

策略模式

我们的模拟鸭子的例子实际上就是使用了策略模式 我们不难看出来 策略模式是针对行为进行抽象的一种行为 即通过增加新的行为 而不用修改实现即可使用新的行为!
在这里插入图片描述

鸭子实例代码

鸭子示例代码如下所示

/**  
* @Title: SimulateDuck.java  
* @Package   
* @Description: TODO(用一句话描述该文件做什么)  
* @author Lustre  
* @date 2019年12月7日  
* @version V1.0  
*/
/**
* @author Nigel
* @version 创建文件时间:2019年12月7日 下午11:25:08
*/
/**  
* @ClassName: SimulateDuck  
* @Description: TODO(这里用一句话描述这个类的作用)  
* @author Nigel  
* @date 2019年12月7日  
*    
*/

/**
 * 
* @ClassName: flyBehavior  
* @Description: 鸭子飞行行为 
* @author Nigel  
* @date 2019年12月8日  
*
 */
interface FlyBehavior {
	void flyAction();
}

class NormalFly implements FlyBehavior{

	@Override
	public void flyAction() {
		// TODO Auto-generated method stub
		System.out.println("normal fly action!");
	}
	
}

class RocketFly implements FlyBehavior {

	@Override
	public void flyAction() {
		// TODO Auto-generated method stub
		System.out.println("I am now in a rocket flight!");
	}
	
}

class CouldNotFly implements FlyBehavior {

	@Override
	public void flyAction() {
		// TODO Auto-generated method stub
		System.out.println("can not fly");
	}
	
}

interface QuarkBehavior {
	void quarkAction();
}

class CouldNotQuark implements QuarkBehavior{

	@Override
	public void quarkAction() {
		// TODO Auto-generated method stub
		System.out.println("I cound not quark!");
	}
	
}

class NormalQuark implements QuarkBehavior {

	@Override
	public void quarkAction() {
		// TODO Auto-generated method stub
		System.out.println("I can quark normally!");
	}
	
}

abstract class Duck {
	//动态运行时对这两个行为进行改变!
	//我们通过组合两个动态实例变量 实现动态时运行和多态行为
	FlyBehavior flyBehavior;
	QuarkBehavior quarkBehavior;
	
	
	

	/**  
	* @Title: performFlyAction  
	* @Description: TODO      
	* @return void    
	* @throws
	*/  
	public void performFlyAction() {
		flyBehavior.flyAction();
	}

	/**  
	* @Title: performQuarkAction  
	* @Description: TODO      
	* @return void    
	* @throws
	*/  
	 public void performQuarkAction() {
		 quarkBehavior.quarkAction();
	 }
	 
	//设置getter 和 setter方法使得能动态改变鸭子的行为
	public FlyBehavior getFlyBehavior() {
		return flyBehavior;
	}

	public void setFlyBehavior(FlyBehavior flyBehavior) {
		this.flyBehavior = flyBehavior;
	}

	public QuarkBehavior getQuarkBehavior() {
		return quarkBehavior;
	}

	public void setQuarkBehavior(QuarkBehavior quarkBehavior) {
		this.quarkBehavior = quarkBehavior;
	}

	abstract void display();
	
	
}

class RubberDuck extends Duck {

	public RubberDuck() {
		//初始化实例变量
		flyBehavior = new CouldNotFly();
		quarkBehavior = new CouldNotQuark();
	}
	
	void display() {
		// TODO Auto-generated method stub
		System.out.println("This is a rubber duck!");
	}
	
	
}


public class SimulateDuck {
	public static void main(String[] args) {
		Duck rubberDuck = new RubberDuck();
		//让橡皮鸭发出叫和飞行这两种动作
		rubberDuck.performFlyAction();
		rubberDuck.performQuarkAction();
		rubberDuck.display();
		//让橡皮鸭增加火箭飞行的行为
		rubberDuck.setFlyBehavior(new RocketFly());
		rubberDuck.performFlyAction();
		
	}
}



角色扮演游戏的示例代码

实例代码如下所示

/**  
* @Title: MultipleWeaponTest.java  
* @Package   
* @Description: TODO(用一句话描述该文件做什么)  
* @author Lustre  
* @date 2019年12月8日  
* @version V1.0  
*/
/**
* @author Nigel
* @version 创建文件时间:2019年12月8日 上午11:09:15
*/

/**
 * 
* @InterfaceName: WeaponBehavior  
* @Description:将武器视为一种行为 即我们不应该针对具体的角色编程 而是根据角色的行为 由于每名角色有它自己的武器行为 所以针对不同的武器进行抽象
* @author Nigel  
* @date 2019年12月8日  
*
 */
interface WeaponBehavior {
	String useWeapon();
}

class KnifeBehavior implements WeaponBehavior{

	@Override
	public String useWeapon() {
		// TODO Auto-generated method stub
		String string = "正在使用Knife";
		return string;
	}
}

class BowAndArrowBehavior implements WeaponBehavior {

	@Override
	public String useWeapon() {
		// TODO Auto-generated method stub
		String string = "正在使用BowAndArrow";
		return string;
	}
	
}

class AxeBehavior implements WeaponBehavior {

	@Override
	public String useWeapon() {
		// TODO Auto-generated method stub
		String string = "正在使用Axe";
		return string;
	}
}

class SwordBehavior implements WeaponBehavior {

	@Override
	public String useWeapon() {
		// TODO Auto-generated method stub
		String string = "正在使用Sword";
		return string;
	}
}

/**
 * 
* @ClassName: Character  
* @Description: 角色基类
* @author Nigel  
* @date 2019年12月8日  
*
 */
abstract class Character {
	protected WeaponBehavior weaponBehavior;
	protected String characterName = this.getClass().getName();
	/**
	 * 
	* @Title: fight  
	* @Description: 和具体的某个人进行打斗操作 
	* @param character    
	* @return void    
	* @throws
	 */
	void fight(Character character) {
		if (character != null) {
			System.out.println( characterName  + weaponBehavior.useWeapon() + "和" + character.characterName + character.getWeaponBehavior().useWeapon() + "进行打斗" );
		} else {
			System.out.println("此时并没有和任何人进行打斗");
		}
		
	}
	
	void holdingWeapon() {
		System.out.println( characterName + weaponBehavior.useWeapon() );
	}
	
	/**
	 * 
	* @Title: getWeaponBehavior  
	* @Description: 角色可以更换所使用的武器 所以使用一个getter和 setter方法来变更对应的武器
	* @return    
	* @return WeaponBehavior    
	* @throws
	 */
	public WeaponBehavior getWeaponBehavior() {
		return weaponBehavior;
	}

	public void setWeaponBehavior(WeaponBehavior weaponBehavior) {
		this.weaponBehavior = weaponBehavior;
	}
}

class Queen extends Character {

	/**
	 * 
	* 创建一个新的实例 Queen.  
	*
	 */
	public Queen() {
		this.weaponBehavior = new AxeBehavior();
	}
}

class King extends Character {
	
	public King() {
		this.weaponBehavior = new KnifeBehavior();
	}
}

/**  
* @ClassName: MultipleWeaponTest  
* @Description: TODO(这里用一句话描述这个类的作用)  
* @author Nigel  
* @date 2019年12月8日  
*    
*/
public class MultipleWeaponTest {

	/**  
	* @Title: main  
	* @Description: TODO  
	* @param args    
	* @return void    
	* @throws
	*/
	public static void main(String[] args) {
		//初始化一个king对象
		Character myKing = new King();
		//初始化一个queen对象
		Character myQueen = new Queen();
		
		//进行行为识别
		myKing.holdingWeapon();
		myQueen.holdingWeapon();
		
		//进行打斗测试
		myKing.fight(myQueen);
		//myQueen.fight(myKing);
		
		//更换武器
		myKing.setWeaponBehavior(new BowAndArrowBehavior());
		myKing.fight(myQueen);
	}

}

观察者模式

给出一个观察者模式的应用场景多个受体依赖于一个主体的时候 我们就可以使用主体-观察者这个设计模式 即Observer-Subject model 下面的应用场景是有一个气象站(起到数据广播的作用)和n个气象显示设备 现在要求气象设备能实时的接收气象站数据的更新状况 此时就是一对多的一个依赖关系 我们通过一个抽象的Observer和Subject接口来实现抽象 Subject接口实现注册 删除 通知功能 在通知功能中我们通过遍历来调用抽象的Observer.update()接口实现统一 具体的实现则是由观察者实现。 这样做到了一个**所谓的松耦合 即低耦合 **

观察者模式的示例代码见下

import java.util.ArrayList;
import java.util.List;

/**  
* @Title: WhetherConditionTest.java  
* @Package   
* @Description: TODO(用一句话描述该文件做什么)  
* @author Lustre  
* @date 2019年12月8日  
* @version V1.0  
*/
/**
* @author Nigel
* @version 创建文件时间:2019年12月8日 下午2:29:41
*/

/**
 * 
* @ClassName: Subject  
* @Description: 主体数据
* @author Nigel  
* @date 2019年12月8日  
*
 */
interface Subject {
	//可以设置天气状况
	void setWhetherInfomationAndNotify(WhetherBean whether);
	//注册成为观察者 则在更新的时候会即时接受到数据
	void RegisterObserver(Observer observer);
	//可以进行移除操作
	void RemoveObserver(Observer observer);
	//在数据变换的时候及时通知观察者进行数据的更新操作
	void NotifyObserver();
}

/**
 * 
* @ClassName: Observer  
* @Description: 观察者 这里我们仅仅需要实现update接口即可
* @author Nigel  
* @date 2019年12月8日  
*
 */
interface Observer {
	void update(Object object);
	void setSubject(Subject subject);
	void removeSelf();
}


/**
 * 
* @ClassName: DisplayData  
* @Description: 由于在这个example中 我们想要展示对应的数据信息 所以也需要继承的"布告板"实现这个display接口
* @author Nigel  
* @date 2019年12月8日  
*
 */
interface DisplayData {
	/**  
	* @Title: displayStatisticsBoardInfo  
	* @Description: TODO  
	* @param whether    
	* @return void    
	* @throws
	*/  
	void display(Object object);
}


class WhetherData implements Subject {
	private List<Observer> observers;
	private WhetherBean whether;//我们只需要维护一个WhetherBean对象即可 将所有的数据放进去 update的时候由程序自己取它自己想要的数据
	
	@Override
	public void setWhetherInfomationAndNotify(WhetherBean whether) {
		//首先更新数据
		this.whether = whether;
		//然后通知所有观察者数据进行了更新的操作
		NotifyObserver();
	}
	
	/**  
	* 创建一个新的实例 WhetherData.  
	*    
	*/
	public WhetherData() {
		//创建一个列表
		observers = new ArrayList<Observer>();
	}

	@Override
	public void RegisterObserver(Observer observer) {
		// TODO Auto-generated method stub
		//由测试程序进行调用 我们需要将新的观察者加入到收听者那部分去
		observers.add(observer);
		//然后将主体传送给观察者
		observer.setSubject(this);
		System.out.println("成功添加一个观察者");
	}

	@Override
	public void RemoveObserver(Observer observer) {
		// TODO Auto-generated method stub
		observers.remove(observer);
	}

	@Override
	public void NotifyObserver() {
		// 遍历每一个观察进行数据的更新!
		for (int i = 0; i < observers.size(); i++) {
			Observer observer = observers.get(i);
			//通过统一的update接口实现数据的更新操作
			observer.update(whether);
		}
	}
}

/**
 * 
* @ClassName: ConcreteDisplayData  
* @Description: 展示具体的数据信息 作为一个视图层来使用 这里我们借鉴了MVC的使用 因为展示也是一个不断变化的部分 所以我们把它也单独抽象了出来
* @author Nigel  
* @date 2019年12月8日  
*
 */
class ConcreteDisplayData implements DisplayData{

	@Override
	public void display(Object whether) {
		//这里简单的在Whether中写了个toString方法 然后进行打印操作
		System.out.println(whether);
	}
	
}

class StatisticsBoard implements Observer {
	//维护一个bean对象和一个数据展示对象
	private WhetherBean whether;
	private DisplayData display = new ConcreteDisplayData();
	private Subject whetherSubject;
	
	/**
	* <p>Title: update</p>  
	* <p>Description: 数据更新及展示功能
	* @see Observer#update()  
	*/  
	@Override
	public void update(Object whether) {
		//由监听者选择从Bean对象中取出哪些数据 而Subject主题对象只需要一股脑的将所有数据放进去即可
		this.whether = (WhetherBean) whether;
		//由display负责展示
		display.display(whether);
	}

	/**
	* <p>Title: setSubject</p>  
	* <p>Description: </p>  
	* @param subject  
	* @see Observer#setSubject(Subject)  
	*/  
	@Override
	public void setSubject(Subject subject) {
		// TODO Auto-generated method stub
		whetherSubject = subject;
	}

	/**
	* <p>Title: removeSelf</p>  
	* <p>Description: </p>    
	* @see Observer#removeSelf()  
	*/  
	@Override
	public void removeSelf() {
		// 删除自己
		whetherSubject.RemoveObserver(this);
	}

}

/**  
* @ClassName: WhetherConditionTest  
* @Description: TODO(这里用一句话描述这个类的作用)  
* @author Nigel  
* @date 2019年12月8日  
*    
*/
public class WhetherConditionTest {

	/**  
	* @Title: main  
	* @Description: TODO  
	* @param args    
	* @return void    
	* @throws
	*/
	public static void main(String[] args) {
		//用于测试Subject 和  Observer 的功能
		Float temperature = 38.6F;
		Float humidity = new Float(30.9);
		WhetherBean testWhetherBean = new WhetherBean();
		//设置测试的bean对象
		testWhetherBean.setHumidity(humidity);
		testWhetherBean.setTemperature(temperature);
		//建立一个Observer对象
		Observer testObserver = new StatisticsBoard();
		//测试Subject对象
		System.out.println("没有监听者的情况:");
		Subject testWhetherData = new WhetherData();
		testWhetherData.setWhetherInfomationAndNotify(testWhetherBean);
		//加入一个监听者
		System.out.println("加入一个监听者之后:");
		testWhetherData.RegisterObserver(testObserver);
		testWhetherData.setWhetherInfomationAndNotify(testWhetherBean);
		//测试数据的更新
		System.out.println("测试对数据进行更改操作:");
		temperature = 38.6F + 3F;
		humidity = new Float(324.9);
		testWhetherBean.setHumidity(humidity);
		testWhetherBean.setTemperature(temperature);
		testWhetherData.setWhetherInfomationAndNotify(testWhetherBean);
		//再次增加一个观察者
		System.out.println("再次增加一个观察者:");
		Observer testObserver2 = new StatisticsBoard();
		testWhetherData.RegisterObserver(testObserver2);//添加到观察者列表
		testWhetherData.setWhetherInfomationAndNotify(testWhetherBean);
		//删除一个观察者 由观察者自身想退出观察!
		System.out.println("由观察者自身进行退出观察操作:");
		testObserver2.removeSelf();
		testWhetherData.setWhetherInfomationAndNotify(testWhetherBean); //此时再次更新
		//由主体数据将观察者进行移除
		System.out.println("由主体数据将观察者进行移除(此时移除后更新发现没有确实成功的移除了一个观察者):");
		testWhetherData.RemoveObserver(testObserver);
		testWhetherData.setWhetherInfomationAndNotify(testWhetherBean); //此时再次更新
		
	}

}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值