23种设计模式之十一种行为型模式从概念介绍再到案例分析,不懂就从例子去感受

三、行为型模式(Behavioral Pattern)

策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。

1.观察者模式

符合开闭原则(ocp)

对象之间多对一依赖的设计方案,被依赖的对象为Subject类似于气象台监测天气变化,依赖的对象为Observer观察者类似于百度去达拿到数据展示,Subject通知Observer变化,这是一个一对多的关系。或者微信公众号订阅等。

//接口,让WeatherData来实现
public interface Subject {
	public void registerObserver(Observer o);
	public void removeObserver(Observer o);
	public void notifyObserver();
}
//观察者接口,由观察者来实现
public interface Observer {
	public void update(float temperature,float pressure,float humidity);
}
//一个观察者
public class CurrentConditions implements Observer{
	
	//温度、气压、湿度
	private float temperature;
	private float pressure;
	private float humidity;
	
	//更新天气情况,是由WeatherData来调用,我使用推送方式
	public void update(float temperature,float pressure,float humidity) {
		this.temperature = temperature;
		this.pressure = pressure;
		this.humidity = humidity;
		display();
	}
	//显示
	public void display() {
		System.out.println("***Today mTemperature: "+temperature+"***");
		System.out.println("***Today mPressure: "+pressure+"***");
		System.out.println("***Today mhumidity: "+humidity+"***");
	}
}
//另一个观察者,百度网站
public class BaiduSit implements Observer{
	//温度、气压、湿度
	private float temperature;
	private float pressure;
	private float humidity;
	//更新天气情况,是由WeatherData来调用,我使用推送方式
	public void update(float temperature,float pressure,float humidity) {
		this.temperature = temperature;
		this.pressure = pressure;
		this.humidity = humidity;
		display();
	}
	//显示
	public void display() {
		System.out.println("***百度天气 mTemperature: "+temperature+"***");
		System.out.println("***百度天气 mPressure: "+pressure+"***");
		System.out.println("***百度天气 mhumidity: "+humidity+"***");
	}
}
/**
 * 类是核心
 * 1.包含最新的天气情况信息
 * 2.含有观察者集合,使用ArrayList管理
 * 3.当数据有更新时,就主动的调用ArrayList,通知所有的接入方,就看到了最新的信息
 * */
public class WeatherData implements Subject{
	//温度、气压、湿度
	private float temperature;
	private float pressure;
	private float humidity;
	//观察者集合
	private ArrayList<Observer> observers;
	
	//加入新的第三方
	public WeatherData() {
		observers = new ArrayList<Observer>();
	}
	//当数据有更新时,就调用setData
	public void setData(float temperature,float pressure,float humidity) {
		this.temperature = temperature;
		this.pressure = pressure;
		this.humidity = humidity;
		//调用notifyObserver,将最新的信息,推送给观察者们
		notifyObserver();
	}
	@Override
	public void registerObserver(Observer o) {
		//注册一个观察者
		observers.add(o);
	}
	@Override
	public void removeObserver(Observer o) {
		//移除一个观察者
		if(observers.contains(o)) {
			observers.remove(o);
		}
	}
	@Override
	public void notifyObserver() {
		//遍历观察者更新天气
		for(int i=0;i<observers.size();i++) {
			observers.get(i).update(this.temperature, this.pressure, this.humidity);
		}		
	}	
}
public class Client {

	public static void main(String[] args) {
		//创建一个WeatherData
		WeatherData weatherData = new WeatherData();
		//创建观察者
		CurrentConditions cc = new CurrentConditions();
		BaiduSit bs = new BaiduSit();
		//注册到WeatherData
		weatherData.registerObserver(cc);
		weatherData.registerObserver(bs);
		//测试
		System.out.println("通知各个注册的观察者,看看信息");
		weatherData.setData(10f, 100f, 30.3f);
	}
}

应用场景:

  • 一个抽象模型有两个方面,其中一个方面依赖于另一个方面。将这些方面封装在独立的对象中使它们可以各自独立地改变和复用。
  • 一个对象的改变将导致其他一个或多个对象也发生改变,而不知道具体有多少对象将发生改变,可以降低对象之间的耦合度。
  • 一个对象必须通知其他对象,而并不知道这些对象是谁。
  • 需要在系统中创建一个触发链,A对象的行为将影响B对象,B对象的行为将影响C对象……,可以使用观察者模式创建一种链式触发机制。
2.模板方法模式

