行为型设计模式

        行为型设计模式目的是将多个类或对象相互协作,共同完成单个类或对象无法单独完成的任务。行为型设计模式共11种,分别为解释器模式、模板方法模式、责任链模式、命令模式、迭代器模式、中介者模式、备忘录模式、观察者模式、状态模式、策略模式、访问者模式。

一、解释器模式

        解释器模式指预先定义一种语法,然后根据语法对传入数据进行解析。例如java中正则表达式解析就是使用该模式。其优点为扩展性好,容易实现,但执行效率较低,并且每种语法对应一种实现,需要建大量类。在解释器模式中存在抽象解释器(AbstractExpression),终结符表达式(TerminalExpression),非终结符表达式(NonterminalExpression),上下文(Context),客户类(Test)五种角色。以简单的规则定义为例,代码如下

新建抽象表达式Expression

/**
 * 抽象表达式:定义所有终结符表达式和非终结符表达式的解释操作
 * 
 * @author huaisf
 *
 */
public interface Expression {

	public boolean interpret(String value);
}

新建非终结符表达式NonterminalExpression

/**
 * 非终结符表达式:实现非终结操作
 * 
 * @author huaisf
 *
 */
public class NonterminalExpression implements Expression {

	private Expression terminalExpression = null;

	public NonterminalExpression(Expression terminalExpression) {
		this.terminalExpression = terminalExpression;
	}

	public boolean interpret(String value) {
		// 没有非终结符,直接调用终结符表达式
		return terminalExpression.interpret(value);
	}
}

新建终结符表达式TerminalExpression

/**
 * 终结符表达式:实现终结操作
 * 
 * @author huaisf
 *
 */
public class TerminalExpression implements Expression {

	private Map map = new HashMap();

	public TerminalExpression(String rule) {
		int index = rule.indexOf(":");
		String city = rule.substring(0, index);
		String scenery = rule.substring(index + 1, rule.length());
		map.put(city, scenery);

	}

	@Override
	public boolean interpret(String value) {
		int index = value.indexOf(":");
		String city = value.substring(0, index);
		String scenery = value.substring(index + 1, value.length());
		String existScenery = map.get(city);
		if (existScenery != null && existScenery.equals(scenery)) {
			return true;
		}
		return false;
	}

}

新建上下文Context

/**
 * 上下文:完成终结表达式初始化,并对要解释的数据进行中转
 * 
 * @author huaisf
 *
 */
public class Context {

	private Expression nonterminalExpression;

	public Context(String rule) {
		Expression terminalExpression = new TerminalExpression(rule);
		nonterminalExpression = new NonterminalExpression(terminalExpression);
	}

	public void matches(String value) {
		boolean isExist = nonterminalExpression.interpret(value);
		if (isExist) {
			System.out.println("城市与景区对应成功");
			return;
		}
		System.out.println("城市与景区对应失败");
	}
}

新建测试类Test

public class Test {

	public static void main(String[] args) {
		// 定义规则为"杭州:西湖"进行验证
		Context context = new Context("杭州:西湖");
		context.matches("杭州:西湖");
		context.matches("苏州:西湖");
		context.matches("苏州:太湖");
	}
}

二、模板方法模式

        模板方法指在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤。使用模板方法可提取公共逻辑进行封装,对于非公共操作交由子类执行,但非公共操作如果有改变,则会影响其所有子类。模板方法中分为抽象模板(AbstractTemplate)与具体实现模板(ConcreteTemplate)两种角色。以生产插排为例,代码如下

新建抽象模板Socket

/**
 * 抽象模板:定义具体操作及抽象操作,抽象操作由子类实现
 * 
 * @author huaisf
 *
 */
public abstract class Socket {

	/**
	 * 封装公共逻辑
	 */
	final void create() {

		// 先购买材料
		buyMaterial();

		// 然后材料组装成插排
		assembly();

		// 印上各厂商logo
		printLogo();

	}

