设计模式第十三次作业——备忘录模式、组合模式

备忘录模式(Memento模式)——游戏存进度代码实现

实现一

public class main {
	public static void main(String[] args) {
			GameRole gr=new GameRole();
			gr.SetInitState();
			gr.StateDisplay();
			//保存进度
			GameRole gr2=new GameRole();
			gr2.setVitality(gr.getVitality());
			gr2.setAttack(gr.getVitality());
			gr2.setDefence(gr.getAttack());
			
			gr.Fignt();
			gr.StateDisplay();
			//恢复之前的状态
			gr.setAttack(gr2.getAttack());
			gr.setVitality(gr2.getVitality());
			gr.setDefence(gr2.getDefence());
			gr.StateDisplay();
	}
}
class GameRole{
	int Vitality;
	int Attack;
	int Defence;
	public int getVitality() {
		return Vitality;
	}
	public void setVitality(int vitality) {
		Vitality = vitality;
	}
	public int getAttack() {
		return Attack;
	}
	public void setAttack(int attack) {
		Attack = attack;
	}
	public int getDefence() {
		return Defence;
	}
	public void setDefence(int defence) {
		Defence = defence;
	}
	public void StateDisplay() {
		System.out.println("角色当前状态");
		System.out.println("体力:"+this.Vitality);
		System.out.println("攻击力:"+this.Attack);
		System.out.println("防御力:"+this.Defence);
	}
	public void SetInitState() {
		this.Vitality=100;
		this.Attack=100;
		this.Defence=100;
	}
	public void Fignt() {
		this.Vitality=0;
		this.Attack=0;
		this.Defence=0;
	}
}

上面的代码存在的问题:
将所有的细节暴露给了客户端,导致客户端承担了太多的职责(保存状态,恢复状态,进行游戏),而且如是一旦游戏人
物的属性修改或者添加了,那么客户端相关的代码也必须修改,这些代码紧紧地耦合在了一起。
解决问题:
并不 一定需要把游戏角色这个类的所有属性都备份/存档,只需要把关心的数据进行存档,所以就要针对需妥存档的数据进行封装, 实现职责的分离。
这里,定义类RoleStateMemento封装需妥存档的数据。

实现二

public class main {
	public static void main(String[] args) {
		GameRole gr = new GameRole();
		gr.SetInitState();
		gr.StateDisplay();
		// 存档
		RoleStateCaretaker care = new RoleStateCaretaker();
		care.setRoleStateMemento(gr.SaveRoleState());
		//进行游戏
		gr.Fignt();
		gr.StateDisplay();
		//恢复状态
		gr.RecoveryState(care.getRoleStateMemento());
		gr.StateDisplay();
	}
}

class RoleStateMemento {
	int Vitality;
	int Attack;
	int Defence;

	public int getVitality() {
		return Vitality;
	}

	public void setVitality(int vitality) {
		Vitality = vitality;
	}

	public int getAttack() {
		return Attack;
	}

	public void setAttack(int attack) {
		Attack = attack;
	}

	public int getDefence() {
		return Defence;
	}

	public void setDefence(int defence) {
		Defence = defence;
	}

	public RoleStateMemento(int vitality, int attack, int defence) {
		this.Vitality = vitality;
		this.Attack = attack;
		this.Defence = defence;
	}
}

//保存memento
class RoleStateCaretaker {
	RoleStateMemento roleStateMemento;

	public RoleStateMemento getRoleStateMemento() {
		return roleStateMemento;
	}

	public void setRoleStateMemento(RoleStateMemento roleStateMem) {
		roleStateMemento = roleStateMem;
	}
}

class GameRole {
	int Vitality;
	int Attack;
	int Defence;

	public int getVitality() {
		return Vitality;
	}

	public void setVitality(int vitality) {
		Vitality = vitality;
	}

	public int getAttack() {
		return Attack;
	}

	public void setAttack(int attack) {
		Attack = attack;
	}

	public int getDefence() {
		return Defence;
	}

	public void setDefence(int defence) {
		Defence = defence;
	}

	public void StateDisplay() {
		System.out.println("角色当前状态");
		System.out.println("体力:" + this.Vitality);
		System.out.println("攻击力:" + this.Attack);
		System.out.println("防御力:" + this.Defence);
	}

	public void SetInitState() {
		this.Vitality = 100;
		this.Attack = 100;
		this.Defence = 100;
	}

	public void Fignt() {
		this.Vitality = 0;
		this.Attack = 0;
		this.Defence = 0;
	}

	// 存档状态
	public RoleStateMemento SaveRoleState() {
		return new RoleStateMemento(this.Vitality, this.Attack, this.Defence);
	}