该模式又叫模板模式,在一个抽象类公开定义了执行它的方法的模板,他的子类可以按照需求重写方法实现,但调用将以抽象类中定义的方法进行。

//这是一个抽象豆浆类
public abstract class SoyaMilk {

	//模板方法,make,模板方法可以做成final,子类不能够覆盖
	public void make() {
		select();
		add();
		soak();
		beat(); 
	}
	
	//选材料
	public void select() {
		System.out.println("第一步:挑选上好的黄豆");
	}
	
	//添加不同的配料,抽象方法,子类具体实现
	public abstract void add();
	
	//浸泡
	public void soak() {
		System.out.println("第三步:黄豆和配料开始浸泡,需要3小时");
	}
	
	//打碎
	public void beat() {
		System.out.println("第四步:进行打碎");
	}
}
//加入红豆原材料
public class RedBeanSoyaMilk extends SoyaMilk{
	@Override
	public void add() {
		System.out.println("加入上好的红豆");
	}
}
//加入花生原材料
public class PeanutSoyaMilk extends SoyaMilk{
	@Override
	public void add() {
		System.out.println("加入上好的花生");
	}
}
public class Client {
	//进行测试
	public static void main(String[] args) {
		System.out.println("--------制作红豆豆浆---------");
		SoyaMilk redBeanSoyaMilk = new RedBeanSoyaMilk();
		redBeanSoyaMilk.make();
		System.out.println("--------制作花生豆浆---------");
		SoyaMilk peanutSoyaMilk = new PeanutSoyaMilk();
		peanutSoyaMilk.make();
	}
}

钩子方法

在模板模式中,我们可以定义一个方法,它默认不干任何事,子类可以视情况要不要去覆盖他,该方法称为“钩子”。

//在SoyaMilk中进行修改
//模板方法,make,模板方法可以做成final,子类不能够覆盖
public void make() {
    select();
    if(addCondition()) {
    	add();
    }
    soak();
    beat(); 
}
//钩子方法,决定是否添加配料
public boolean addCondition() {
	return true;
}
//钩子方法,纯豆浆
public class PureSoyaMilk extends SoyaMilk{

	@Override
	public void add() {
		//空实现,啥也不写
	}
	@Override
	public boolean addCondition() {
		return false;
	}
}
public class Client {
	public static void main(String[] args) {
		System.out.println("--------制作红豆豆浆---------");
		SoyaMilk redBeanSoyaMilk = new RedBeanSoyaMilk();
		redBeanSoyaMilk.make();
		System.out.println("--------制作花生豆浆---------");
		SoyaMilk peanutSoyaMilk = new PeanutSoyaMilk();
		peanutSoyaMilk.make();
		System.out.println("--------制作纯的豆浆---------");
		SoyaMilk pureSoyaMilk = new PureSoyaMilk();
		pureSoyaMilk.make();
	}
}
3.命令模式

在软件设计中,我们经常需要向某些对象发送请求,但是并不知道请求的接收者是谁,也不知道被请求的操作是哪一个,我们只需要在程序运行时指定具体的请求接收者即可,此时,可以使用命令模式来进行设计。命令模式使得请求发送者与请求接收者消除彼此之间的耦合。

在命令模式中,会将一个请求封装为一个对象,以便使用不同参数来表示不同的请求,同时它也支持撤销操作。

//创建命令接口
public interface Command {

	//执行动作
	public void execute();
	//撤销动作
	public void undo();
}
public class LightReceive {
	
	public void on() {
		System.out.println("点灯打开了 ");
	}
	public void off() {
		System.out.println("电灯关闭了 ");
	}
}
public class LightOnCommand implements Command{

	LightReceive light;
	//构造器
	public LightOnCommand(LightReceive light) {
		super();
		this.light = light;
	}
	@Override
	public void execute() {
		//调用 接收者方法
		light.on();
	}

	@Override
	public void undo() {
		//调用 接收者方法
		light.off();
	}
}
public class LightOffCommand implements Command{

	//聚合LightReceive
	LightReceive light;
	//构造器
	public LightOffCommand(LightReceive light) {
		super();
		this.light = light;
	}
	@Override
	public void execute() {
		//调用 接收者方法
		light.off();
	}

	@Override
	public void undo() {
		//调用 接收者方法
		light.on();
	}
}
//没有任何命令,即空执行:用于初始化每一个按钮,当调用空命令是啥也不干
//其实这也是一种设计模式,可以省掉对空的判断
public class NoCommand implements Command{

	@Override
	public void execute() {
	}