	void buyMaterial() {
		System.out.println("购买材料");
	}

	void assembly() {
		System.out.println("材料组装成插排");
	}

	/**
	 * 印上logo
	 */
	abstract void printLogo();

}

新建具体实现模板BullSocket与TCLSocket

/**
 * 具体实现模板:实现父类定义的抽象方法,重写父类逻辑
 * 
 * @author huaisf
 *
 */
public class BullSocket extends Socket {

	@Override
	void printLogo() {
		System.out.println("图上公牛的logo");

	}

}


/**
 * 具体实现模板:实现父类定义的抽象方法,重写父类逻辑
 * 
 * @author huaisf
 *
 */
public class TCLSocket extends Socket {

	@Override
	void printLogo() {
		System.out.println("图上TCL的logo");

	}

}

新建测试类Test

public class Test {

	public static void main(String[] args) {
		// 生产公牛插排
		BullSocket bullSocket = new BullSocket();
		bullSocket.create();

		// 生成tcl插排
		TCLSocket tclSocket = new TCLSocket();
		tclSocket.create();

	}
}

三、责任链模式

        责任链模式是对某个请求的所有处理构成一条链,如果链上的某一处理者可以处理,则处理后返回。如果不能处理则将请求传递给链上的下一个处理者。责任链模式中存在抽象处理者(Handler)与具体处理者(ConcreteHandler)两种角色。以购买插排为例,代码如下:

新建抽象处理者AbstractSocketHandler

/**
 * 抽象处理者:定义处理请求接口
 * 
 * @author huaisf
 *
 */
public abstract class AbstractSocketHandler {

	private AbstractSocketHandler NextHandler;

	public AbstractSocketHandler getNextHandler() {
		return NextHandler;
	}

	public void setNextHandler(AbstractSocketHandler nextHandler) {
		NextHandler = nextHandler;
	}

	/**
	 * 购买插排
	 * 
	 * @param count
	 */
	abstract void buySocket(Integer count);
}

新建具体处理者OriginalPriceSocketHandler、NineDiscountSocketHandler、EightDiscountSocketHandler

/**
 * 具体处理者:对抽象处理者定义的接口进行实现,如果无法处理则将请求传递给下一个处理者
 * 
 * @author huaisf
 *
 */
public class OriginalPriceSocketHandler extends AbstractSocketHandler {

	@Override
	void buySocket(Integer count) {
		if (count <= 500) {
			System.out.println("原价购买插排");
			return;
		}
		this.getNextHandler().buySocket(count);
	}

}

public class NineDiscountSocketHandler extends AbstractSocketHandler {

	@Override
	void buySocket(Integer count) {
		if (count > 500 && count <= 5000) {
			System.out.println("九折购买插排");
			return;
		}
		this.getNextHandler().buySocket(count);
	}
}

public class EightDiscountSocketHandler extends AbstractSocketHandler {

	@Override
	void buySocket(Integer count) {
		if (count > 5000) {
			System.out.println("八折购买插排");
			return;
		}
		this.getNextHandler().buySocket(count);
	}
}

 新建测试类Test组装调用   

public class Test {

	public static void main(String[] args) {
		// 组装责任链
		OriginalPriceSocketHandler originalPriceSocket = new OriginalPriceSocketHandler();
		NineDiscountSocketHandler nineDiscountSocket = new NineDiscountSocketHandler();
		originalPriceSocket.setNextHandler(nineDiscountSocket);
		nineDiscountSocket.setNextHandler(new EightDiscountSocketHandler());

		originalPriceSocket.buySocket(50000);
	}
}

四、命令模式

        命令模式将请求以命令的形式包裹在对象中,并传给调用对象。调用对象寻找可以处理该命令的合适的对象,并把该命令传给相应的对象,由该对象处理请求。命令模式中包括抽象命令(Command)、具体命令(Concrete Command)、接收者(Receiver)、调用者(Invoker)四种角色。使用命令模式可降低系统耦合度,提高扩展性,但每增加一个命令需要新增具体命令类造成类膨胀。以聊天为例,代码如下:

