diff --git a/README.md b/README.md index 51146a59bcd1bea84c8cf8322aeb06d393a42456..320286807f67e6a855e5b6671e849dc3adc78595 100644 --- a/README.md +++ b/README.md @@ -283,7 +283,22 @@ ![img.png](img/img_memento_pattern_eg.png) ### 6.8.2 备忘录模式原理 +![img.png](img/img_memento_pattern_principple.png) +### 6.8.5 备忘录模式总结 +**1 ) 备忘录模式的优点** + +1. 提供了一种状态恢复的实现机制,使得用户可以方便的回到一个特定的历史步骤,当新的状态无效或者存在问题的时候,可以使用暂时存储起来的备忘录将状态复原. +2. 备忘录实现了对信息的封装,一个备忘录对象是一种发起者对象状态的表示,不会被其他代码所改动.备忘录保存了发起者的状态,采用集合来存储备忘录可以实现多次撤销的操作 + +**2 ) 备忘录模式的缺点** + +- 资源消耗过大,如果需要保存的发起者类的成员变量比较多, 就不可避免的需要占用大量的存储空间,每保存一次对象的状态,都需要消耗一定系统资源 + +**3) 备忘录模式使用场景** + +1. 需要保存一个对象在某一时刻的状态时,可以使用备忘录模式. +2. 不希望外界直接访问对象内部状态时. ![img.png](img/img_memento_pattern_principle.png) 备忘录模式的主要角色如下: diff --git a/byv-memento-patttern-19/src/main/java/com/boyunv/memento/example02/MainApp.java b/byv-memento-patttern-19/src/main/java/com/boyunv/memento/example02/MainApp.java new file mode 100644 index 0000000000000000000000000000000000000000..4477642268bdbfa4e2f5ca0666edc16de0b56bba --- /dev/null +++ b/byv-memento-patttern-19/src/main/java/com/boyunv/memento/example02/MainApp.java @@ -0,0 +1,41 @@ +package com.boyunv.memento.example02; +/* + *@description + * + *@author boyunv + *@create 2023/9/5 22:46 + *@version 1.0 + */ + +public class MainApp { + public static void main(String[] args) throws InterruptedException { + + //创建玩家类,设置初始金币 + Player player = new Player(100); + //c创建备忘录对象 + Memento memento = player.createMemento(); + for (int i = 0; i < 100; i++) { + + //显示一下扔骰子的次数 + System.out.println("================第"+i+"次投掷"); + //显示当前的玩家状态 + System.out.println("当前状态:"+player); + + //开启游戏 + player.yacht(); + System.out.println("玩家所持有的金币:"+player.getMoney()+"元"); + //复活操作 + if(player.getMoney()> memento.getMoney()){ + System.out.println("赚到金币,保存当前的状态,继续游戏"); + player.createMemento();//更新快照 + } else if (player.getMoney()< player.getMoney()/2) { + System.out.println("所持有的金币不多了,游戏恢复初始状态"); + player.restoreMemento(memento); + } + + Thread.sleep(1000); + + } + + } +} diff --git a/byv-memento-patttern-19/src/main/java/com/boyunv/memento/example02/Memento.java b/byv-memento-patttern-19/src/main/java/com/boyunv/memento/example02/Memento.java new file mode 100644 index 0000000000000000000000000000000000000000..55bf9f614a61da875a785d8f13abbf78ed6a9836 --- /dev/null +++ b/byv-memento-patttern-19/src/main/java/com/boyunv/memento/example02/Memento.java @@ -0,0 +1,40 @@ +package com.boyunv.memento.example02; +/* + *@description + * 表示备份玩家的状态 + *@author boyunv + *@create 2023/9/5 22:18 + *@version 1.0 + */ + +import java.util.ArrayList; +import java.util.List; + +class Memento { + + private int money;//玩家的金钱 + + ArrayList fruits; //玩家获取的水果 + + public Memento(int money) { + this.money = money; + this.fruits=new ArrayList(); + + } + + //获取当前玩家的金币 + public int getMoney(){ + return money; + } + + //获取当前玩家的水果 + List getFruits(){ + return (List) fruits.clone(); + } + + //添加水果的方法 + void addFruit(String fruit){ + fruits.add(fruit); + } + +} diff --git a/byv-memento-patttern-19/src/main/java/com/boyunv/memento/example02/Player.java b/byv-memento-patttern-19/src/main/java/com/boyunv/memento/example02/Player.java new file mode 100644 index 0000000000000000000000000000000000000000..7237421b24c52a985751b126fa2e573851d928a9 --- /dev/null +++ b/byv-memento-patttern-19/src/main/java/com/boyunv/memento/example02/Player.java @@ -0,0 +1,96 @@ +package com.boyunv.memento.example02; +/* + *@description + * 玩家类 + *@author boyunv + *@create 2023/9/5 22:27 + *@version 1.0 + */ + +import lombok.ToString; + +import java.util.ArrayList; +import java.util.List; +import java.util.Random; + +public class Player { + + private int money; //金币 + + private List fruits=new ArrayList<>(); //玩家获得的水果 + + private static String[] fruitsName={ //表示水果种类的数组 + "苹果","葡萄","香蕉","橘子" + }; + + Random random=new Random(); + + public Player(int money) { + this.money = money; + } + + //获取当前所有金币 + public int getMoney(){ + return money; + } + + //获取一个水果 + public String getFruit(){ + String prefix=""; + if (random.nextBoolean()){ + prefix="好吃的"; + } + + //从 数组中拿一个水果 + String f=fruitsName[random.nextInt(fruitsName.length)]; + return prefix+f; + } + + //掷色子的方法 + public void yacht(){ + int dice=random.nextInt(6)+1; //掷骰子 + if(dice==1){ + money+=100; + System.out.println("所持有的金币增加了>>"); + } else if (dice==2) { + money/=2; + System.out.println("所持有的金币减少一半"); + + } else if (dice==6) { + //获取水果 + String fruit = getFruit(); + System.out.println("获取了一个水果:"+fruit); + fruits.add(fruit); + + }else { + System.out.println("无效数字,继续投递"); + } + + } + //拍摄快照 + public Memento createMemento(){ + Memento memento = new Memento(money); + for (String fruit : fruits) { + //判断:只保存 "好吃的" 水果 + if (fruit.startsWith("好吃的")){ + memento.addFruit(fruit); + } + } + + return memento; + } + + //撤销的方法 + public void restoreMemento(Memento memento){ + this.money= memento.getMoney(); + this.fruits=memento.getFruits(); + } + + @Override + public String toString() { + return "Player{" + + "money=" + money + + ", fruits=" + fruits + + '}'; + } +} diff --git a/byv-memento-patttern-19/src/main/java/com/boyunv/visitor/example01/Acceptable.java b/byv-memento-patttern-19/src/main/java/com/boyunv/visitor/example01/Acceptable.java deleted file mode 100644 index 9b04250b0c6d19d4257504f502d5ca09387f4213..0000000000000000000000000000000000000000 --- a/byv-memento-patttern-19/src/main/java/com/boyunv/visitor/example01/Acceptable.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.boyunv.visitor.example01; -/* - *@description - * 接待者接口 (抽下昂元素接口) - *@author boyunv - *@create 2023/9/3 9:42 - *@version 1.0 - */ - -public interface Acceptable { - - //接受所有visitor访问者的子类 - public void accept(Visitor visitor); -} diff --git a/byv-memento-patttern-19/src/main/java/com/boyunv/visitor/example01/Candy.java b/byv-memento-patttern-19/src/main/java/com/boyunv/visitor/example01/Candy.java deleted file mode 100644 index b9ced9d2f9a907dfeaba614a6aa40744437f5b80..0000000000000000000000000000000000000000 --- a/byv-memento-patttern-19/src/main/java/com/boyunv/visitor/example01/Candy.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.boyunv.visitor.example01; -/* - *@description - * 糖果类 - *@author boyunv - *@create 2023/9/3 9:21 - *@version 1.0 - */ - -import java.time.LocalDate; - -public class Candy extends Product implements Acceptable{ - public Candy(String name, LocalDate producedDate, double price) { - super(name, producedDate, price); - } - - - @Override - public void accept(Visitor visitor) { - //accept方法中调用访问者,并将this传递回去 - visitor.visit(this); - - } -} diff --git a/byv-memento-patttern-19/src/main/java/com/boyunv/visitor/example01/Client.java b/byv-memento-patttern-19/src/main/java/com/boyunv/visitor/example01/Client.java deleted file mode 100644 index e18059e62c4bd5353b6affb6973a3e9192bf7900..0000000000000000000000000000000000000000 --- a/byv-memento-patttern-19/src/main/java/com/boyunv/visitor/example01/Client.java +++ /dev/null @@ -1,48 +0,0 @@ -package com.boyunv.visitor.example01; -/* - *@description - * - *@author boyunv - *@create 2023/9/3 9:37 - *@version 1.0 - */ - -import java.text.NumberFormat; -import java.time.LocalDate; -import java.util.Arrays; -import java.util.List; - -public class Client { - public static void main(String[] args) { - LocalDate billDate = LocalDate.now(); - - Candy candy = new Candy("徐福记",LocalDate.of(2022,10,1),10.0); - System.out.println("糖果: " + candy.getName()); - - double rate = 0.0; - - long days = billDate.toEpochDay() - candy.getProducedDate().toEpochDay(); - System.out.println(days); - - if(days > 180){ - System.out.println("超过半年的糖果,请勿食用!"); - }else{ - rate = 0.9; - double discountPrice = candy.getPrice() * rate; - System.out.println("打折后的价格"+ NumberFormat.getCurrencyInstance().format(discountPrice)); - } - - //三件商品加入购物车 //模拟添加多个商品 - List products = Arrays.asList( - new Candy("金丝猴奶糖",LocalDate.of(2022,6,10),10.00), - new Wine("衡水老白干",LocalDate.of(2020,6,10),100.00), - new Fruit("草莓",LocalDate.of(2022,10,12),50.00,1) - ); - - Visitor visitor = new DiscountVisitor(LocalDate.of(2022,10,17)); - for (Acceptable product : products) { - product.accept(visitor); - } - - } -} diff --git a/byv-memento-patttern-19/src/main/java/com/boyunv/visitor/example01/DiscountVisitor.java b/byv-memento-patttern-19/src/main/java/com/boyunv/visitor/example01/DiscountVisitor.java deleted file mode 100644 index c69c7c508c91d2a314c38dc63c068a63a6964133..0000000000000000000000000000000000000000 --- a/byv-memento-patttern-19/src/main/java/com/boyunv/visitor/example01/DiscountVisitor.java +++ /dev/null @@ -1,63 +0,0 @@ -package com.boyunv.visitor.example01; -/* - *@description - * 折扣计价访问者类 - *@author boyunv - *@create 2023/9/3 9:26 - *@version 1.0 - */ - -import java.text.NumberFormat; -import java.time.LocalDate; - -public class DiscountVisitor implements Visitor{ - - private LocalDate billDate; - - public DiscountVisitor(LocalDate billDate) { - this.billDate = billDate; - System.out.println("结算日期: " + billDate); - } - - @Override - public void visit(Candy candy) { - System.out.println("糖果: " + candy.getName()); - - //糖果大于180天,禁止售卖,否则九折 - long days=billDate.toEpochDay()-candy.getProducedDate().toEpochDay(); - if(days>180){ - System.out.println("超过半年的糖果,请勿食用!"); - }else{ - double rate = 0.9; - double discountPrice = candy.getPrice() * rate; - System.out.println("糖果打折后的价格"+ NumberFormat.getCurrencyInstance().format(discountPrice)); - } - - } - - @Override - public void visit(Wine wine) { - System.out.println("酒类: " + wine.getName()+",无折扣价格!"); - System.out.println("原价: "+NumberFormat.getCurrencyInstance().format(wine.getPrice())); - } - - @Override - public void visit(Fruit fruit) { - System.out.println("水果: " + fruit.getName()); - //获取产品生产天数 - long days = billDate.toEpochDay() - fruit.getProducedDate().toEpochDay(); - - double rate = 0; - - if(days > 7){ - System.out.println("超过七天的水果,请勿食用!"); - }else if(days > 3){ - rate = 0.5; - }else{ - rate = 1; - } - - double discountPrice = fruit.getPrice() * fruit.getWeight() * rate; - System.out.println("水果价格: "+NumberFormat.getCurrencyInstance().format(discountPrice)); - } -} diff --git a/byv-memento-patttern-19/src/main/java/com/boyunv/visitor/example01/Fruit.java b/byv-memento-patttern-19/src/main/java/com/boyunv/visitor/example01/Fruit.java deleted file mode 100644 index f714d45afa59f3b874aa9dc84906e72afc712d1a..0000000000000000000000000000000000000000 --- a/byv-memento-patttern-19/src/main/java/com/boyunv/visitor/example01/Fruit.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.boyunv.visitor.example01; -/* - *@description - * - *@author boyunv - *@create 2023/9/3 9:22 - *@version 1.0 - */ - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.Getter; -import lombok.Setter; - -import java.time.LocalDate; - -public class Fruit extends Product implements Acceptable{ - - @Setter - @Getter - private double weight; - - public Fruit(String name, LocalDate producedDate, double price) { - super(name, producedDate, price); - } - - public Fruit(String name, LocalDate producedDate, double price, double weight) { - super(name, producedDate, price); - this.weight = weight; - } - @Override - public void accept(Visitor visitor) { - //accept方法中调用访问者,并将this传递回去 - visitor.visit(this); - - } -} diff --git a/byv-memento-patttern-19/src/main/java/com/boyunv/visitor/example01/Product.java b/byv-memento-patttern-19/src/main/java/com/boyunv/visitor/example01/Product.java deleted file mode 100644 index 45366ccc128a74653da6e98ae805514dfc9b8a4a..0000000000000000000000000000000000000000 --- a/byv-memento-patttern-19/src/main/java/com/boyunv/visitor/example01/Product.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.boyunv.visitor.example01; -/* - *@description - * 抽象商品父类 - *@author boyunv - *@create 2023/9/3 9:19 - *@version 1.0 - */ - -import lombok.AllArgsConstructor; -import lombok.Data; - -import java.time.LocalDate; -@Data -@AllArgsConstructor -public abstract class Product { - private String name; //商品名 - private LocalDate producedDate; // 生产日期 - private double price; //单品价格 -} diff --git a/byv-memento-patttern-19/src/main/java/com/boyunv/visitor/example01/Visitor.java b/byv-memento-patttern-19/src/main/java/com/boyunv/visitor/example01/Visitor.java deleted file mode 100644 index 83807c476d8d60c6a6a19a67cbbad62f8933be34..0000000000000000000000000000000000000000 --- a/byv-memento-patttern-19/src/main/java/com/boyunv/visitor/example01/Visitor.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.boyunv.visitor.example01; -/* - *@description - * 访问者接口-根据入参不同调用对应的重载方法 - *@author boyunv - *@create 2023/9/3 9:24 - *@version 1.0 - */ - -public interface Visitor { - - public void visit(Candy candy); //糖果重载方法 - - public void visit(Wine wine); //酒类重载方法 - - public void visit(Fruit fruit); //水果重载方法 -} diff --git a/byv-memento-patttern-19/src/main/java/com/boyunv/visitor/example01/Wine.java b/byv-memento-patttern-19/src/main/java/com/boyunv/visitor/example01/Wine.java deleted file mode 100644 index e6b866ddc23e064257d5c0c6c0d7982a6326b411..0000000000000000000000000000000000000000 --- a/byv-memento-patttern-19/src/main/java/com/boyunv/visitor/example01/Wine.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.boyunv.visitor.example01; -/* - *@description - *酒水类 - *@author boyunv - *@create 2023/9/3 9:21 - *@version 1.0 - */ - -import java.time.LocalDate; - -public class Wine extends Product implements Acceptable{ - public Wine(String name, LocalDate producedDate, double price) { - super(name, producedDate, price); - } - - @Override - public void accept(Visitor visitor) { - //accept方法中调用访问者,并将this传递回去 - visitor.visit(this); - - } -} diff --git a/img/img_memento_pattern_principple.png b/img/img_memento_pattern_principple.png new file mode 100644 index 0000000000000000000000000000000000000000..1751add6e7e1d694b11769d56c21b74ff8ff468e Binary files /dev/null and b/img/img_memento_pattern_principple.png differ