	@Override
	public void undo() {
	}
}
//这是一个遥控器
public class RemoteController {
	//开 按钮的命令数组
	Command[] onCommands;
	Command[] offCommands;
	
	//执行撤销的命令
	Command undoCommand;
	
	//构造器,完成对按钮的初始化
	public RemoteController() {
		onCommands = new Command[5];
		offCommands = new Command[5];
		
		for(int i=0;i<5;i++) {
			onCommands[i] = new NoCommand();
			offCommands[i] = new NoCommand();
		}
	}
	
	//给我们的按钮设置你需要的命令
	public void setCommand(int no,Command onCommand,Command offCommand) {
		onCommands[no] = onCommand;
		offCommands[no] = offCommand;
	}
	//按下开按钮
	public void onButtonWasPushed(int no) {
		//找到你按下的开的按钮,并调用对应的方法
		onCommands[no].execute();
		//记录这次操作,用于撤销
		undoCommand = onCommands[no];
	}
	//按下关按钮
	public void offButtonWasPushed(int no) {
		//找到你按下的开的按钮,并调用对应的方法
		offCommands[no].execute();
		//记录这次操作,用于撤销
		undoCommand = offCommands[no];
	}
	//按撤销按钮
	public void undoButtonWasPushed(int no) {
		//找到你按下的开的按钮,并调用对应的方法
		undoCommand.undo();
	}
}
public class Client {

	public static void main(String[] args) {
		//使用命令模式,完成通过遥控器,对电灯操作
		
		//创建电灯的对象(接收者)
		LightReceive lightReceive = new LightReceive();
		
		//创建电灯相关的开关命令
		LightOnCommand lightOnCommand = new LightOnCommand(lightReceive);
		LightOffCommand lightOffCommand = new LightOffCommand(lightReceive);
		
		//需要一个遥控器
		RemoteController remoteController = new RemoteController();
		
		//给我们的遥控器设置命令,比如no=0是电灯开关的按钮
		remoteController.setCommand(0, lightOnCommand, lightOffCommand);
		
		System.out.println("----------------按下灯的开按钮-------------------");
		remoteController.onButtonWasPushed(0);
		System.out.println("----------------按下灯的关按钮-------------------");
		remoteController.offButtonWasPushed(0);
		System.out.println("----------------按下灯撤销按钮-------------------");
		remoteController.undoButtonWasPushed(0);
	}
}
4.访问者模式

基本工作原理:在被访问的类里面加一个对外提供接待访问者的接口。主要是将数据结构与数据操作分离,解决数据结构和数据耦合性问题。

应用场景:需要对一个对象就够中的对象进行很多不同操作,这些操作彼此没有关联,同时需要比卖你让这些操作“污染”这些对象的类,可以选用访问者模式解决。
举例:将人分为男人和女人,对歌手进行测评,当看完某歌手表演后,得到他们对该歌手不同的评价(评价有不同的种类,比如 成功、失败等)

public abstract class Action {

	//得到男性的测评结果
	public abstract void getManResult(Man man); 
	//得到女性的测评结果
	public abstract void getWomanResult(Woman woman); 
}
public class Success extends Action{

	@Override
	public void getManResult(Man man) {
		System.out.println("男人给的该歌手的评价是成功!");
	}

	@Override
	public void getWomanResult(Woman woman) {
		System.out.println("女人给的该歌手的评价是成功!");
	}
}
public class Fail extends Action{

	@Override
	public void getManResult(Man man) {
		System.out.println("男人给的该歌手的评价是失败!");
	}

	@Override
	public void getWomanResult(Woman woman) {
		System.out.println("女人给的该歌手的评价是失败!");
	}
}
public abstract class Person {

	//提供一个方法,让访问者可以访问
	public abstract void accept(Action action);
}
//说明:1.我们使用双分派,及首先客户端程序,将具体的状态作为参数传递man中(第一次分派)
//   2.然后man类作为参数的具体方法中方法getManResult,同时将自己(this)作为参数传入,这是第二次分派
public class Man extends Person{

	@Override
	public void accept(Action action) {
		action.getManResult(this);
	}
}
public class Woman extends Person{

	@Override
	public void accept(Action action) {
		action.getWomanResult(this);
	}
}
//数据结构,管理了很多人 (Man,Woman)
public class ObjectStructure {

	//维护里一个集合
	private List<Person> persons = new LinkedList();
	