定义操作枚举ChatTypeEnum

public enum ChatTypeEnum {

	GROUP_CHAT("群聊"), 
	PRIVATE_CHAT("私聊");
	
	private String name;

	ChatTypeEnum(String name) {
		this.name = name;
	}
}

新建抽象命令Command


/**
 * 抽象命令:定义执行命令方法
 * 
 * @author huaisf
 *
 */
public interface Command {

	void execute();
}

新建具体命令GroupChatCommand与PrivateChatCommand

/**
 * 具体命令:对定义的抽象命令实现
 * 
 * @author huaisf
 *
 */
public class GroupChatCommand implements Command {

	private ChatRecord chatRecord;

	public GroupChatCommand() {
		chatRecord = new ChatRecord();
	}

	@Override
	public void execute() {
		System.out.println("群聊消息发送给房间内所有人");
		chatRecord.save();
	}

}


public class PrivateChatCommand implements Command {

	private ChatRecord chatRecord;

	public PrivateChatCommand() {
		chatRecord = new ChatRecord();
	}

	@Override
	public void execute() {
		System.out.println("私聊记录发送到对应人");
		chatRecord.save();
	}

}

 新建接受者ChatRecord

/**
 * 接收者:对真正业务进行处理
 * 
 * @author huaisf
 *
 */
public class ChatRecord {

	public void save() {
		System.out.println("保存聊天记录成功");
	}
}

新建调用者CommandManager

/**
 * 调用者:调用具体命令进行处理
 * 
 * @author huaisf
 *
 */
public class CommandManager {

	public static HashMap map = new HashMap<>();

	static {
		map.put(ChatTypeEnum.GROUP_CHAT.name(), new GroupChatCommand());
		map.put(ChatTypeEnum.PRIVATE_CHAT.name(), new PrivateChatCommand());
	}

	public void saveRecord(ChatTypeEnum chatTypeEnum) {
		Command command = map.get(chatTypeEnum.name());
		command.execute();
	}
}

新建测试类Test

public class Test {

	public static void main(String[] args) {
		CommandManager commandManager = new CommandManager();

		// 群聊消息
		commandManager.saveRecord(ChatTypeEnum.GROUP_CHAT);

		// 私聊消息
		commandManager.saveRecord(ChatTypeEnum.PRIVATE_CHAT);
	}
}

五、迭代器模式

        迭代器模式提供一种方法顺序访问一个聚合对象中的各种元素,而又不暴露该对象的内部表示。在迭代器模式中存在抽象容器(Aggregate)、具体容器(ConcreteAggregate)、抽象迭代器(Iterator)、具体迭代器(ConcreteIterator)。使用迭代器模式可以以不同的方式遍历一个聚合对象,并将遍历算法进行封装。但增加新的聚合类需要新增对应迭代器,提高了系统复杂性。下面以数组及集合两种数据结构遍历为例:

新建抽象迭代器AbstractIterator

/**
 * 抽象迭代器:定义遍历元素所需要的方法
 * 
 * @author huaisf
 *
 */
public interface AbstractIterator {

	/**
	 * 获取下一个元素
	 * 
	 * @return
	 */
	Object next();

	/**
	 * 是否有下一个元素
	 * 
	 * @return
	 */
	boolean hashNext();
}

新建具体迭代器ArrayIterator与ListIterator

/**
 * 具体迭代器:对抽象迭代器定义的方法进行实现,本迭代器为数组迭代器
 * @author huaisf
 *
 */
public class ArrayIterator implements AbstractIterator {

	private int index = 0;
	private Object[] array;

	public ArrayIterator(Object[] array){
		this.array=array;
	}
	@Override
	public Object next() {
		if (index <= array.length) {
			return array[index-1];
		}
		return null;
	}

	@Override
	public boolean hashNext() {
		if (index >= array.length) {
			return false;
		}
		index+=1;
		return true;
	}

}


