java设计模式之策略模式

什么是策略模式?策略模式就是:定义了算法族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化独立于使用算法的客户,简单点来说就是“封装变化”.仍然以手机为列,举一个反列:有两个手机 HuaWeiMobile.java,和XiaoMiMobile.java,这两个手机都有一个1200W的后置摄像头来拍照( photo()方法),都能打电话( call() 方法),为了代码复用,不在每一个子类中都实现这两个方法,可以在这两个子类的父类(OppositeMobile.java)中实现这两个方法,就像下面这样

 

package strategy;
/**
 * 反列
 * @author Administrator
 *
 */
public class OppositeMobile {
	public void photo(){
		System.out.println("用1200W后置摄像头拍照");
	}
	
	public void call(){
		System.out.println("打电话");
	}
}

 

 

 

 

 

 

但是这有一个问题,假如有一个魅族手机(MeiZuMoible.java)他的后置摄像头是2100W的,那怎么办?假如又有一个老式的诺基亚手机,他没有拍照功能,那又怎么办,我们可以看出,对于拍照这个功能,对于不同的手机,可能会有不同的实现,他是不断变化的,我们没法为了“复用”而把它放在父类中实现,难道没有办法了吗?有办法,我们可以重写 MeiZuMobile.java等子类中的 photo()方法,从而覆盖父类的实现,一个还好说,假如有100个手机呢,都有自己的后置摄像头像素,每一次都要被迫去检查photo()方法,看是否需要覆盖父类的实现。这显然太糟糕了。。这时候我们的另一种解决办法是把photo()这个方法抽取出来,把这个方法放到一个接口中 Photo.java 中,然后让有拍照功能的手机 如 魅族手机,和华为手机,去实现这个接口,至于用2100 w 还是用1200W像素 让这两个子类自己去实现,对于没有拍照功能的老式诺基亚手机,就不需要实现这个接口。但是,这又造成了新的问题,假如有很多手机都是 用同一个像素比如1200w 像素,那么每个这种像素的手机类中的 photo()方法中的代码都是一样的,这样就没法“复用”代码了,也就是说用实现接口这种方式,没法复用代码,这中情况下又该怎么办?

 

这时候就是策略模式大显身手的时候了。还记得刚说的策略模式的核心是什么了吗 “封装变化”,我们把 photo()这个方法抽取出来,定义到一个接口里边(AbstractPhotoStrategy.java),如下

但是这里我们不是让手机子类去实现这个接口,而是把他独立成一个接口(或者父类),让 PhotoWith1200Strategy.java   ,PhotoWith2100Strategy.java    

这两个子类去实现 AbstractPhotoStrategy.java  接口中的 photo()方法,

AbstractPhotoStrategy .java

 

/**
 * 抽象策略角色
 */
public interface AbstractPhotoStrategy {
	public void photo();
}

 

PhotoWith1200Strategy.java

 

package design.strategy;

/**
 * 具体策略角色
 */
public class PhotoWith1200Stragegy implements AbstractPhotoStrategy {

	@Override
	public void photo() {
		System.out.println("用1200W摄像头拍照");

	}

}

 

 

 

 

 

PhotoWith2100Stragegy .java

 

package design.strategy;
/**
 * 具体策略角色
 */
public class PhotoWith2100Stragegy implements AbstractPhotoStrategy {

	@Override
	public void photo() {
		System.out.println("用2100W摄像头拍照");

	}

}

 

 

 

 

 

这是不是一个策略?仔细想试是不是有那么点意思?,策略模式也有几个角色,如下:

(1)抽象策略角色(如上,AbstractPhotoStrategy.java,一个接口)

(2)具体策略角色(下面的,PhotoWith1200Stragegy.java,    PhotoWith2100Stragegy.java)

(2)环境角色(Context.java,持有对策略角色的引用(引用的是父类或者接口类型,也就是超类型,为的是能够使用多态这个特性))
我们定义一个AbstractPhotoStrategy.java的实现类 PhotoWith1200Stragegy.java给华为,和小米手机用来拍照用的,魅族不是浪吗,给魅族定义一个AbstractPhotoStrategy.java的实现类 PhotoWith2100Stragegy.java,给魅族用来拍照的。(这里面体现了一个设计原则:针对接口编程,这里的接口不是就单单指 interface,指的是针对超类型,父类啊,接口啊,都是超类型).

我们定义一个环境角色Context.java, 让子类型 HuaWeiMobile.java , XiaoMiMobile.java ,MeiZuMobile.java 拥有环境角色的引用(成员变量)。

 

环境角色 Context.java

 

package design.strategy;

public  class Context {
	//环境角色持有对抽象策略角色的引用
	AbstractPhotoStrategy photo;
	
	public  void photo() {
		photo.photo();
	}
	public void call(){
		System.out.println("打电话");
	}

	public AbstractPhotoStrategy getPhoto() {
		return photo;
	}

	public void setPhoto(AbstractPhotoStrategy photo) {
		this.photo = photo;
	}
	
	
}

	
	
}

 

 

上面体现了一个设计原则 :“多用组合,少用继承”,Context.java中的成员变量 photo 就是组合,然后委托photo干活,组合使Context.java具备了他自身没有的功能(photo对象的功能)

 

 

 

 HuaWeiMobile.java

 

package design.strategy;

public class HuaWeiMobile{
	Context context;//可以通过构造方法参数或者是get,set方法传入
	public void photo(){
		context.photo();//委托,委托给 context 干活
	}

	public Context getContext() {
		return context;
	}

	public void setContext(Context context) {
		this.context = context;
	}
}


XiaoMiMobile.java

 

package design.strategy;

public class XiaoMiMobile {
	Context context;//可以通过构造方法参数或者是get,set方法传入
	public void photo(){
		context.photo();//委托,委托给 context 干活
	}

	public Context getContext() {
		return context;
	}

	public void setContext(Context context) {
		this.context = context;
	}
}


MeiZuMobile.java

 

package design.strategy;

public class MeiZuMobile {
	Context context;//可以通过构造方法参数或者是get,set方法传入
	public void photo(){
		context.photo();//委托,委托给 context 干活
	}

	public Context getContext() {
		return context;
	}

	public void setContext(Context context) {
		this.context = context;
	}
}

 

 

 

客户端测试类ClientTest.java

 

 

package design.strategy;

import org.junit.Test;

public class ClientTest {

	@Test
	public void test() {
		HuaWeiMobile huaWeiMobile=new HuaWeiMobile();
		Context context1=new Context();
		context1.setPhoto(new PhotoWith1200Stragegy());
		huaWeiMobile.setContext(context1);
		huaWeiMobile.photo();
		
		System.out.println("--------------->");
		XiaoMiMobile xiaoMiMobile=new XiaoMiMobile();
		Context context2=new Context();
		context2.setPhoto(new PhotoWith1200Stragegy());
		xiaoMiMobile.setContext(context2);
		xiaoMiMobile.photo();
		
		System.out.println("---------->");
		MeiZuMobile meiZuMobile=new MeiZuMobile();
		Context context3=new Context();
		context3.setPhoto(new PhotoWith2100Stragegy());
		meiZuMobile.setContext(context3);
		meiZuMobile.photo();
	}

}

 

 

用1200W摄像头拍照
--------------->
用1200W摄像头拍照
---------->
用2100W摄像头拍照


当然,如果你愿意的话,也可以让HuaWeiMobile.java 华为手机用上2100W的后置摄像头。。。o(╯□╰)o

 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值