	//增加list
	public void attach(Person p) {
		persons.add(p);
	}
	//删除
	public void detach(Person p) {
		persons.remove(p);
	}
	//显示测评结果
	public void display(Action action) {
		for(Person p : persons) {
			p.accept(action);
		}
	}
}
public class Client {

	public static void main(String[] args) {
		//创建ObjectStructure
		ObjectStructure objectStructure = new ObjectStructure();
		
		objectStructure.attach(new Man());
		objectStructure.attach(new Woman());
		
		//成功
		Success success = new Success();
		objectStructure.display(success);
		
		//失败
		Fail fail = new Fail();
		objectStructure.display(fail);
	}
}

双分派:不管类怎么变化,我们都能够找到期望的方法运行,双分派意味着得到执行的操作取决于请求的种类和两个接收者的类型。这个action是一个不变的,利于扩展。

5.迭代器模式

迭代器模式(Iterator Pattern),提供提供一种遍历集合元素的统一接口,用一致的方法遍历集合元素,不需要知道集合对象的底层表示,即不暴露其内部结构。

案列:还是举例计算机学院与信息工程学院有不同的专业,但重点是专业的遍历,假设计算机学院专业放在数组里,而信息工程学院专业放在集合里,封装一个接口去实现遍历。

迭代器模式角色分析:

  1. Iterator:迭代器接口,是系统提供,含有hasNext(),next(),remove()
  2. ConcreteIterator: 具体的迭代器类,管理迭代
  3. Aggregate:一个统一的聚合接口,将将客户端和具体聚合解耦
  4. CincreteAggreage: 具体的聚合持有对象集合,并提供一个方法,返回一个迭代器,该迭代器可以正确遍历集合
  5. Client: 客户端,通过Iterator和Aggregate依赖子类
public class Department {

	private String name;
	private String desc;
	public Department(String name,String desc) {
		super();
		this.name = name;
		this.desc = desc;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getDesc() {
		return desc;
	}
	public void setDesc(String desc) {
		this.desc = desc;
	}
}
public class ComputerCollegeIterator implements Iterator{

	//这里我们需要Department 是以怎样的方式存放
	Department[] departments;
	int position = 0;	//遍历位置
	
 	public ComputerCollegeIterator(Department[] departments) {
		this.departments = departments;
	}
 	//判断是否还有下一个元素
	@Override
	public boolean hasNext() {
		if(position >= departments.length || departments[position] == null) {
			return false;
		}else {
			return true;
		}
	}
	@Override
	public Object next() {
		Department department = departments[position];
		position += 1;
		return department;
	}
	//删除方法,默认空实现
	public void remove() {
	}
}
public class InfoCollageIterator implements Iterator{

	List<Department> departmentList; //信息工程学院是以List方式存放系
	int index = -1;//索引
	
	public InfoCollageIterator(List<Department> departmentList) {
		this.departmentList = departmentList;
	}
	//判断list中还有没有下一个元素
	public boolean hasNext() {
		if(index >= departmentList.size()-1) {
			return false;
		}else {
			index += 1;
			return true;
		}
	}
	@Override
	public Object next() {
		return departmentList.get(index);
	}
	//空实现remove方法
	public void remove() {}
}

public interface College {

	//获得学院的名称
	public String getName();
	//增加系的方法
	public void addDepartment(String name,String desc);
	//返回一个迭代器,遍历
	public Iterator createTterator();
}
public class ComputerCollege implements College{

	Department[] departments;
	int numofDepartment = 0; //保存当前数组的对象个数
	
	public ComputerCollege() {
		departments = new Department[5];
		addDepartment("Java专业", "Java专业");
		addDepartment("PHP专业", "PHP专业");
		addDepartment("大数据专业", "大数据专业");
	}
	@Override
	public String getName() {
		return "计算机学院";
	}
	@Override
	public void addDepartment(String name, String desc) {
		Department department = new Department(name,desc);
		departments[numofDepartment] = department;
		numofDepartment += 1;
	}
	@Override
	public Iterator createTterator() {
		return new ComputerCollegeIterator(departments);
	}
}
public class InfoCollage implements College{

	List<Department> departmentList;
	
	public InfoCollage() {
		departmentList = new ArrayList<Department>();
		addDepartment("信息安全专业", "信息安全专业");
		addDepartment("网络安全专业", "网络安全专业");
		addDepartment("服务器安全专业", "服务器安全专业");
	}

	@Override
	public String getName() {
		return "信息工程学院";
	}

	@Override
	public void addDepartment(String name, String desc) {
		Department department = new Department(name,desc);
		departmentList.add(department);
	}

