河南新闻联播:制作者模式——连系案例,通俗易懂

admin/2020-05-04/ 分类:科技/阅读:

一个设计模式解决一类问题,最近学习了一下制作者模式,看了许多博客,讲的模棱两可,以是决议写一下我以为比较好明白的简介
参考自知乎 https://zhuanlan.zhihu.com/p/58093669,

一、先容

1、啥是制作者模式

是将一个庞大的工具的构建与它的示意星散,使得同样的构建历程可以建立差别的示意

看不懂对吧!实在我也看不懂,不管它,通过案例和代码加深明白

2、使用场景

一个设计模式解决一类问题,那么制作者模式解决了什么问题呢?——工具的构建过于庞大的问题

  • 当一个类的组织函数参数过多(跨越四个),而且有的参数无关紧要,或者许多产物有默认值。
  • 产物类非常庞大或者产物类由于挪用顺序差别而发生差别作用
3、优点
  • 庞大产物的建立步骤剖析在差别的方式中,这些方式可以挪用顺序差别,效果差别,建立效果很清晰
4、瑕玷
  • 若是产物的内部转变庞大,可能会导致需要界说许多详细制作者来实现这种转变。

二、案例

理论总是难以明白的,现在通过案例剖析问题,一步步领会使用制作者模式的利益

【案例】好好看一下这个案例

KFC套餐
如果现在KFC内里有许多个套餐
在套餐内里有必点,也有选点,然后每个单品又有巨细之分
必点:汉堡(hamburger),薯条(chips)
选点:鸡腿(chicken),可乐(cola),披萨(pizza)

【用Java代码模拟场景】

我们若何组成这么多套餐实例呢?

我们不使用制作者模式也能构建代码,然则制作者模式会让代码看上去更装逼,代码到后期更结构化更容易维护和拓展

首先构建这个实体类KFC

public class KFC { //套餐必点 private String hamburger; private String chips; //套餐选点 private String chicken; private String cola; private String pizza; } 

我们的想法是不是折叠组织函数来建立实例,下面来实验一下

public class KFC{ //省略了上面的属性..... //必点套餐A public KFC(String hamburger,String chips){ this(hamburger,chips,null,null,null); } A //套餐B public KFC(String hamburger,String chips,String chicken){ this(hamburger,chips,chicken,null,null); } //套餐C public KFC(String hamburger,String chips,String chicken,String cola){ this(hamburger,chips,chicken,cola,null); } //......另有好多种组合方式,你会发现使用折叠组织函数的方式十分庞大 //全选 public KFC(String hamburger,String chips,String chicken,String cola,String pizza){ this.hamburger = hamburger; this.chips = chips; this.chicken = chicken; this.cola = cola; this.pizza = pizza; } } 

我们会发现使用折叠组织函数的方式很庞大,很恶心,代码看都不想看

那么有人会想,我可以使用set方式来建立,我只要一个必点组织就好了,那继续模拟咯

public class KFC{ //.....省略了属性 //必点 public KFC(String hamburger,String chips){ this.hamburger = hamburger; this.chips = chips; } //set方式 public void setChicken(String chicken) { this.chicken = chicken; } public void setCola(String cola) { this.cola = cola; } public void setPizza(String pizza) { this.pizza = pizza; } //实例化工具,你会发现这种方式就友好许多 public static void main(String[] args) { KFC kfc = new KFC("大汉堡","大薯条"); //加小份可乐 kfc.setCola("小可乐"); //加个鸡腿 kfc.setChicken("大鸡腿"); System.out.println(kfc); } } 

你会发现使用set方式就友好了许多

这个虽然友好了许多,然则也有点小毛病,就是你set太随意了,我可能这个套餐内里没有这个单品,而使用set的人却不知道,造成错误的套餐泛起!。

为领会决上面的两种问题:一种设计模式解决一类问题,以是制作者模式就泛起了


三、制作者模式

先领会一下又哪些角色吧,看不懂没关系,看一下代码就懂了

四个角色

Product(产物角色): 一个详细的产物工具。

Builder(抽象制作者): 建立一个Product工具的各个部件指定的抽象接口。

ConcreteBuilder(详细制作者): 实现抽象接口,构建和装配各个部件。

Director(指挥者): 构建一个使用Builder接口的工具。它主要是用于建立一个庞大的工具。它主要有两个作用,一是:隔离了客户与工具的生产历程,二是:卖力控制产物工具的生产历程。

拿其中两个套餐举例

套餐A:汉堡,薯条,大鸡腿
套餐B:汉堡,薯条,小鸡腿,小可乐,小披萨

其中薯条和汉堡小大由之,而且必须有,
其它的都为牢固巨细,然则你可以选择有或没有

