策略模式

0.前言

原本是本周五想推出一个自己本认为写的很好的一篇作业给大家分享的,但是后来论文分析以及其它琐事就延迟了这次的博客,现在乘着空隙,回想自己的考试内容以及学习的过程,分享自己的心得。

1.策略模式

(1)策略,当然指的是面对一件事情不同的处理方法,我们将这套方法的一个流程称之为策略。

(2)那么,什么是策略模式呢?所谓策略模式,我的理解就是,通过调用不同的方法,但是却实现同样的功能的一个过程,即是策略模式。下面给出的是《设计模式的艺术之道》中的定义:"定义一系列算法类,将每一个算法封装起来,并让他们互相替换,策略模式让算法独立于使用它的客户而变化,也称为政策模式,是一种对象型行为型模式。"

2.案例分析

  • (1)下面给出我本周五的《设计模式》考试题:

学校新开了一家超市,为了吸引同学们到店里购物,超市采用了一些针对性的措施,如果加入超市的会员,购物享有9.5折优惠,如果既是会员又采用支付宝支付,购物享有9.2折优惠,对于vip会员(需要该会员在超市消费总额已超过1000元),购物享有9折优惠。

1) 试问根据该描述应该采用哪一种设计模式,并给出其类图。(30分)

2)试根据题意设计满足题意要求的类和客户端代码。(70分)

  • (2)分析题意可知,这个超市中购物者有三种消费者,对应的是三种消费方式,一种是普通会员的9.5折优惠;一种是普通会员但是使用支付宝的9.2折优惠;一种是超级vip的9.0种优惠。有这么三种消费方式。所以很明显,我们应该采用策略模式。
  • (3)但是我们注意到:对于超级vip我们有两种方式,一种是当他的积分>=1000时,他才享有9.0折优惠;假若积分没有达到1000,还是和普通的会员一样,这里我们可以将积分视为一种改变消费的因素,而不同的状态下有着不同的享折优惠,所以我们可以对超级vip使用状态模式,于是画出类图如下:
  • (4)根据以上分析,我们结合策略模式知识知道,有一个SuperMarket,作为超市类;有一个Customer,作为抽象购物者类;有一个接口Pay,代表的是使用支付宝支付的这个方式;有一个CommonMember1,是普通会员类,单纯继承自Customer;有一个CommonCustomer2,是普通会员类,继承自Customer类,实现Pay接口;有一个SuperMember,继承自Customer;当然这个SuperMember有两种状态,在不同的状态下享有不同的优惠,于是有一个State,为抽象状态类;所以就有一个GreaterThanThousand,为积分超过1000元的类,继承自State;同理,有一个LessThanThousand类,继承自State类。
  • (5)综上所述,得到如下类:

SuperMarket,作为超市类;

Customer,作为抽象购物者类;

接口Pay,代表的是使用支付宝支付的这个方式;

CommonMember1,是普通会员类,单纯继承自Customer;

CommonCustomer2,是普通会员类,继承自Customer类,实现Pay接口

SuperMember,继承自Customer

State,为抽象状态类;

GreaterThanThousand,为积分超过1000元的类,继承自State;

LessThanThousand类,继承自State类。画出类图如下所示:

3.代码实现

1.Client类
package liu.shen;

/**
 * 客户端测试代码
 * @author Object
 *
 */
public class Client {
	public static void main(String args[]){
		Customer cMember1,cMember2,sMember1,sMember2;//代表三种不同支付的人
		
		//实例化三种不同的购物者
		cMember1 = (Customer) XmlUtil.getObject(0);//未使用支付宝支付
		cMember2 = (Customer) XmlUtil.getObject(1);//使用支付宝
		sMember1 = (Customer) XmlUtil.getObject(2);//积分<1000的超级会员
		sMember2 = (Customer) XmlUtil.getObject(2);//积分>=1000的超级会员
		
		
		/*设置各个对象的属性值*/
		cMember1.setName("Class");
		cMember1.setBond(100);
		
		cMember2.setName("Return");
		cMember2.setBond(100);
		
	    sMember1.setName("Void");
		sMember1.setBond(100);
		((SuperMember) sMember1).setState();
		
		sMember2.setName("Object");
	    sMember2.setBond(1001);
	    ((SuperMember) sMember2).setState();

	    
	    /*新建一个超市对象*/
		SuperMarket sMarket = new SuperMarket();
		sMarket.welcome();
		sMarket.buy(cMember1);
		sMarket.buy(cMember2);
		sMarket.buy(sMember1);
		sMarket.buy(sMember2);
		sMarket.banner();
		
	}
}



3. CommonMember2类
package liu.shen;

/**
 * 普通会员类,继承Customer,实现Pay功能
 * @author Object
 *
 */
public class CommonMember2 extends Customer implements Pay{

	
	@Override
	public void pay() {
		// TODO Auto-generated method stub
		System.out.println("我是普通会员,我叫:"+this.name+",但是使用支付宝支付,所以享受9.2折优惠!");
	}

	@Override
	public void buy() {
		// TODO Auto-generated method stub
		this.pay();//使用支付宝支付
	}

}