	@Override
	public Iterator createTterator() {
		return new InfoCollageIterator(departmentList);
	}
}
public class OutPutImpl {

	//学院集合
	List<College> collegeList;
	
	public OutPutImpl(List<College> collegeList) {
		this.collegeList = collegeList;
	}
	//遍历所有学院,然后调用printDepartment 输出个学院的系
	public void printCollege() {
		//从collegeList 取出所有学院, Java 中的List 已经实现Iterator
		Iterator<College> iterator = collegeList.iterator();
		while(iterator.hasNext()) {
			//取出一个学院
			College college = iterator.next();
			System.out.println("==="+college.getName()+"===");
			printDepartment(college.createTterator());  //得到对应的迭代器
		}
	}
	//输出学院的系
	public void printDepartment(Iterator iterator) {
		while(iterator.hasNext()) {
			Department d = (Department)iterator.next();
			System.out.println(d.getName());
		}
	}
}
public class Client {

	public static void main(String[] args) {
		//创建学院
		List<College> collegeList = new ArrayList<College>();
		
		ComputerCollege computerCollege = new ComputerCollege();
		InfoCollage infoCollage = new InfoCollage();
		
		collegeList.add(computerCollege);
		collegeList.add(infoCollage);
		
		OutPutImpl outPutImpl = new OutPutImpl(collegeList);
		outPutImpl.printCollege();
	}
}
6.中介者模式

中介者模式(Mediator Pattern),用一个中介对象来封装一系列的对象交互,中介者使各个对象不再需要显式地相互引用,从而使其耦合松散,而且可以独立地改变他们之间的友谊。

  1. Mediator就是抽象中介者,定义了同事对象到中介对象的接口
  2. Colleague是抽象同事类
  3. Concretemediator具体的中介者对象,实现抽象方法,他需要知道所有具体的同时类,即以一个集合管理HashMap,并接受某同事对象消息,完成相应任务。
  4. ConcreteColleague具体的同事类,会有很多,每个同事只知道自己的行为,而不了解其他同事类的行为(方法),但是他们都依赖中介者对象。

案例:智能家庭包含设备有闹钟、咖啡机、电视机、窗帘等。主人看电视时各个设备协同工作。

流程:闹铃响起->咖啡机开始做咖啡->窗帘自动落下->电视机开始播放

中介者模式-智能家庭的操作流程

  1. 创建ConcreteMediator对象
  2. 创建各个同事类对象,比如:Alarm、CoffeeMachine、TV..
  3. 在创建同事类对象那个的时候,就直接同构构造器,加入到colleagueMap
  4. 同事类对象,可以调用sendMessage,最终会去调用ConcreteMediator的getMessage()方法
  5. getMessage()会根据接收的同事对象发出的消息来协调调用其他同事对象,完成任务
  6. 可以看到getMessage()是核心方法,完成相应任务
//这个代码当时没有自己运行就是看了看
namespace Mediator_Pattern
{
    class MediatorPattern
    {
    }
    /// 抽象中介者
    public abstract class Mediator
    {
        /// 定义与同事间的交互通信 
        public abstract void Common(string type);
    }

    /// 抽象同事类
    public abstract class Colleague
    {
        /// 处理自己的事务(房东展示自己的房屋)
        public abstract void Handle();

    }
    /// 房屋中介
    public class HouseMediator : Mediator
    {
        /// 中介有所有房东的房屋信息
        private SmallHouseColleague SmallHouse;
        private TwoHouseColleague TwoHouse;
        private ThreeHouseColleague ThreeHouse;

        public void SetSmallHouse(SmallHouseColleague small) 
        {
            SmallHouse = small;
        }

        public void SetTwoHouse(TwoHouseColleague two)
        {
            TwoHouse = two;
        }
        public void SetThreeHouse(ThreeHouseColleague three)
        {
            ThreeHouse = three;
        }

        /// <param name="colleague"></param>
        public override void Common(string  type)
        { 
            switch (type)
            {
                case "单间":
                    SmallHouse.Handle();
                    Console.WriteLine("如果可以就可以租房了!");
                    break;
                case "两居室":
                    TwoHouse.Handle();
                    Console.WriteLine("如果可以就可以租房了!");
                    break;
                case "三居室":
                    ThreeHouse.Handle();
                    Console.WriteLine("如果可以就可以租房了!");
                    break;
                default: 
                    Console.WriteLine($"{type}暂时没有房源!");
                    break;
            }
        }
    }
    /// 房东(小房间)
    public class SmallHouseColleague : Colleague
    {
        /// 展示单间
        public override void Handle()
        {
            Console.WriteLine( "单间——便宜整洁");
        }
    }