/**
 * 具体迭代器:对抽象迭代器定义的方法进行实现,本迭代器为集合迭代器
 * @author huaisf
 *
 */
public class ListIterator implements AbstractIterator {

	private int index = 0;
	private List list;

	
	public ListIterator(List list){
		this.list=list;
	}
	@Override
	public Object next() {
		if (index <= list.size()) {
			return list.get(index-1);
		}
		return null;
	}

	@Override
	public boolean hashNext() {
		if (index >= list.size()) {
			return false;
		}
		index+=1;
		return true;
	}

}

新建抽象容器AbstractContainer

/**
 * 抽象容器:定义容器所需方法
 * 
 * @author huaisf
 *
 */
public interface AbstractContainer {

	void add(Object object);

	void delete(int index);

	AbstractIterator iterator();
}

新建具体容器ArrayContainer与ListContainer

/**
 * 具体容器:抽象容器的实现,对数据进行存储,本容器为数组容器
 * 
 * @author huaisf
 *
 */
public class ArrayContainer implements AbstractContainer {
	
	private static Object[] array = new Object[0];
	
	private int size = 0;

	@Override
	public void add(Object object) {
		Object[] temp = new Object[size + 1];
		System.arraycopy(array, 0, temp, 0, size);
		temp[size] = object;
		array = temp;
		size += 1;
	}

	@Override
	public void delete(int index) {
		Object[] temp = new Object[size - 1];
		System.arraycopy(array, 0, temp, 0, index);
		System.arraycopy(array, index + 1, temp, index, size - index - 1);
		array = temp;
		size -= 1;
	}

	@Override
	public AbstractIterator iterator() {
		return new ArrayIterator(array);
	}

}


/**
 * 具体容器:抽象容器的实现,对数据进行存储,本容器为集合容器
 * 
 * @author huaisf
 *
 */
public class ListContainer implements AbstractContainer {
	
	List list = new ArrayList();

	@Override
	public void add(Object object) {
		list.add(object);
		
	}

	@Override
	public void delete(int index) {
		list.remove(index);
		
	}

	@Override
	public AbstractIterator iterator() {
		return new ListIterator(list);
	}

}

新建测试类Test

public class Test {

	public static void main(String[] args) {
		// 使用list迭代器
		ListContainer listContainer = new ListContainer();
		for (int i = 0; i < 5; i++) {
			listContainer.add(i);
		}
		AbstractIterator listIterator = listContainer.iterator();
		while (listIterator.hashNext()) {
			System.out.println(listIterator.next());
		}

		// 使用数组迭代器
		ArrayContainer arrayContainer = new ArrayContainer();
		for (int i = 5; i < 10; i++) {
			arrayContainer.add(i);
		}
		AbstractIterator arrayIterator = arrayContainer.iterator();
		while (arrayIterator.hashNext()) {
			System.out.println(arrayIterator.next());
		}
	}
}

六、中介者模式

        中介者模式是用一个中介对象来封装一系列的对象交互。中介者使各个对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。该模式包括抽象中介者(Mediator)、具体中介者(Concrete Mediator)、抽象同事类(Colleague)、具体同事类(Concrete Colleague)四种角色。以买卖房屋为例,代码如下

定义操作类型OperationTypeEnum,该类型与设计模式无关

public enum OperationTypeEnum {

	BUY("买房子"), SELL("卖房子");

	private String name;

	OperationTypeEnum(String name) {
		this.name = name;
	}
}

新建抽象中介者AbstractMediator

/**
 * 抽象中介者:定义处理同事信息操作,保存同事对象
 * 
 * @author huaisf
 *
 */
public abstract class AbstractMediator {

	BuyHouseUser buyHouseUser;

	SellHouseUser sellHouseUser;

	/**
	 * 转发消息
	 * 
	 * @param type
	 */
	public abstract void contact(OperationTypeEnum type);

	public BuyHouseUser getBuyHouseUser() {
		return buyHouseUser;
	}