  • 产物(KFC)
public class KFC { //套餐必点 private String hamburger; private String chips; //套餐选点 private String chicken; private String cola; private String pizza; //必点 public KFC(String hamburger,String chips){ this.hamburger = hamburger; this.chips = chips; } //set方式 public void setChicken(String chicken) { this.chicken = chicken; } public void setCola(String cola) { this.cola = cola; } public void setPizza(String pizza) { this.pizza = pizza; } } 
  • Builder

界说一个接口,解释需要制作什么,获得什么

public interface Builder { void setChicken(); void setCola(); void setPizza(); KFC getKFC(); } 
  • ConcreteBuilder:

此时应该注重,这个时刻还没有生产套餐,只是界说套餐

套餐A

public class ConcreteBuilder1 implements Builder { private KFC kfc; //这一步非常重要 public ConcreteBuilder1(String hamburger,String chips){ kfc = new KFC(hamburger,chips); } @Override public void setChicken() { kfc.setChicken("大鸡腿"); } @Override public void setCola() { kfc.setCola(null); System.out.println("套餐A内里没有可乐"); } @Override public void setPizza() { kfc.setPizza(null); System.out.println("套餐A内里没有披萨"); } @Override public KFC getKFC() { return kfc; } } 

套餐B

public class ConcreteBuilder2 implements Builder { private KFC kfc; //这一步非常重要 public ConcreteBuilder2(String hamburger,String chips){ kfc = new KFC(hamburger,chips); } @Override public void setChicken() { kfc.setChicken("小鸡腿"); } @Override public void setCola() { kfc.setCola("小可乐"); } @Override public void setPizza() { kfc.setPizza("小披萨"); } @Override public KFC getKFC() { return kfc; } } 

Director:

真正的执行者,这里把他看成服务员,此时你像服务员点餐

public class Director { public KFC build(Builder builder){ //套餐内里我只选了鸡腿和可乐 builder.setChicken(); builder.setCola(); return builder.getKFC(); } } 

测试

public class BuilderTest { public static void main(String[] args) { //套餐A System.out.println("======套餐A======"); Builder concreteBuilder1 = new ConcreteBuilder1("大汉堡", "小薯条"); KFC kfc1 = new Director().build(concreteBuilder1); System.out.println(kfc1); //套餐B System.out.println("======套餐B======"); Builder concreteBuilder2 = new ConcreteBuilder2("小汉堡", "小薯条"); KFC kfc2 = new Director().build(concreteBuilder2); System.out.println(kfc2); } } 

输出

到了这里你照样会以为有点贫苦,你会发现,单品无关紧要的选择上面你十分的被动,代码看上去也很怪,若是你下次想所有单品先选上,再去选套餐的时刻,你又要新建一个新的指导者。 

我以为通俗的制作者模式不适合参数的无关紧要的选择,通俗的制作者模式更偏重调控顺序,在有些情况下需要简化系统结构


四、简化版的制作者模式

这个时刻简化版的制作者模式站出来了

接纳链式编程的方式

这种模式加倍天真,加倍相符界说

既然Director是转变的,而且实在在生活中我们自己自己就是Director,以是这个时刻我们可以把Director这个角色去掉,由于我们自身就是指导者