    /// 房东(两居室)
    public class TwoHouseColleague : Colleague
    { 
        /// 展示两居室
        public override void Handle()
        {
            Console.WriteLine("两居室——合适,靠谱");
        }
    }

    /// 房东(三居室)
    public class ThreeHouseColleague : Colleague
    { 

        /// 展示三居室
        public override void Handle()
        {
            Console.WriteLine("三居室——大气,宽松");
        }
    }
}
namespace Mediator_Pattern
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("一个租客看房:");
            ///初始化中介
            HouseMediator mediator = new HouseMediator();

            ///初始化房屋信息
            SmallHouseColleague smallHouseColleague = new SmallHouseColleague( );
            TwoHouseColleague twoHouseColleague = new TwoHouseColleague( );
            ThreeHouseColleague threeHouseColleague = new ThreeHouseColleague( );

            ///中介获取房屋信息
            mediator.SetSmallHouse(smallHouseColleague);
            mediator.SetTwoHouse(twoHouseColleague);
            mediator.SetThreeHouse(threeHouseColleague); 

            ///租户A需要两居室、提供看房
            mediator.Common("两居室");

            //租户B需要四居室、暂无房源
            mediator.Common("四居室");

        }
    }
}
7.备忘录模式

备忘录模式(Memento Pattern):是在不破坏封装的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,这样可以在以后将对象恢复到原先保存的状态。

案例: 1、后悔药。 2、打游戏时的存档3、Windows 里的 ctri + z。 4、数据库的事务管理。

public class Memento {

	//攻击力
	private int vit;
	//防御力
	private int def;
	public Memento(int vit, int def) {
		super();
		this.vit = vit;
		this.def = def;
	}
	public int getVit() {
		return vit;
	}
	public void setVit(int vit) {
		this.vit = vit;
	}
	public int getDef() {
		return def;
	}
	public void setDef(int def) {
		this.def = def;
	}
}
//守护者对象,保存游戏角色对象
public class Caretaker {

	//如果只保存一次状态
	private Memento memento;
	//对GameRole保存多次状态
//	private ArrayList<Memento> mements;
//	//对多个游戏保存多个状态
//	private HashMap<String, ArrayList<Memento>> rolesMemento;

	public Memento getMemento() {
		return memento;
	}

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

	private int vit;
	private int def;
	
	//创建Memento,即根据当前的状态得到Memento
	public Memento createMemento() {
		return new Memento(vit, def);
	}
	
	//从备忘录对象恢复GameRole的状态
	public void recoverGameRoleFromMemento(Memento memento) {
		this.vit = memento.getVit();
		this.def = memento.getDef();
	}
	
	//显示当前游戏角色的状态
	public void display() {
		System.out.println("游戏角色当前的攻击力:"+this.vit+"防御力: "+this.def);
	}

	public int getVit() {
		return vit;
	}

	public void setVit(int vit) {
		this.vit = vit;
	}

	public int getDef() {
		return def;
	}

	public void setDef(int def) {
		this.def = def;
	}
}
public class Client {
	public static void main(String[] args) {
		
		//创建游戏角色
		GameRole gameRole = new GameRole();
		gameRole.setVit(100);
		gameRole.setDef(100);
		System.out.println("和BOSS大战前的状态");
		gameRole.display();
		
		//把当前状态保存caretaker
		Caretaker caretaker = new Caretaker();
		caretaker.setMemento(gameRole.createMemento());
		
		System.out.println("和BOSS大战");
		gameRole.setVit(30);
		gameRole.setDef(30);
		gameRole.display();
		
		System.out.println("大战后,使用备忘录对象进行恢复");
		gameRole.recoverGameRoleFromMemento(caretaker.getMemento());
		System.out.println("恢复后状态");
		gameRole.display();
	}
}
8.解释器模式

​ 解释器模式(Interpreter Pattern)提供了评估语言的语法或表达式的方式,它属于行为型模式。这种模式实现了一个表达式接口,该接口解释一个特定的上下文。这种模式被用在 SQL 解析、符号处理引擎等。

应用实例:编译器、运算表达式计算。

何时使用:如果一种特定类型的问题发生的频率足够高,那么可能就值得将该问题的各个实例表述为一个简单语言中的句子。这样就可以构建一个解释器,该解释器通过解释这些句子来解决该问题。

