策略模式



策略模式定义了一系列算法,并将每个算法封装起来,而且他们相互替换不会使客户端感到影响。我看可以看出,策略抽象类是抽象类算法的抽象,context类聚合策略类,聚合关系表现在强的关联关系,是部分跟整体的关系。所以一般策略抽象类被context关联使用在构造函数中。

简单工厂模式与策略类差不多结构,但是context与factory之间是依赖,也就是说工厂类只是context类中的某个函数的方法参数或者方法的成员变量。

策略模式(Strategy):
 它定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换。
 策略模式让算法的变化不会影响到使用算法的客户
优点:

1、 简化了单元测试,因为每个算法都有自己的类,可以通过自己的接口单独测试。
2、 避免程序中使用多重条件转移语句,使系统更灵活,并易于扩展。
3、 遵守大部分GRASP原则和常用设计原则,高内聚、低偶合。

缺点:
1、 因为每个具体策略类都会产生一个新类,所以会增加系统需要维护的类的数量。

2、 在基本的策略模式中,选择所用具体实现的职责由客户端对象承担,并转给策略模式的Context对象。(这本身没有解除客户端需要选择判断的压力,而策略模式与简单工厂模式结合后,选择具体实现的职责也可以由Context来承担,这就最大化的减轻了客户端的压力。)

简单工厂模式和策略模式区别(摘录,出处)

这两种模式的作用就是拥抱变化,减少耦合。在变化来临时争取做最小的改动来适应变化。这就要求我们把些“善变”的功能从客户端分离出来,形成一个个的功能类,然后根据多态特性,使得功能类变化的同时,客户端代码不发生变化。

package package0416;

//策略抽象类,支付策略
abstract class Stractegy{
	public abstract void payMehtod();
}
//策略具体类,人民币支付,实现抽象类方法
class RMBcash extends Stractegy{

	@Override
	public void payMehtod() {
		// TODO Auto-generated method stub
		System.out.println("人民币支付");
	}
}
//策略具体类,美元支付,实现抽象类方法
class Dollar extends Stractegy{

	@Override
	public void payMehtod() {
		// TODO Auto-generated method stub
		System.out.println("美元支付");
	}
}
//策略具体类,银行卡支付,实现抽象类方法
class Card extends Stractegy{

	@Override
	public void payMehtod() {
		// TODO Auto-generated method stub
		System.out.println("银行卡支支付");
	}
}
//上下文,维护对策略的引用
class Context{
	private Stractegy stractegy;
	//将策略作为生命周期函数参数,组合关系
	public Context(Stractegy stractegy){
		this.stractegy=stractegy;
	}
	
	public void payMethod(){
		stractegy.payMehtod();
	}
}

public class StrategyContext {

	
	public static void main(String[] args) {
		
		Context context=null;
		context=new Context(new Dollar());
		context.payMethod();
		context=new Context(new Card());
		context.payMethod();
		context=new Context(new RMBcash());
		context.payMethod();
	}

}

 

简单工厂模式

 

简单工厂模式:有一个父类需要做一个运算(其中包含了不同种类的几种运算),将父类涉及此运算的方法都设成虚方法,然后父类派生一些子类,使得每一种不同的运算都对应一个子类。另外有一个工厂类,这个类一般只有一个方法(工厂的生成方法),这个方法的返回值是一个超类,在方法的内部,根据传入参数的不同,分别构造各个不同的子类的对象,并返回。客户端并不认识子类,客户端只认识超类和工厂类。每次客户端需要一中运算时,就把相应的参数传给工厂类,让工厂类构造出相应的子类,然后在客户端用父类接收(这里有一个多态的运用)。客户端很顺理成章地用父类的计算方法(其实这是一个虚方法,并且已经被子类特化过了,其实是调用子类的方法)计算出来结果。如果要增加功能时,你只要再从父类中派生相应功能的子类,然后修改下工厂类就OK了,对于客户端是透明的。

策略模式

策略模式:策略模式更直接了一点,没有用工厂类,而是直接把工厂类的生成方法的代码写到了客户端。客户端自己构造出了具有不同功能的子类(而且是用父类接收的,多态),省掉了工厂类。策略模式定义了算法家族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化,不会影响到使用算法的客户。这里的算法家族和简单工厂模式里的父类是同一个概念。当不同的行为堆砌在一个类中时,就很难避免使用条件语句来选择合适的行为,将这些行为封装在一个个独立的策略子类中,可以在客户端中消除条件语句。

简单工厂模式+策略模式:为了将工厂方法的代码从客户端移出来,我们把这些代码搬到了父类的构造函数中,让父类在构造的时候,根据参数,自己实现工厂类的作用。这样做的好处就是,在客户端不用再认识工厂类了,客户端只要知道父类一个就OK,进一步隔离了变化,降低了耦合。

在基本的策略模式中,选择所用具体实现的职责由客户端对象成端,并转给客户端。这本身并没有减除客户端需要选择判断的压力,而策略模式与简单工厂模式结合后,选择具体实现的职责也可以由父类承担,这就最大化地减轻了客户端的职责。
结合点:在context类的构造方法 中,改造为工厂方法

package package0416;

import java.util.Scanner;

//策略抽象类,支付策略
abstract class Stractegy{
	public abstract void payMehtod();
}
//策略具体类,人民币支付,实现抽象类方法
class RMBcash extends Stractegy{

	@Override
	public void payMehtod() {
		// TODO Auto-generated method stub
		System.out.println("人民币支付");
	}
}
//策略具体类,美元支付,实现抽象类方法
class Dollar extends Stractegy{

	@Override
	public void payMehtod() {
		// TODO Auto-generated method stub
		System.out.println("美元支付");
	}
}
//策略具体类,银行卡支付,实现抽象类方法
class Card extends Stractegy{

	@Override
	public void payMehtod() {
		// TODO Auto-generated method stub
		System.out.println("银行卡支支付");
	}
}
//上下文,维护对策略的引用
class Context{
	private Stractegy stractegy;
	//将策略作为生命周期函数参数,组合关系
	public Context(String type){
		switch(type){
		case "1":
			stractegy=new RMBcash();
			break;
		case "2":
			stractegy=new Card();
			break;
		case "3":
			stractegy=new Dollar();
			break;
		}
	
	}
	
	public void payMethod(){
		stractegy.payMehtod();
	}
}


public class StrategyContext {

	
	public static void main(String[] args) {
		
		Context context=null;
		Scanner in=new Scanner(System.in);
		System.out.println("请输入支付方式:1:人民币   2:银行卡  3:美元");
		context=new Context(in.next());
		context.payMethod();
		
	}

}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值