  • 产物(product)
public class KFC { //套餐必点 private String hamburger; private String chips; //套餐选点 private String chicken; private String cola; private String pizza; public KFC(String hamburger,String chips){ this.hamburger = hamburger; this.hamburger = chips; } public void setChicken(String chicken) { this.chicken = chicken; } public void setCola(String cola) { this.cola = cola; } public void setPizza(String pizza) { this.pizza = pizza; } } 
  • 抽象制作者(builder)
public abstract class Builder { abstract Builder setChicken(); abstract Builder setCola(); abstract Builder setPizza(); abstract KFC getKFC(); } 
  • 详细制作者(ConcreteBuilder)
public class ConcreteBuilder extends Builder { KFC kfc; public ConcreteBuilder(String hamburger,String chips){ kfc = new KFC(hamburger,chips); } @Override Builder setChicken() { kfc.setChicken("鸡腿"); return this; } @Override Builder setCola() { kfc.setCola("可乐"); return this; } @Override Builder setPizza() { kfc.setPizza("披萨"); return this; } @Override KFC getKFC() { return kfc; } } 
  • 测试
public class BTest { public static void main(String[] args) { KFC kfc = new ConcreteBuilder("汉堡","薯条").setChicken().setCola().getKFC(); } } 

若是不需要抽象制作者的角色来划定生产内容,那么代码到这里实在另有进一步的简化空间。

【要害代码】

使用静态内部类的方式

【进一步简化】

public class KFC { //套餐必点 private String hamburger; private String chips; //套餐选点 private String chicken; private String cola; private String pizza; //一定要有一个带有Builder参数的制作者 private KFC(Builder builder) { this.hamburger = builder.hamburger; this.chips = builder.chips; this.chicken = builder.chicken; this.cola = builder.cola; this.pizza = builder.pizza; } //注重必须为静态内部类 public static class Builder{ //套餐必点 private String hamburger; private String chips; //套餐选点 private String chicken; private String cola; private String pizza; public Builder(String hamburger,String chips){ this.hamburger = hamburger; this.chips = chips; } public Builder setChicken(){ this.chicken = "小鸡腿"; return this; } public Builder setCola(){ this.cola = "小可乐"; return this; } public Builder setPizza(){ this.pizza = "小披萨"; return this; } //天生一个产物 public KFC getKFC(){ return new KFC(this); } } } 

测试

public class BuilderTest { public static void main(String[] args) { KFC kfc = new KFC.Builder("大汉堡", "小薯条").setChicken().setCola().getKFC(); System.out.println(kfc); } } 

五、制作者模式和抽象工厂模式的区别

通过上面的代码,你发现通俗的制作者模式和抽象工厂模式真的很像,在制作者模式中的builder角色很像超级工厂,然后contracterBuilder很像详细的工厂,都是划定了制作的内容

那么它们之前 有什么区别呢

  • 制作者模式有指导者这个角色,直接返回一个组装好的产物,而抽象工厂模式返回一系列相关的产物,这些产物位于差别的产物品级结构,组成了一个产物族
  • 制作者模式更适合庞大的产物构建
  • 可以将抽象工厂模式明白成汽车零件生产工厂,而制作者模式看出组装工厂

【总结】

学习一类技巧是为领会决一类问题,学习设计模式主要是为了明白它的头脑,未来遇到代码的编写,使用这种模式会加倍的方式,而没有必要刻意的去使用,然则需要刻意的去演习,形成这种头脑

,

申博sunbet

申博sunbet www.sunbet88.us是Sunbet指定的Sunbet官网,Sunbet提供Sunbet(Sunbet)、Sunbet、申博代理合作等业务。

TAG:
阅读:
广告 330*360
广告 330*360
Sunbet_进入申博sunbet官网
微信二维码扫一扫
关注微信公众号
新闻自媒体 Copyright © 2002-2019 Sunbet 版权所有
二维码
意见反馈 二维码