将创建一个接口 Expression 和实现了 Expression 接口的实体类。定义作为上下文中主要解释器的 TerminalExpression 类。
其他的类 OrExpression、AndExpression 用于创建组合式表达式。
InterpreterPatternDemo,我们的演示类使用 Expression 类创建规则和演示表达式的解析。

//创建一个表达式接口
public interface Expression {
   public boolean interpret(String context);
}
//创建实现了上述接口的实体类
public class TerminalExpression implements Expression {
   
   private String data;
 
   public TerminalExpression(String data){
      this.data = data; 
   }
 
   @Override
   public boolean interpret(String context) {
      if(context.contains(data)){
         return true;
      }
      return false;
   }
}
public class OrExpression implements Expression {
    
   private Expression expr1 = null;
   private Expression expr2 = null;
 
   public OrExpression(Expression expr1, Expression expr2) { 
      this.expr1 = expr1;
      this.expr2 = expr2;
   }
 
   @Override
   public boolean interpret(String context) {      
      return expr1.interpret(context) || expr2.interpret(context);
   }
}
public class AndExpression implements Expression {
    
   private Expression expr1 = null;
   private Expression expr2 = null;
 
   public AndExpression(Expression expr1, Expression expr2) { 
      this.expr1 = expr1;
      this.expr2 = expr2;
   }
 
   @Override
   public boolean interpret(String context) {      
      return expr1.interpret(context) && expr2.interpret(context);
   }
}
//InterpreterPatternDemo 使用 Expression 类来创建规则,并解析它们。
public class InterpreterPatternDemo {
 
   //规则:Robert 和 John 是男性
   public static Expression getMaleExpression(){
      Expression robert = new TerminalExpression("Robert");
      Expression john = new TerminalExpression("John");
      return new OrExpression(robert, john);    
   }
 
   //规则:Julie 是一个已婚的女性
   public static Expression getMarriedWomanExpression(){
      Expression julie = new TerminalExpression("Julie");
      Expression married = new TerminalExpression("Married");
      return new AndExpression(julie, married);    
   }
 
   public static void main(String[] args) {
      Expression isMale = getMaleExpression();
      Expression isMarriedWoman = getMarriedWomanExpression();
 
      System.out.println("John is male? " + isMale.interpret("John"));
      System.out.println("Julie is a married women? " 
      + isMarriedWoman.interpret("Married Julie"));
   }
}
执行程序,输出结果:
John is male? true
Julie is a married women? true
9.状态模式

状态模式(State Pattern):他主要用来解决对象在多种状态转换时,需要对外输出不同的行为的问题 。状态和行为是一一对应的,状态之间可以相互转换,不同的状态对应于不同的场景。

应用实例: 1、打篮球的时候运动员可以有正常状态、不正常状态和超常状态。

使用场景:1、行为随状态改变而改变的场景。 2、条件、分支语句的代替者。

//创建一个接口。
public interface State {
   public void doAction(Context context);
}
//创建实现接口的实体类。
public class StartState implements State {
 
   public void doAction(Context context) {
      System.out.println("Player is in start state");
      context.setState(this); 
   }
 
   public String toString(){
      return "Start State";
   }
}
public class StopState implements State {
 
   public void doAction(Context context) {
      System.out.println("Player is in stop state");
      context.setState(this); 
   }
 
   public String toString(){
      return "Stop State";
   }
}
//创建 Context 类。
public class Context {
   private State state;
 
   public Context(){
      state = null;
   }
 
   public void setState(State state){
      this.state = state;     
   }
 
   public State getState(){
      return state;
   }
}
//使用 Context 来查看当状态 State 改变时的行为变化。
public class StatePatternDemo {
   public static void main(String[] args) {
      Context context = new Context();
 
      StartState startState = new StartState();
      startState.doAction(context);
 
      System.out.println(context.getState().toString());
 
      StopState stopState = new StopState();
      stopState.doAction(context);
 
      System.out.println(context.getState().toString());
   }
}
执行程序,输出结果:
Player is in start state
Start State
Player is in stop state
Stop State
10.策略模式

在策略模式(Strategy Pattern)中,我们创建表示各种策略的对象和一个行为随着策略对象改变而改变的 context 对象。策略对象改变 context 对象的执行算法。

使用场景:如果在一个系统里面有许多类,它们之间的区别仅在于它们的行为,那么使用策略模式可以动态地让一个对象在许多行为中选择一种行为。