	public void setBuyHouseUser(BuyHouseUser buyHouseUser) {
		this.buyHouseUser = buyHouseUser;
	}

	public SellHouseUser getSellHouseUser() {
		return sellHouseUser;
	}

	public void setSellHouseUser(SellHouseUser sellHouseUser) {
		this.sellHouseUser = sellHouseUser;
	}

}

新建抽象同事类AbstractUser

/**
 * 抽象同事类:定义同事操作接口,保存中介者对象。
 * 
 * @author huaisf
 *
 */
public abstract class AbstractUser {

	AbstractMediator abstractMediator;

	public AbstractUser(AbstractMediator abstractMediator) {
		this.abstractMediator = abstractMediator;
	}

	/**
	 * 发送消息
	 */
	abstract void send();

	/**
	 * 接收消息
	 */
	abstract void receive();

}

新建具体同事类BuyHouseUser与SellHouseUser

/**
 * 具体同事类:对抽象同事类定义方法实现,本类为购房者同事类
 * 
 * @author huaisf
 *
 */
public class BuyHouseUser extends AbstractUser {

	public BuyHouseUser(AbstractMediator abstractMediator) {
		super(abstractMediator);
	}

	@Override
	void send() {
		System.out.println("发送买房请求");
		super.abstractMediator.contact(OperationTypeEnum.BUY);
	}

	@Override
	void receive() {
		System.out.println("收到卖房响应");

	}

}


/**
 * 具体同事类:对抽象同事类定义方法实现,本类为售房者同事类
 * 
 * @author huaisf
 *
 */
public class SellHouseUser extends AbstractUser {

	public SellHouseUser(AbstractMediator abstractMediator) {
		super(abstractMediator);
	}

	@Override
	void send() {
		System.out.println("发送卖房响应");
		super.abstractMediator.contact(OperationTypeEnum.SELL);
	}

	@Override
	void receive() {
		System.out.println("收到买房请求");

	}
}

新建具体中介者HouseMediator

/**
 * 具体中介者:实现抽象中介者定义方法,对同事请求进行处理
 * 
 * @author huaisf
 *
 */
public class HouseMediator extends AbstractMediator {

	@Override
	public void contact(OperationTypeEnum type) {
		if (OperationTypeEnum.BUY == type) {
			super.sellHouseUser.receive();
		} else if (OperationTypeEnum.SELL == type) {
			super.buyHouseUser.receive();
		}

	}

}

新建测试类Test

public class Test {

	public static void main(String[] args) {
		AbstractMediator mediator = new HouseMediator();
		BuyHouseUser buyHouseUser = new BuyHouseUser(mediator);
		SellHouseUser sellHouseUser = new SellHouseUser(mediator);
		mediator.setBuyHouseUser(buyHouseUser);
		mediator.setSellHouseUser(sellHouseUser);
		buyHouseUser.send();
		sellHouseUser.send();
	}
}

七、备忘录模式

        备忘录模式指在不破坏封装性的前提下,获取到一个对象的内部状态,并在对象之外记录或保存这个状态。在有需要的时候可将该对象恢复到原先保存的状态。使用备忘录模式可以对操作对象提供回滚操作,但对资源消耗过大,每操作一次都需要记录操作前数据。备忘录模式中包括发起人(Originator)、备忘录(Memento)、负责人(Caretaker)三种角色。以文档回滚为例,代码如下:

新建备忘录Memento

/**
 * 备忘录:保存发起人数据,在需要时提供数据
 * 
 * @author huaisf
 *
 */
public class Memento {
	
	private String content;

	public String getContent() {
		return content;
	}

	public void setContent(String content) {
		this.content = content;
	}

}

新建发起人Originator

/**
 * 发起人:定义哪些属于备份数据,提供保存及恢复方法
 * 
 * @author huaisf
 *
 */
public class Originator {
	
	private String content;

	public Memento save() {
		Memento memento = new Memento();
		memento.setContent(content);
		return memento;
	}

