今天我将以制作酸菜鱼谈谈java抽象思想和处理问题的思路,一方面分享酸菜鱼的制作步骤,另外一方面结合过程谈谈我联想到的设计模式和一些思想,随着编程经验的增加,再加上自己喜欢制作一些美食,越来越觉得编程思想都是来源于生活,抽象于生活,如果觉得可以请帮忙点赞、收藏、转发
我们先来看下整体流程:
整个制作过程真的简单,作为程序员的我们如果不知道吃什么,可以亲手实践下这道菜,接下我将详细叙述制作过程
就近选择可靠的店,1人到2人建议选择2斤左右的,酸菜鱼制作我选择的是花鲢鱼,个人可根据口味和爱好选择喜欢的鱼,3人到5人建议选择3斤到4斤重的,我今天选择的是一般重的正好3斤,5人吃,还有其他菜,只吃鱼5人建议可以整2条3斤重的或者6斤重的,一般这种店都会售卖煮鱼调料,可以直接选择酸菜鱼调料,烹饪步骤也可按调料包说明进行操作,一般做出来味道都不错的,我这里直接选用的是酸菜包,也就3元一袋约200g酸菜
如果自身动手能力强,可以选择自己回家杀鱼并完成后面打整步骤,这里我们一般都是直接交给摊贩打理,摊贩将鱼拍晕,打鳞,破肚,清理内脏,清理鱼鳃,分解鱼头、鱼骨,切鱼片,打包装袋,我要求的是切片,摊贩会将带骨的和鱼片分开装袋,这个过程就是大家常谈的代理模式,我们将此项工作完全交给摊贩,在编程中我们也需要使用代理模式来完成某些需要的工作,接下来就摊贩帮我们处理鱼实现一下代理模式
定义接口,处理鱼
public interface HandleFish {
/**
* 处理鱼
* @param fish
*/
void handleFish(String fish);
}
真实处理鱼的摊贩处理
@Service
public class RealPersonHandleFish implements HandleFish{
/**
* 处理鱼
*
* @param fish
*/
@Override
public void handleFish(String fish) {
System.out.println("我是摊贩,开始处理:" + fish);
}
}
自己处理鱼
@Service
public class MySelfHandleFist implements HandleFish {
private RealPersonHandleFish realPersonHandleFish;
/**
* 处理鱼
*
* @param fish
*/
@Override
public void handleFish(String fish) {
if (realPersonHandleFish == null) {
realPersonHandleFish = new RealPersonHandleFish();
}
System.out.println("开始处理:");
//调用其他类进行处理
realPersonHandleFish.handleFish(fish);
}
}
开始处理鱼
public class ProxyPatternDemo {
public static void main(String[] args) {
HandleFish handleFish = new MySelfHandleFist();
handleFish.handleFish("鱼");
}
}
执行结果
开始处理:
我是摊贩,开始处理:鱼
Process finished with exit code 0
代理模式意图:为其他的对象提供一种代理,从而控制对这个对象的访问
代理模式主要解决:直接访问对象时带来的影响,比如说:要访问的对象在远程的机器上。
代理模式何时使用:访问一个类时,我们需要做一些控制的时候,不直接访问这个类,通过它的代理类进行访问。
代理模式如何解决:增加中间代理层。
代理模式关键代码:实现与被代理类组合,和被代理类具有同样的功能。
尽管摊贩已经清洗过鱼肉,但可能有的摊贩打扫的不是那么令人满意,回家后务必自己重新清理干净,特别是鱼鳃(这个东西吃着是苦的,别问我怎么知道的),清理后将带骨的和鱼片分开装盆滤干水分,准备腌制
今天煮酸菜鱼用到的调料基本上大家家里都有,具体可看上图调料工厂说明,胡椒粉建议家里可以备一瓶,买最小规格的,没有就不用,猪油能增加层次感,没有也可不用,还有就是去腥的料酒,少做饭的买个小规格的就好,大葱一般都可以不用,烹饪荤菜都少不了料酒,然后就是平常必备的那些了不一一赘述,其实我们所使用的调料,抽象一下就像我们平常使用的java基本数据类型以及集合类,每一样都会在我们的代码中使用,必不可少。注意1:生姜两用
注意2:酸菜包,打开后用清水清洗1到2遍,挤干水分,然后切成大块
然后用锅开中火直接炒制酸菜,将多余的水分炒干后装盘备用,这样做的目的是为了炒制时能更加的激发酸菜的酸味和香味,怎么判断炒干 > 锅边无明显水分,炒制时无多余的水蒸气冒出
注意3:做啥菜都可以放点小葱,香菜根据个人口味放或不放
注意4:我这里没有选用现成的鱼调料,直接用少许火锅料(味道稍稍带点甜味,不辣),火锅料可根据个人口味选择,能吃辣的可以选择辣味重的,量大概就100g到300g足够了,直接用鱼调料包的按照说明操作即可
注意5:我使用了少量嫩肉粉,主要目的是适度增加鱼肉的爽滑口感,没有可以不用或者用少量淀粉替代
鱼头鱼骨和鱼片分别用不同的容器腌制,腌制方法一致,腌制方法:放入适量的盐(不会就少一点少一点的慢慢增加,拌匀后直接尝,带有咸味稍重即可),盐是鱼肉入味的关键,盐少了烹饪出来的味道可能会很淡以至不好吃,然后放入少许胡椒粉,鸡精,料酒,嫩肉粉,姜片搅拌均匀,腌制时间不小于20分钟
微信图片_2022080616250614.jpg
出锅装盘后放上葱段和香菜
一份简单的酸菜鱼就制作完成,其实这个过程按照顺序一步一步操作就像是职责链模式
责任链模式(Chain of Responsibility Pattern),属于行为型模式,为请求创建了一个接收者对象的一条链。这种设计模式给予了请求的类型,对请求的发送端和接收端进行解耦操作。
在这种设计模式中,一般说来每个接收者都包含对另一个接收者的引用。如果一个对象不能处理该请求,那么它会把相同的请求传递给下一个接收者,依此类推,知道这条链走完。
意图:
避免请求发送者与接收者强耦合在一起,让多个对象都有可能接收到请求,且将这些对象连接成一条链,沿着这条链持续传递请求,直到有对象处理它为止。
主要解决:
职责链上的每一个处理者负责处理请求,上游只需要将请求发送到职责链上即可,不用关心请求的处理细节和请求的传递,所以职责链将请求的发送者和请求的处理者解耦了。
何时使用:
在处理消息的时候以过滤很多道,比如权限校验的各个环节,参数,合法性校验等等。
如何解决:
拦截的类都实现统一接口。
关键代码:
Handler 里面聚合它自己,在 HandlerRequest 里判断是否合适,如果没达到条件则向下传递,向谁传递之前 set 进去。
使用场景:
1、有多个对象可以处理同一个请求,具体哪个对象处理该请求由运行时刻自动确定。
2、在不明确指定接收者的情况下,向多个对象中的一个提交一个请求。
3、可动态指定一组对象处理请求。
简单实现:
我们创建抽象类 AbstractCookingFish,带有详细制作酸菜鱼步骤。然后我们创建六个顺序的处理类,都扩展了 AbstractCookingFish。每个处理类的级别是否属于自己的级别,如果是则相应地打印出来,否则将不打印并把消息传给下一个处理类。
责任链模式的 UML 图
创建抽象的鱼处理类。
public abstract class AbstractCookingFish {
public static final int FIRST = 1;
public static final int SECOND = 2;
public static final int THIRD = 3;
public static final int FOURTH = 4;
public static final int FIFTH = 5;
public static final int SIXTH = 6;
protected int level;
protected AbstractCookingFish nextCookingFish;
public void setNextCookingFish(AbstractCookingFish nextCookingFish){
this.nextCookingFish = nextCookingFish;
}
public void cookingFish(int level,String message){
if(this.level == level){ cooke(message);
}
if(nextCookingFish !=null){
nextCookingFish.cookingFish(level, message);
}
}
abstract protected void cooke(String message);
}
创建扩展了该鱼处理类的实体类。
public class BuyFish extends AbstractCookingFish {
public BuyFish(int level){
this.level = level;
}
@Override
protected void cooke(String message) {
System.out.println("BuyFish:买鱼步骤--" + message);
}
}
public class CleanFish extends AbstractCookingFish {
public CleanFish(int level){
this.level = level;
}
@Override
protected void cooke(String message) {
System.out.println("CleanFish:清理鱼,准备调料步骤--" + message);
}
}
public class PickleFish extends AbstractCookingFish {
public PickleFish(int level){
this.level = level;
}
@Override
protected void cooke(String message) {
System.out.println("PickleFish:腌制鱼步骤--" + message);
}
}
public class CookedSoupFish extends AbstractCookingFish {
public CookedSoupFish(int level){
this.level = level;
}
@Override
protected void cooke(String message) {
System.out.println("CookedSoupFish:炒制汤料步骤--" + message);
}
}
public class AddFish extends AbstractCookingFish {
public AddFish(int level){
this.level = level;
}
@Override
protected void cooke(String message) {
System.out.println("AddFish:分时段加入鱼骨鱼肉步骤--" + message);
}
}
public class DecorateFish extends AbstractCookingFish {
public DecorateFish(int level){
this.level = level;
}
@Override
protected void cooke(String message) {
System.out.println("最后一步DecorateFish:点缀装饰步骤--" + message);
}
}
创建不同类型的处理实现类。赋予它们不同的顺序,并在每个处理类中设置下一个处理类。每个处理类的下一个处理类代表的是链的一部分。
public class CookingFishDemo {
private static AbstractCookingFish getCookingFish(){
AbstractCookingFish buyFish = new BuyFish(AbstractCookingFish.FIRST);
AbstractCookingFish cleanFish = new CleanFish(AbstractCookingFish.SECOND);
AbstractCookingFish pickleFish = new PickleFish(AbstractCookingFish.THIRD);
AbstractCookingFish cookedSoupFish = new CookedSoupFish(AbstractCookingFish.FOURTH);
AbstractCookingFish addFish = new AddFish(AbstractCookingFish.FIFTH);
AbstractCookingFish decorateFish = new DecorateFish(AbstractCookingFish.SIXTH);
buyFish.setNextCookingFish(cleanFish);
cleanFish.setNextCookingFish(pickleFish);
pickleFish.setNextCookingFish(cookedSoupFish);
cookedSoupFish.setNextCookingFish(addFish);
addFish.setNextCookingFish(decorateFish);
return buyFish;
}
public static void main(String[] args) {
AbstractCookingFish cookingFish = getCookingFish();
cookingFish.cookingFish(AbstractCookingFish.FIRST, "一");
cookingFish.cookingFish(AbstractCookingFish.SECOND, "二");
cookingFish.cookingFish(AbstractCookingFish.THIRD, "三");
cookingFish.cookingFish(AbstractCookingFish.FOURTH, "四");
cookingFish.cookingFish(AbstractCookingFish.FIFTH, "五");
cookingFish.cookingFish(AbstractCookingFish.SIXTH, "六");
}
}
执行程序,输出结果:
Connected to the target VM, address: '127.0.0.1:55215', transport: 'socket'
BuyFish:买鱼步骤--一
CleanFish:清理鱼,准备调料步骤--二
PickleFish:腌制鱼步骤--三
CookedSoupFish:炒制汤料步骤--四
AddFish:分时段加入鱼骨鱼肉步骤--五
最后一步DecorateFish:点缀装饰步骤--六
Disconnected from the target VM, address: '127.0.0.1:55215', transport: 'socket'
Process finished with exit code 0
今天这个例子简单叙述了酸菜鱼的烹饪步骤,给大家讲述了设计模式中的代理模式和职责链模式,后期会随机更新其他设计模式,欢迎关注博主公众号,发现更多精彩内容!