注意事项:如果一个系统的策略多于四个,就需要考虑使用混合模式,解决策略类膨胀的问题。

public interface Strategy {
   public int doOperation(int num1, int num2);
}
public class OperationAdd implements Strategy{
   @Override
   public int doOperation(int num1, int num2) {
      return num1 + num2;
   }
}
public class OperationSubtract implements Strategy{
   @Override
   public int doOperation(int num1, int num2) {
      return num1 - num2;
   }
}
public class OperationMultiply implements Strategy{
   @Override
   public int doOperation(int num1, int num2) {
      return num1 * num2;
   }
}
public class Context {
   private Strategy strategy;
 
   public Context(Strategy strategy){
      this.strategy = strategy;
   }
 
   public int executeStrategy(int num1, int num2){
      return strategy.doOperation(num1, num2);
   }
}
public class StrategyPatternDemo {
   public static void main(String[] args) {
      Context context = new Context(new OperationAdd());    
      System.out.println("10 + 5 = " + context.executeStrategy(10, 5));
 
      context = new Context(new OperationSubtract());      
      System.out.println("10 - 5 = " + context.executeStrategy(10, 5));
 
      context = new Context(new OperationMultiply());    
      System.out.println("10 * 5 = " + context.executeStrategy(10, 5));
   }
}
执行程序,输出结果:
10 + 5 = 15
10 - 5 = 5
10 * 5 = 50
11.责任链模式

责任链模式(Chain of Responsibility Pattern)为请求创建了一个接收者对象的链。在这种模式中,通常每个接收者都包含对另一个接收者的引用。如果一个对象不能处理该请求,那么它会把相同的请求传给下一个接收者,依此类推。

我们创建抽象类 AbstractLogger,带有详细的日志记录级别。然后我们创建三种类型的记录器,都扩展了 AbstractLogger。每个记录器消息的级别是否属于自己的级别,如果是则相应地打印出来,否则将不打印并把消息传给下一个记录器。

//创建抽象的记录器类。
public abstract class AbstractLogger {
   public static int INFO = 1;
   public static int DEBUG = 2;
   public static int ERROR = 3;
 
   protected int level;
 
   //责任链中的下一个元素
   protected AbstractLogger nextLogger;
 
   public void setNextLogger(AbstractLogger nextLogger){
      this.nextLogger = nextLogger;
   }
 
   public void logMessage(int level, String message){
      if(this.level <= level){
         write(message);
      }
      if(nextLogger !=null){
         nextLogger.logMessage(level, message);
      }
   }
 
   abstract protected void write(String message);
   
}
//创建扩展了该记录器类的实体类。
public class ConsoleLogger extends AbstractLogger {
 
   public ConsoleLogger(int level){
      this.level = level;
   }
 
   @Override
   protected void write(String message) {    
      System.out.println("Standard Console::Logger: " + message);
   }
}
public class ErrorLogger extends AbstractLogger {
 
   public ErrorLogger(int level){
      this.level = level;
   }
 
   @Override
   protected void write(String message) {    
      System.out.println("Error Console::Logger: " + message);
   }
}
public class FileLogger extends AbstractLogger {
 
   public FileLogger(int level){
      this.level = level;
   }
 
   @Override
   protected void write(String message) {    
      System.out.println("File::Logger: " + message);
   }
}
//创建不同类型的记录器。赋予它们不同的错误级别,并在每个记录器中设置下一个记录器。每个记录器中的下一个记录器代表的是链的一部分。
public class ChainPatternDemo {
   
   private static AbstractLogger getChainOfLoggers(){
 
      AbstractLogger errorLogger = new ErrorLogger(AbstractLogger.ERROR);
      AbstractLogger fileLogger = new FileLogger(AbstractLogger.DEBUG);
      AbstractLogger consoleLogger = new ConsoleLogger(AbstractLogger.INFO);
 
      errorLogger.setNextLogger(fileLogger);
      fileLogger.setNextLogger(consoleLogger);
 
      return errorLogger;  
   }
 
   public static void main(String[] args) {
      AbstractLogger loggerChain = getChainOfLoggers();
 
      loggerChain.logMessage(AbstractLogger.INFO, "This is an information.");
 
      loggerChain.logMessage(AbstractLogger.DEBUG, 
         "This is a debug level information.");
 
      loggerChain.logMessage(AbstractLogger.ERROR, 
         "This is an error information.");
   }
}

posted on 2021-05-07 10:42  后悔有药  阅读(267)  评论(0)    收藏  举报

导航