	public void rollback(Memento memento) {
		this.content = memento.getContent();

	}

	public String getContent() {
		return content;
	}

	public void setContent(String content) {
		this.content = content;
	}

}

新建负责人Caretaker

/**
 * 负责人:对备忘录角色进行管理暂存、提供备忘录
 * 
 * @author huaisf
 *
 */
public class Caretaker {

	private Memento memento;

	public Memento getMemento() {
		return memento;
	}

	public void setMemento(Memento memento) {
		this.memento = memento;
	}

}

新建测试类Test

public class Test {

	public static void main(String[] args) {
		Caretaker caretaker = new Caretaker();
		Originator originator = new Originator();
		originator.setContent("文档1");

		System.out.println("第一次保存后文档内容:" + originator.getContent());

		caretaker.setMemento(originator.save());
		originator.setContent("文档2");

		System.out.println("第一次保存后文档内容:" + originator.getContent());

		originator.rollback(caretaker.getMemento());

		System.out.println("回滚后文档内容:" + originator.getContent());

	}
}

八、观察者模式

        观察者模式也称发布-订阅模式,该多个观察者同时监听某一个主题对象。当主题对象变化时,会通知所有的观察者对象,使观察者可以更新自身数据。使用观察者模式可以在观察者与主题对象中建立连接关系,构成抽象耦合。但并未完全解耦,并且观察者越多,主题通知观察者耗费时间越长。在观察者模式中包括抽象主题(Subject)、具体主题(Concrete Subject)、抽象观察者(Observer)、具体观察者(Concrete Observer)四种角色。

新建抽象观察者AbstractObserver

/**
 * 抽象观察者:定义主题通知时调用方法
 * @author huaisf
 *
 */
public interface AbstractObserver {

	/**
	 * 更新数据
	 */
	void update();
}

新建具体观察者ConcreteObserverA与ConcreteObserverB

/**
 * 具体观察者:实现抽象观察者定义的方法,当收到通知时进行自身业务处理
 * 
 * @author huaisf
 *
 */
public class ConcreteObserverA implements AbstractObserver {

	@Override
	public void update() {
		System.out.println("观察者A收到通知,更新数据");

	}

}


public class ConcreteObserverB implements AbstractObserver {

	@Override
	public void update() {
		System.out.println("观察者B收到通知,更新数据");

	}

}

新建抽象主题AbstractSubject

/**
 * 抽象主题:定义操作观察者方法
 * @author huaisf
 *
 */
public interface AbstractSubject {

	/**
	 * 添加观察者
	 * 
	 * @param abstractObserver
	 */
	void addObserver(AbstractObserver abstractObserver);

	/**
	 * 通知观察者
	 */
	void noticeObserver();
}

新建具体主题ConcreteSubject

/**
 * 具体主题:对抽象观察者定义进行实现
 * 
 * @author huaisf
 *
 */
public class ConcreteSubject implements AbstractSubject {
	List list = new ArrayList<>();

	@Override
	public void addObserver(AbstractObserver abstractObserver) {
		list.add(abstractObserver);

	}

	@Override
	public void noticeObserver() {

		for (AbstractObserver abstractObserver : list) {
			abstractObserver.update();
		}
	}

}

新建测试类Test

public class Test {

	public static void main(String[] args) {
		AbstractObserver observerA = new ConcreteObserverA();
		AbstractObserver observerB = new ConcreteObserverB();
		AbstractSubject subject = new ConcreteSubject();
		// 添加观察者
		subject.addObserver(observerA);
		subject.addObserver(observerB);
		// 对观察者进行通知
		subject.noticeObserver();
	}
}

九、状态模式

        状态模式定义为允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它的类。通俗来说当控制一个对象状态转换的条件表达式过于复杂时,可以使用状态模式将状态的判断逻辑转移到表示不同状态的一系列类中,将复杂的判断逻辑简化。使用状态模式可以将复杂逻辑简化到不同子类中,提高扩展性,但同样会造成类膨胀。在状态模式中存在上下文(Context)、抽象状态(State)、具体状态(ConcreteState)三种角色。以开关门状态转换为例,代码如下:

新建上下文Context

/**
 * 上下文:定义外部调用方法,存储当前状态
 * 
 * @author huaisf
 *
 */
public class Context {

	private DoorState doorState;

	public Context(DoorState doorState) {
		this.doorState = doorState;
	}

	public DoorState getDoorState() {
		return doorState;
	}

	public void setDoorState(DoorState doorState) {
		this.doorState = doorState;
	}

	public void switchOperation() {
		doorState.switchOperation(this);
	}
}

新建抽象状态DoorState

/**
 * 抽象状态:定义不同状态的操作
 * 
 * @author huaisf
 *
 */
public abstract class DoorState {

	/**
	 * 开关操作
	 */
	public abstract void switchOperation(Context context);

}

新建具体状态CloseDoorState与OpenDoorState

/**
 * 具体状态:对抽象状态进行实现,在需要时进行状态切换
 * 
 * @author huaisf
 *
 */
public class CloseDoorState extends DoorState {

	@Override
	public void switchOperation(Context context) {
		
		System.out.println("关门");
		
		// 设置下一次状态为开门
		context.setDoorState(new OpenDoorState());

	}

}


public class OpenDoorState extends DoorState {

	@Override
	public void switchOperation(Context context) {
		
		System.out.println("开门");
		
		// 设置下一次状态为关门
		context.setDoorState(new CloseDoorState());

	}

}

新建测试类Test

public class Test {

	public static void main(String[] args) {
		Context context = new Context(new OpenDoorState());
		context.switchOperation();
		context.switchOperation();
		context.switchOperation();
		context.switchOperation();
	}
}

十、策略模式

      策略模式定义一系列的算法,把每一个算法封装起来, 并且使它们可相互替换,策略模式使得算法可独立于使用它的客户而变化。使用策略模式可自由切换算法,避免多重条件判断,提升扩展性。但每个策略对应一个类,复用性低。在策略模式中存在上下文(Context)、抽象策略角色(Strategy)、具体策略角色(ConcreteStrategy)三种角色。以打折促销为例,代码如下:

新建抽象策略DiscountStrategy

/**
 * 抽象策略:定义策略
 * 
 * @author huaisf
 *
 */
public interface DiscountStrategy {

	void buy();
}

新建具体策略OriginalPriceStrategy与EightDiscountStrategy

/**
 * 具体策略:对抽象策略进行实现
 * 
 * @author huaisf
 *
 */
public class OriginalPriceStrategy implements DiscountStrategy {

	@Override
	public void buy() {
		System.out.println("原价购买");
	}

}


public class EightDiscountStrategy implements DiscountStrategy {

	@Override
	public void buy() {
		System.out.println("八折购买");
	}

}

 新建上下文Context

/**
 * 上下文:定义外部调用方法
 * 
 * @author huaisf
 *
 */
public class Context {
	private DiscountStrategy discountStrategy;

	public Context(DiscountStrategy discountStrategy) {
		this.discountStrategy = discountStrategy;

	}

	public void buy() {
		discountStrategy.buy();
	}
}

新建测试类Test

public class Test {

	public static void main(String[] args) {
		// 没有促销互动,原价购买商品
		Context originalContext = new Context(new OriginalPriceStrategy());
		originalContext.buy();

		// 厂家促销,商品八折
		Context eightContext = new Context(new EightDiscountStrategy());
		eightContext.buy();

	}
}

十一、访问者模式

        访问者模式指封装一些作用于某种数据结构中的各元素的操作,它可以在不改变这个数据结构的前提下定义作用于这些元素的新的操作。该模式中存在抽象访问者(Visitor)、具体访问者(ConcreteVisitor)、抽象元素(Element)、具体元素(ConcreteElement)、对象结构(Object Structure)五种角色。当对象结构比较稳定且对一个对象结构中的对象进行很多不同的且不相关的操作时可使用访问者模式。使用该模式后想增加对象操作只需增加具体访问者即可。以查账为例,账本结构固定,税务局查询到的是假账,公司内会计查到的是真账。代码如下:

新建抽象元素AccountBook

/**
 * 抽象元素:定义账本接受操作
 * 
 * @author huaisf
 *
 */
public interface AccountBook {

	/**
	 * 接受数据
	 * @param viewer
	 */
	void accept(Viewer viewer);
}

新建具体元素IncomeAccountBook与SpendingAccountBook

/**
 * 具体元素:实现账本收入操作
 * 
 * @author huaisf
 *
 */
public class IncomeAccountBook implements AccountBook {

	private int amount = 100000;

	@Override
	public void accept(Viewer viewer) {
		viewer.view(this);

	}

	public int getAmount() {
		return amount;
	}

	public void setAmount(int amount) {
		this.amount = amount;
	}

}

/**
 * 具体元素:实现账本支出操作
 * 
 * @author huaisf
 *
 */
public class SpendingAccountBook implements AccountBook {

	private int amount = 100000;

	@Override
	public void accept(Viewer viewer) {
		viewer.view(this);

	}

	public int getAmount() {
		return amount;
	}

	public void setAmount(int amount) {
		this.amount = amount;
	}

}

 新建抽象访问者Viewer

/**
 * 抽象访问者:定义每个具体元素访问方法
 * 
 * @author huaisf
 *
 */
public interface Viewer {

	/**
	 * 查看收入账单
	 * 
	 * @param incomeAccountBook
	 */
	void view(IncomeAccountBook incomeAccountBook);

	/**
	 * 查看支出账单
	 * 
	 * @param spendingAccountBook
	 */
	void view(SpendingAccountBook spendingAccountBook);
}

新建具体访问者AccountingViewer与RevenueViewer

/**
 * 具体访问者:对抽象访问者方法进行实现,会计查到的是真账
 * 
 * @author huaisf
 *
 */
public class AccountingViewer implements Viewer {

	@Override
	public void view(IncomeAccountBook incomeAccountBook) {
		System.out.println("财务人员查看收入:" + incomeAccountBook.getAmount());

	}

	@Override
	public void view(SpendingAccountBook spendingAccountBook) {
		System.out.println("财务人员查看支出:" + spendingAccountBook.getAmount());

	}
}


/**
 * 具体访问者:对抽象访问者方法进行实现,税务局查到的是假账
 * 
 * @author huaisf
 *
 */
public class RevenueViewer implements Viewer {

	@Override
	public void view(IncomeAccountBook incomeAccountBook) {
		System.out.println("税务局查看收入:" + incomeAccountBook.getAmount() / 10);

	}

	@Override
	public void view(SpendingAccountBook spendingAccountBook) {
		System.out.println("税务局查看支出:" + spendingAccountBook.getAmount() * 10);

	}

}

新建对象结构AccountBookStructure

/**
 * 对象结构:存储元素并提供遍历所有元素的方法供外部调用
 * 
 * @author huaisf
 *
 */
public class AccountBookStructure {
	
	private List accountBooks = new ArrayList();

	public void add(AccountBook accountBook) {
		accountBooks.add(accountBook);
	}

	public void show(Viewer viewer) {
		for (AccountBook accountBook : accountBooks) {
			accountBook.accept(viewer);
		}
	}
}

新建测试类Test

public class Test {

	public static void main(String[] args) {
		AccountBookStructure accountBookStructure = new AccountBookStructure();
		accountBookStructure.add(new IncomeAccountBook());
		accountBookStructure.add(new SpendingAccountBook());
		
		// 税务局查账
		accountBookStructure.show(new RevenueViewer());
		
		// 会计查账
		accountBookStructure.show(new AccountingViewer());
	}
}

你可能感兴趣的:(设计模式,设计模式)