	// 从RoleStateMemento恢复状态
	public void RecoveryState(RoleStateMemento memento) {
		this.Vitality = memento.Vitality;
		this.Attack = memento.Attack;
		this.Defence = memento.Defence;
	}
}

在进行软件系统设计的时候给用户后悔的权利(实际上可能也是用户妥求的权利),
对一些关键性的操作需要提供诸如撤销(Undo)的操作。这种操作就是Memento模式提供的。
Memento模式: 在不破坏封装性的前提 捕获一个对象的内部状态, 并在该对象之外保存这个状态。这样以
后就可以利用该保存的状态实施恢复操作。

Memento模式的共型结构图为:

在这里插入图片描述
Memento(备忘录): 负责存储Originator 对象的内部状态, 并可以防止Originator以外的其他对象访问 备忘录。
备忘录有两个接口:
Caretaker只能看到备忘录的 宿报 它只能将各忘录传递给其它对象。
Originator可看到备忘录的宽接 它可以访问返回到先前状态所需要的所有数据。

Memento模式基本代码

public class main {
	public static void main(String[] args) {
		Originator o=new Originator();
		o.setState("On");
		o.Show();
		
		Caretaker c=new Caretaker();
		c.setMemento(o.CreateMemento());
		o.setState("Off");
		o.Show();
		
		//恢复初始状态
		o.SetMemento(c.getMemento());
		o.Show();
	}
}
class Originator{
	private String state;//需要保存的属性,可能有多个
	public String getState() {
		return state;
	}
	public void setState(String state) {
		this.state=state;
	}
	public Memento CreateMemento() {
		//创建备忘录,将当前需要保存的信息导入并实例化一个Memento对象
		return(new Memento(state));
	}
	public void SetMemento(Memento memento) {
		//恢复备忘录,将memento导并将相关数据恢复
		state=memento.getState();
	}
	public void Show() {
		//显示数据
		System.out.println("State="+state);
	}
}
//备忘录类
class Memento{
	private String state;
	public Memento(String state) {
		this.state=state;
	}
	public String getState() {
		return state;
	}
	public void setState(String state) {
		this.state = state;
	}
}

class Caretaker{
	private Memento memento;

	public Memento getMemento() {
		return memento;
	}

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

备忘录模式和原型模式这两个模式可以结合使用
在发起人对象创建各忘录对象的时候, 如发起人对象中全部或者大部分的状态都需要保存,一个简洁的方式就是直接克隆 一个发起人对象。
也就是说,这个时候备忘录对象里面存放的是一个发起人对象的实例。

数据结构模式
常常有一些组件在内部其有特定的数据结构,如是让客户程序依赖这些特定的数据结构,将极大地破坏组件的复用。
这时候, 将这些特定数据结构封装在内部,在外部提供统一的接口, 来实现与特定数据结构无关的访问,是种行之有效的解决方案。

典型模式:
Composite
Iterator
Chain of Resposibility

组合模式

在软件在某些情况下,客户代码过多地位赖于对象容器复杂的内部实现结构,对象容器内部实现结构(而非抽象接口)的变化将引起客广代码的频繁文化,带来了代码的
维护性、扩展性等弊端。如何将 “客户代码与复杂的对象容器结构"解耦?让对象容器自己未实现自身的复杂结构,从而使得客户代码就像处理简单对象一样来处理复杂的对象容器?

不带模式的解决方案:组合模式

public class main {
	public static void main(String[] args) {
		Composite root = new Composite("服装");
		Composite c1 = new Composite("男装");
		Composite c2 = new Composite("女装");
		//定义所有叶子节点
		Leaf l1=new Leaf("衬衣");
		Leaf l2=new Leaf("夹克");
		Leaf l3=new Leaf("裙子");
		Leaf l4=new Leaf("套装");
		root.addComposite(c1);
		root.addComposite(c2);
		c1.addLeaf(l1);
		c1.addLeaf(l2);
		c2.addLeaf(l3);
		c2.addLeaf(l4);
		root.printStruct(0);
	}
}

class Leaf {
	private String name = "";

	public Leaf(String name) {
		this.name = name;
	}

	public void printStruct(int d) {
		for (int i = 0; i < d; i++) {
			System.out.println("-" + name);
		}
	}
}

class Composite {
	private Collection<Composite> childComposite = new ArrayList<Composite>();
	private Collection<Leaf> childLeaf = new ArrayList<Leaf>();
	private String name = "";

	public Composite(String name) {
		this.name = name;
	}

	public void addComposite(Composite c) {
		this.childComposite.add(c);
	}