4. Customer类
package liu.shen;

/**
 * Customer类,为抽象购物者类
 * @author Object
 *
 */
public abstract class Customer {
	String name;//顾客姓名
	int bond;//积分
	
	public abstract void buy();//抽象的购物方法

	public void setName(String name) {
		// TODO Auto-generated method stub
		this.name = name;
	}
	
	public void setBond(int bond) {
		// TODO Auto-generated method stub
		this.bond = bond;
	}
	
}


5. GreaterThanThousand类
package liu.shen;


public class GreaterThanThousand extends State{
	SuperMember sMember;
	
	public GreaterThanThousand(SuperMember sMember){
		this.sMember = sMember;
	}

	@Override
	public void buy() {
		// TODO Auto-generated method stub
		System.out.println("我是超级会员,我叫:"+sMember.name+",我的积分是:"+sMember.bond+
				">=1000,享受9.0折优惠!");
	}
	
}

6. LessThanThousand类
package liu.shen;


public class LessThanThousand extends State{
	
	SuperMember sMember;
	
	public LessThanThousand(SuperMember sMember){
		this.sMember = sMember;
	}
	
	@Override
	public void buy() {
		// TODO Auto-generated method stub
		System.out.println("我是超级会员,我叫:"+sMember.name+",我的积分是:"+sMember.bond+
				"<1000,享受9.5折优惠!");
	}
	

}


7. Pay类
package liu.shen;

/**
 * Pay,接口,使用支付宝支付
 * @author Object
 *
 */
public interface Pay {
	public void pay();
}


8. State类
package liu.shen;


/**
 * 超级会员的状态类
 * @author Object
 *
 */
public abstract class State {

	
	public abstract void buy();
}


9. SuperMarket类
package liu.shen;

/**
 * 商店类
 * @author Object
 *
 */
public class SuperMarket {
	//public Customer customer;
	
	public void buy(Customer customer){
		customer.buy();//购物者购买
	}
	
	
	public void welcome(){
		System.out.println("--------------顾客你好,欢迎来到**超市购物,本超市现有如下优惠政策-------------------");
		System.out.println("(1)会员:购物享有9.5折优惠");
		System.out.println("(2)既是会员又采用支付宝支付,购物享有9.2折优惠");
		System.out.println("(3)vip会员(消费总额已超过1000元),购物享有9折优惠");
		System.out.println("-----------------------------------------------------------------");
		System.out.println("");
	}
	
	public void banner(){
		System.out.println("-----------------------------------------------------------------");		
	}
}

10. SuperMember类
package liu.shen;


/**
 * 超级会员类,继承自Customer
 * @author Object
 *
 */
public class SuperMember extends Customer{	
	public State state;
	
	public void setState(){
		if(this.bond>=1000){
			state = new GreaterThanThousand(this);//则将其更改成超级会员+积分>=1000
		}
		else{
			state = new LessThanThousand(this);
		}
	}
	
	@Override
	public void buy() {
		// TODO Auto-generated method stub	
		state.buy();
	}
}


11.XmlUtil类
package liu.shen;

import java.io.File;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

/**
 * 处理xml文件
 * @author Object
 *
 */
public class XmlUtil {
	
	public static Object getObject(int i){
		
		try {
			DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
			DocumentBuilder dbuilder;
			dbuilder = dbFactory.newDocumentBuilder();
			Document document;
			
			document = dbuilder.parse(new File("config.xml"));
			
			NodeList nList = document.getElementsByTagName("className");
			
			
			Node classNode = null;//
			
			if(i == 0){
				classNode = nList.item(0).getFirstChild();
			}
			else if(i == 1){
				classNode = nList.item(1).getFirstChild();
			}
			else if(i == 2){
				classNode = nList.item(2).getFirstChild();
			}
			String cName = classNode.getNodeValue();
			
			//System.out.println(cName);			
			Class c =Class.forName(cName);			
			Object object =c.newInstance(); 
			
			return object;
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;		
	}
}


4.实验结果

5.总结

(1)考试过后,很多同学问我,这题到底该用什么模式实现,根据上面的分析,我们可以很清楚的知道,这一题肯定会是使用策略模式,策略模式就是解决这种“做一件事可以有很多种解决方案”的问题。

(2)能选择策略模式做出这一题并不算高明,毕竟一个班抬眼看去,肯定会有百分之七十的人这么做。但是在这百分这七十的人中肯定会有百分之九十的人会花出一个不算完美的类图。比如说,我在上面说到的那个使用支付宝支付的普通会员享受9.2折优惠,对于这一点,我们就一定要意识到,使用支付宝支付这是一个行为,有的消费者具有,有的消费者不具有,所以“支付宝支付”这个肯定是一个接口,有的消费者可以实现,有的消费者可以不实现。

(3)同时,对于超级会员的两种状态也是一个加分项【我认为的】,毕竟这一题主要的考点是策略模式,并不是状态模式,但是只要在涉及超级会员的时候写到状态模式时就会有一个很强的优势。【想要具体了解状态模式,详情见:http://blog.csdn.net/liu16659/article/details/53138022】

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

说文科技

看书人不妨赏个酒钱?

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值