	public void addLeaf(Leaf leaf) {
		this.childLeaf.add(leaf);
	}

	public void printStruct(int d) {
		for (int i=0; i < d; i++) {
			System.out.println(" ");
		}
		System.out.println("+"+name);
		for (Leaf leaf : childLeaf) {
			leaf.printStruct(d + 2);
		}
		for (Composite c : childComposite) {
			c.printStruct(d + 2);
		}
	}
}

改进:

要处理的对象可以表示成 个树形结构,而要对树上的分支节点和叶子进行操作时,它能够提供一致的方式,而不用区
分它是分支节点还是叶子—— 抽象出共同基类Component继承它产生计子节点和空

public class main {
	public static void main(String[] args) {
		Composite root = new Composite("服装");
		Composite c1 = new Composite("男装");
		Composite c2 = new Composite("女装");
		//定义所有叶子节点
		Leaf l1=new Leaf("衬衣");
		Leaf l2=new Leaf("夹克");
		Leaf l3=new Leaf("裙子");
		Leaf l4=new Leaf("套装");
		root.Add(c1);
		root.Add(c2);
		c1.Add(l1);
		c1.Add(l2);
		c2.Add(l3);
		c2.Add(l4);
		root.printStruct(0);
	}
}

abstract class Component{
	protected String name;
	public Component(String name) {
		this.name=name;
	}
	public abstract void Add(Component component);
	public abstract void Remove(Component component);
	public abstract void printStruct(int component);
	
}
class Leaf extends Component{
	public Leaf(String name) {
		super(name);
	}
	public void Add(Component component) {
		System.out.println("不能添加分支");
	}
	public void printStruct(int d) {
		for(int i=0;i<d;i++) {
			System.out.println(" ");
		}
		System.out.println("-"+name);
	}
	public void Remove(Component component) {
		System.out.println("不能删除分支");		
	}
}
class Composite extends Component{
	private ArrayList<Component>components=new ArrayList<Component>();
	public Composite(String name) {
		super(name);
	}
	
	@Override
	public void Add(Component component) {
		components.add(component);
		
	}
	@Override
	public void Remove(Component component) {
		components.remove(component);
	}
	@Override
	public void printStruct(int d) {
		for (int i=0; i < d; i++) {
			System.out.println(" ");
		}
		System.out.println("+"+name);
		for (Component c : components) {
			c.printStruct(d+2);
		}
		
	}
}

组合模式代码

public class main {
	public static void main(String[] args) {
		//生成树根,根上长出两个树叶
		Composite c=new Composite("ROOT");
		c.Add(new Leaf("leafA"));
		c.Add(new Leaf("leafB"));
		//根上长出分支CompositeX.分支上也有两叶LeafA和LeafB
		Composite c1=new Composite("CompositeX");
		c1.Add(new Leaf("LeafAx"));
		c1.Add(new Leaf("LeafBx"));
		c.Add(c1);
		
		Composite c2=new Composite("compositeXY");
		c2.Add(new Leaf("LeafAxy"));
		c2.Add(new Leaf("LeafBxy"));
		c1.Add(c2);
		
		c.Add(new Leaf("leafaxyc"));
		Leaf leaf=new Leaf("Leafaxyd");
		c.Add(leaf);
		c.Remove(leaf);
		c.Display(1);
	}
}
//Component为组合中的对象声明接口
abstract class Component{
	protected String name;
	public Component(String name) {
		this.name=name;
	}
	public abstract void Add(Component component);
	public abstract void Remove(Component component);
	public abstract void Display(int component);
	
}
class Leaf extends Component{
	public Leaf(String name) {
		super(name);
	}
	public void Add(Component component) {
		System.out.println("不能添加一个树叶");
	}
	public void Remove(Component component) {
		System.out.println("不能删除一个叶子");		
	}
	public void Display(int d) {
		for(int i=0;i<d;i++) {
			System.out.println(" ");
		}
		System.out.println("-"+name);
	}
}
//定义有枝节点行为,用来储存子部件在Component接口中实现与子部件有关的操作,比如Add和Remove
class Composite extends Component{
	private ArrayList<Component>components=new ArrayList<Component>();
	public Composite(String name) {
		super(name);
	}
	
	public void Add(Component component) {
		components.add(component);
		
	}
	
	public void Remove(Component component) {
		components.remove(component);
	}

	public void Display(int d) {
		for (int i=0; i < d; i++) {
			System.out.println(" ");
		}
		System.out.println("+"+name);
		for (Component c : components) {
			c.Display(d+2);
		}
		
	}

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Sweet y y y y u

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值