headfirst设计模式(4)—工厂模式

背景

 

电商平台时召开有些秒杀场景的移位来对货品进行促销,来带全企业之影响力;而秒杀活动一般是以一定的时日、特定的货色进行限定的行销抢购,这样见面掀起大量底用户展开抢购,并在移动约定的年华接触而的开展秒杀抢购;这样啊就算形成如下特征:

1)大量用户同一时间同时展开抢购,网站弹指之间访问流量剧增。

2)访问请求数量远远好叫库存数量,只有少部分用户会秒杀成功。

3)购物车一直生单减库存。

4)秒杀商品下仅减库存。

 

开篇

概念

从今上面的背景中我们要给的题目便,针对于电商平台如何给它可以在这种高并发、大流量之乞求下让其会安居乐业、满负荷的周转。所以就便待引入流量监控平台,它会实时了解各个服务器的周转参数、各个业务单元的乞求数量;随时为官员提供清晰的数码参考,以备调度。

 

整日逛博客园,就是狠毒不下中心来写首博客,忙是一边,但是说忙能发生差不多忙也,都有时间闲逛博客园,写篇博客的时光还没有?(这尚真的不好说)

咦是流量监控

流量监控,又好清楚为同种流量整形,是一个计算机网络的纱交通管理技术,从而延缓部分或者具备数据包,使的切人们所用的纱交通规则,速率限制的其中同样栽主要形式。

网络流量控制是因此来优化还是包性能,改善延迟,和/或增加一些品种的数码包延迟满足某些标准下之可用带富。如果某一个环节趋于饱和点,网络延迟或大幅上升。因此,网络流量控制得应用为戒这种状况来,并保障延迟性检查。

网络流量控制提供了平栽手段来支配以指定时间内(带富限制),被发送到网被之数据量,或者是极酷速率的多寡流量发送。这种操纵可以实现的门路来诸多,但是一般状态下,网络流量控制总是以拖延发包来贯彻之,一般下在网边缘,以控制入网络的流量,但也可一直采用被数据源(例如,计算机还是网卡),或是网络被的一个元素。

每次想到写一首新的设计模式,我究竟会问自己:

流量监控限流算法

限流算法主要也:漏桶、令牌桶、计数器

1,自己懂了也?

漏桶

一个稳定容量的漏桶,按照常量固定速率流出水滴。

图片 1 

 

2,我能够坐同等种简单且产生逻辑的方法把其说出去呢?

令牌桶

使牌桶算法是一个存固定容量令牌的桶,按照固定速率往桶里添加令牌。

图片 2 

背好万无一失,但是同样按照正经的放屁还是要生吧,起码要忽悠得头头是道嘛(手动斜眼笑)

计数器

突发性我们尚用计数器来进行限流,主要用来界定总并发数,比如数据库连接池、线程池、秒杀的连发数;只要全局总请求数或者自然时间段的总请求数设定的阀值则进行限流,是简单粗暴的到底数据限流,而未是平均速率限流。

有关工厂模式的几乎单问题

限流措施

  • 克总并发数(比如数据库连接池、线程池)
  • 界定瞬时连发数(如nginx的limit_conn模块,用来限制瞬时连发连接数)
  • 克时间窗口内之平均速率(如Guava的RateLimiter、nginx的limit_req模块,限制每秒的平分速率)
  • 限远程接口调用速率
  • 克MQ的费速率。
  • 好根据网络连接数、网络流量、CPU或内存负载等来限流

 

 

1,这个是将来波及啊的?

行业

以下针对为国内比较大型的互联网商家对被流量监控架构方面的信息收集

2,怎么用?

阿里

从未有过找到相关的技术资料,只是找到2016年享受的
“阿里管控系统靠什么扛住世界最充分局面之流量洪峰?”的篇章,文章被关系了那殊场景下的算法和限流框架。

用户洪峰

设想的素是:

a) 允许看的速率

b) 系统接受的极其老洪峰

c) 洪峰爆发的间隔时间

处理方式: 令牌桶限流

回调洪峰

除此之外0点0细分的这种流量洪峰,还有网里头的回调引起的大水。想象一下这样的观,物流体系以处理发货信息,会隔一段时间调用交易系统来得到交易信息。为了提高效率,它每次批量询问交易系统的多少。这样,对交易系统也拉动了流量之碰撞。如果对这种回调不加以限定,那么可能交易系统忙于处理这种回调洪峰,对用户洪峰会见疏于处理。

对这种洪峰,有三栽特性:

a) 有距离频率

b) 每次调用计量大

c) 允许发生延迟

处理方式:漏桶算法

限流框架分为:监控模块、决策模块、规则改变模块、限流模块。

图片 3 

 

3,不用行非常?

腾讯

腾讯采用同样种轻量级流控方案,方案如下:

1、计数器的key能“计时“

率先选择下ckv作为计数器存储,相比redis开发会再次熟悉,同时保护也再次易,当然该方案为堪选取redis作为计数器存储。

优势:方案用简短的措施将全局流控服务做成原子化(计数和计时原子化),开发门槛低。

2、请求统计用拉取之法子替换上报

于要的统计方式,一般全量上报不可行,所有工作的请求量至少1:1上报及ckv,ckv的容量与是个问题,单key也易于变成热点。定时或定量批量举报,都没法儿确保实时流控,特别是请求量大的时光,流控延迟的题目会见让加大。

优势:方案减ckv的访问量,同时确保流控的准头。

3、部署不待agent

为做重新轻量的方案,我们着想agent的必要性,分析发现,agent要形成的功能比较简单,主要力量托管到业务流控api。

优势:方案免使用agent的方法,部署维护还简约。

4、全局和单机流控同时启用

方案对容灾做了尽量的设想,主要解决智是全局和单机流控同时启用,即根据ckv的全局流控和根据单机共享内存的单机流控都同时工作。

优势:方案来大好的容灾能力,容灾方式大概实用。

5、解决ckv性能瓶颈,流控性能达到百万/s

是因为采用ckv的incr以及配额拉取的兑现方式,全局流控接入服务要的力赢得基金增长。

眼前方案单独申请了同样片ckv,容量也6G,使用incr的不二法门,压测性能上9w+/s。

针对业务空接口(Appplatform框架)做流控压测,使用30尊v6虚拟机,单机50进程,压测性能达到50w+/s。

单接口50w/s的伸手的劳动接通,同样也能满足多接口总体服务请求量50w+/s的大局流控需求。

上述的压测瓶颈主要是Appplatform框架的习性原因,由于拉取配额值是根据流控阈值设定(一般>10),50w+的请求量只有无交5w的ckv访问量,ckv没到瓶颈。

优势:方案以相同的资源(单独一片6G底ckv),能满足工作的请求量更胜似,性能上百万/s。

6、支持扩容和动态流控升级

支撑平行扩展流控能力,一模仿全局流控部署会满足流控的服务请求量是上百万/s,更老之劳动请求量需要配置多仿全局流控。

支撑提升至动态流控能力,ckv写入的流控阈值是由此定时管理器完成,目前事情已开了健康度上报,定时管理器只需要针对接健康度数据,分析接口时恳请情况,动态调整流控阈值即可达到动态流控能力。

优势:方案总体简单轻量,扩容和升级还死爱。

要流程图

图片 4 

 

首先单同老三只问题,我现即令得告知您答案:早点收工,可以

京东

京东10亿调用量的赛可用网关系统所干的技巧栈:

接入层 Nginx+lua 技术。

NIO+Serviet3 异步技术。

分手技术。

降限流。

熔断技术。

缓存,哪些地方该加缓存,哪些地方可以直接读库。

异构数据。

霎时砸。

监理统计,这是全部大可用网关系统里非常主要之同有的。

有着的设计模式对自身来说都是为减少工作量。关于减少工作量我之知情是:每个需求,都应于她相当的时出现适当的代码!这个极度重要了

小米

小米抢购限流峰值系统针对为小米商城秒杀抢购的实现同技术架构

大秒系统的架构设计

图片 5 

 

大秒系统要是因为如下几个模块组合

限流集群 HTTP 服务放号策略集群
Middle 服务监控数据基本 Dcacenter监控管理体系 Master准实时防刷模块
antiblack基础存储和日志队列服务: Redis 集群、Kafka 集群等

整个大秒体系中大秒前端模块
(HTTP/middle/antiblack) 和监察数据主导利用 golang
开发,大秒监控管理体系使用 Python + golang 开发。

大秒的前端架构设计

大秒前端的架构设计从三个网开展

限流集群 HTTP 服务

策略集群 Middle 服务

准实时反作弊 antiblack 服务

图片 6 

 

代码偷懒,后期返工多

当当

根据SOA架构理念,降低系统耦合性,接口定义清晰明确,保证独立子系统的健壮性高,降低故障过系统扩散风险,从而以伸缩性的诸多不便逐步分解至各个系统。

本着网进行分级,集中力量,突出重点系统。当当网从卖场及交易流程均属一级系统,这部分体系直接关乎用户体验以及订单量。在网稳定以及可靠性等指标上,设计标准高于后台系统。

预先考虑用异步处理代替同步处理,做好系统十分的降方案,保证一定量的合格服务。

图片 7 

 

 

 

 

过度设计,后期返工多

方案

透过资料的募集,参考各大互联网商家的流量监控平台的架构搭建方案,大概了解涉及的系模块组成、限流算法、限流措施与原理。

归纳各方资料整理得出简要的流量监控方案,流量监控可以分成多只系统组成来好其职责,这个平台要的片是:流量上报、限流、策略、调度。

设计模式+经验可解决是题目,其他的自己还不明白。没有经历怎么惩罚?两个中心:

流量上报

重点用来采集系统的请数据、状态及系统运行状况。有了这些运行数据,才能够对外要对内进行决策处理;

1,能用

1、监控内容

1)对外和对外

对外用户请求

对内各个系统之间的回调请求

2)上报数格式标准化

报告数制定规范的

3)数据质量

4)实时和延时申报

5)硬件监控,如服务器的CPU、内存、网卡

6)心跳监控,时刻了解各一个机械的运转状态

7)业务层监控,涉及JVM,Nginx的连接数

2,简洁

2、监控措施

1)、采用开源和shell脚本搭建监控平台

2)、自行研发监控平台

 

第一要达到能就此,然后就尽可能精简,这样代码就非会见太差。首先你若团结扣得明白,然后是为队友看得清楚。

限流 

最主要是依据流量上报的数量做政策、调度来
进行针对性超越预想请求的处理方式,比如限流、排队齐方法;

因不同景象下不同的限流算法,可以借鉴阿里针对于用户访问、物流、交易的处理方式。

1)用户访问:采用让牌桶方式;

2)物流、交易:采用漏桶方式,平滑削峰处理;

3)购物车:采用分块网格化,单元处理

乃掌握你队友看到同样堆积烂的羁押都看无亮堂,也一致句注释都无底代码的当儿的思维阴影面积也?

策略

一言九鼎是由此提前装的系统、业务场景参数,来用于决定什么状况用啊限流措施;相对的风险的回,也是策略的要害的远在;在活动开展时,根据监察上报的流量数据,动态灵活的调整政策也是老大关键之;通过整治的素材提成一下策方案:

1)水平扩展

针对不同服务器的压力进行增减服务器个数以落实服务之压力负载均衡,这样的话对于系刚刚开始的紧缩性设计要求比较大,能够非常灵活的增长机器,来应本着流量的更动。

2)系统分组

网服务之事务不同,有先级赛之,有先级低的,那就算为不同之工作调用提前分组好之机械,这样的话在关键时刻,可以管中心工作。

3)业务降级

以一个用户请求,涉及到几近个逻辑处理,其中多可以无底,可以当高并发的情事下,可以透过开关设置,来针对未关键逻辑下进行关闭其请求,以提升了系的主业务能力。

4)开关设置

于各级一个网业务要,都增减相应的开关设置,可以实时应针对高并作状况下,根据气象实现动态调度的企图。

 

立即事实上也不曾什么,谁没有填了别人的坑呢?关键是外掌握你家在乌,而且还清楚您时常活动夜路,就问你毛骨悚然就?(卧槽,又跑题了。。)

调度

提供被官员相应的调度数据,实时呈现系统运作状态,并于主任下达仲裁指令后飞快执行策略;如何来兑现大概的方案如下:

1、建立基本数量可视化平台

2、策略规则可动态配置

3、各个业务线开关集中管理

4、自动化的脚本执行

5、运维服务之动态化管理

6、命令执行之分发协议及联合管理

 

总结

流量监控为电商平台供高速稳定之运转环境的基本,它是无时不刻的监督所有阳台的运作状态、并也负责人提供实时数据以供参考;流量监控平台被的限流只是千篇一律栽保护体制,如何承接高并发、大流量之用户要,还是用与其他平台合作,以高达让用户最的用户体验。

 

 

 

 

需要:你来一个披萨店,只售同栽披萨,代码如下:

参考自文章

腾讯轻量级全局流控方案详解

http://wetest.qq.com/lab/view/320.html?from=content\_toutiao&hmsr=toutiao.io&utm\_medium=toutiao.io&utm\_source=toutiao.io

当当网系统分级与海量信息动态发布执行

http://www.csdn.net/article/2014-11-07/2822541

披萨:

小米抢购限流峰值系统「大秒」架构解密

https://mp.weixin.qq.com/s?\_\_biz=MzAwMDU1MTE1OQ==&mid=402182304&idx=1&sn=1bd68d72e6676ff782e92b0df8b07d35&scene=1&srcid=12045k1zDgO7DLlMLwimBKjC&from=groupmessage&isappinstalled=0\#wechat\_redirect

import java.util.ArrayList;
import java.util.List;

/**
 * 披萨类
 * @author skysea
 */
public class Pizza {

    private String name;//披萨名称

    private String dough;//面团

    private String sauce;//酱料

    private List<String> toppings = new ArrayList<>();//佐料

    public Pizza() {
            this.name = "原味披萨";
            this.dough = "原味面团";
            this.sauce = "原味酱料";
    }

    void prepare() {
        System.out.println("开始准备披萨:" + name);

        System.out.println("开始处理面团:" + dough);

        System.out.println("添加酱料:" + sauce);

        System.out.println("添加佐料:");
        if(toppings.size() > 0) {
            for(String t : toppings) {
                System.out.println(" " + t);
            }
        }
    }

    void bake() {
        System.out.println("烘焙25分钟..");
    }

    void cut() {
        System.out.println("披萨切片..");
    }

    void box() {
        System.out.println("披萨打包..");
    }

    public String getName() {
        return name;
    }
}

阿里管控系统靠什么扛住大地最为要命范围的流量洪峰?

http://jm.taobao.org/2016/05/19/how-to-withstand-the-world-s-largest-traffic/?hmsr=toutiao.io&utm\_medium=toutiao.io&utm\_source=toutiao.io

 

披萨店:

/**
 * 只卖一种披萨的披萨店
 * @author skysea
 */
public class PizzaStore {

    public Pizza orderPizza() {
        Pizza pizza = new Pizza();
        pizza.prepare();
        pizza.bake();
        pizza.cut();
        pizza.box();
        return pizza;
    }
}

 测试类:

/**
 * pizza测试类
 * @author skysea
 */
public class PizzaTest {
    public static void main(String[] args) {
        PizzaStore pizzaStore = new PizzaStore();
        Pizza pizza = pizzaStore.orderPizza();
        System.out.println("当前预定的披萨:" + pizza.getName());
    }
}

图片 8 

今昔披萨店要进行业务了,因为卖同种披萨顾客既吃腻了,现在如果从头补充加新的披萨类型

简易工厂模式

Pizza类的精益求精

import java.util.ArrayList;
import java.util.List;

/**
 * 披萨抽象类
 * 1,修改private -> protected(保证子类拥有这些属性)
 * 2,将Pizza定义为abstract类,防止被new,也是为后面的改造做准备
 * @author skysea
 */
public abstract class Pizza {

    protected String name;//披萨名称

    protected String dough;//面团

    protected String sauce;//酱料

    protected List<String> toppings = new ArrayList<>();//佐料

    void prepare() {
        System.out.println("开始准备披萨:" + name);

        System.out.print("开始处理面团:" + dough);

        System.out.println("添加酱料:" + sauce);

        System.out.println("添加佐料:");
        for(String t : toppings) {
            System.out.println(" " + t);
        }
    }

    void bake() {
        System.out.println("烘焙25分钟..");
    }

    void cut() {
        System.out.println("披萨切片..");
    }

    void box() {
        System.out.println("披萨打包..");
    }

    public String getName() {
        return name;
    }

    @Override
    public String toString() {
        return "Pizza [name=" + name + ", dough=" + dough + ", sauce=" + sauce + ", toppings=" + toppings + "]";
    }
}

先行让来新增的披萨

芝士披萨:

图片 9图片 10

/**
 * 芝士披萨
 * @author skysea
 */
public class CheesePizza extends Pizza{
    public CheesePizza() {
        this.name = "芝士披萨";
        this.dough = "芝士披萨的面团";
        this.sauce = "芝士披萨的酱料";
        this.toppings.add("很多芝士....");
    }
}

View Code

蛤蜊披萨:

图片 11图片 12

/**
 * 蛤蜊披萨
 * @author skysea
 */
public class ClamPizza extends Pizza {
    public ClamPizza() {
        this.name = "蛤蜊披萨";
        this.dough = "蛤蜊披萨的面团";
        this.sauce = "蛤蜊披萨的酱料";
        this.toppings.add("蛤蜊");
    }
}

View Code

意大利烤肠披萨:

图片 13图片 14

/**
 * 意大利烤肠披萨
 * @author skysea
 */
public class PepperoniPizza extends Pizza{

    public PepperoniPizza() {
        this.name = "意大利烤肠披萨";
        this.dough = "意大利烤肠披萨的面团";
        this.sauce = "意大利烤肠披萨的酱料";
        this.toppings.add("一大波意大利烤肠...");
    }
}

View Code

 素食比萨:

图片 15图片 16

/**
 * 素食比萨
 * @author skysea
 */
public class VeggiePizza extends Pizza {
    public VeggiePizza() {
        name = "素食比萨";
        dough = "素食比萨的面团";
        sauce = "素食比萨的酱料";
        toppings.add("素食比萨");
        toppings.add("素食比萨佐料1");
        toppings.add("素食比萨佐料2");
    }
}

View Code

贴了这样多代码,先为来同波简单的贯彻:

/**
 * pizza店
 * @author skysea
 */
public class PizzaStore {

    public Pizza orderPizza(String type) {
        Pizza pizza = null;
        if (type.equals("cheese")) {
            pizza = new CheesePizza();
        } else if (type.equals("pepperoni")) {
            pizza = new PepperoniPizza();
        } else if (type.equals("clam")) {
            pizza = new ClamPizza();
        } else if (type.equals("veggie")) {
            pizza = new VeggiePizza();
        }

        pizza.prepare();
        pizza.bake();
        pizza.cut();
        pizza.box();

        return pizza;
    }

}

于匪考虑继续壮大披萨品种的下,这样的落实有没起题目,一般的话,达到了足以据此的正儿八经,但是不好用,问题如下:

1,没有兼容原来的一样种植披萨方法 public Pizza
orderPizza(),相信我,每一个public方法还是深要紧之,因为您莫明了有微微地方用到了。当然为无是不曾道知道,只是你知吧不肯定就能改,就算你能改,也无肯定改对。

2,String类型的type太爱错了,个人感觉对先后开发不自己,当然这个为要是分情况,灵活和审慎本来就很麻烦就少净

3,推荐获得不交相当的type时抛大,而未是回来空,便于排查问题(此处的if里面只是直new返回的目标,实际情形多较今底复杂性)

给来第二版:

/**
 * pizza店
 * @author skysea
 */
public class PizzaStore {

    public Pizza orderPizza() {
        return orderPizza(PizzaTypeEnum.CHEESE);
    }

    public Pizza orderPizza(PizzaTypeEnum type) {
        Pizza pizza;

        pizza = SimplePizzaFactory.getPizza(type);
        pizza.prepare();
        pizza.bake();
        pizza.cut();
        pizza.box();

        return pizza;
    }
}

SimplePizzaFactory:

/**
 * 简单工厂类
 * @author skysea
 */
public class SimplePizzaFactory {

    /**
     * 根据类型获取pizza
     * @param type
     * @return
     */
    public static final Pizza getPizza(PizzaTypeEnum type){
        switch (type) {
            case CHEESE: return new CheesePizza();
            case CLAM: return new ClamPizza();
            case PEPPERONI: return new PepperoniPizza();
            case VEGGIE: return new VeggiePizza();
            default: throw new NoSuchPizzaException(type.getCode());
        }
    }
}

辅助类(枚举,异常):

图片 17图片 18

/**
 * 定义pizza类型枚举
 * @author skysea
 *
 */
public enum PizzaTypeEnum{
    /**
     * 芝士披萨
     */
    CHEESE("cheese"),
    /**
     * 意大利烤肠披萨
     */
    PEPPERONI("pepperoni"),
    /**
     * 蛤蜊披萨
     */
    CLAM("clam"),
    /**
     * 素食比萨
     */
    VEGGIE("veggie");
    private final String code;
    PizzaTypeEnum(String code) {
        this.code = code;
    }
    public String getCode() {
        return code;
    }
}

View Code

图片 19图片 20

/**
 * 没有匹配的pizza异常
 * @author skysea
 */
public class NoSuchPizzaException extends RuntimeException{
    private static final long serialVersionUID = 6831396172306375611L;
    public NoSuchPizzaException(String message) {
        super(message);
    }
}

View Code

测试类:

/**
 * pizza测试类
 * @author skysea
 */
public class PizzaTest {

    public static void main(String[] args) {
        PizzaStore store = new PizzaStore();

        Pizza pizza = store.orderPizza(PizzaTypeEnum.CHEESE);
        System.out.println(pizza);

        pizza = store.orderPizza(PizzaTypeEnum.VEGGIE);
        System.out.println(pizza);
    }
}

图片 21

好了,代码写到此,其实对:新增披萨类型的这要求的贯彻其实已杀好了。至少来说现阶段之需实现了,其次就是是针对调用方友好,至少队友不会见挥发过来问你色传啥,不会见告知您他string字符串传错了,不会见以公转移个种类的时,还要通知他(当然是啊足以透过常量来处理)。

流产了大体上天,来说说就段代码的题目,正常状态下,需求会是这么变:

1,PepperoniPizza暂时不要了,一般的话,你问问他要是无苟,他会说,这个只要看后的营业状况(我:…)

2,你让我新加一个xx披萨

兹亟需转移之是简单个地方,一个凡是工厂类,一个凡枚举,但是要的流水线是绝不转了,如果你看还是挺辛苦在非考虑性能的情形下,你还好用反射来打,改造一下工厂类(实现通过class来创建对象)和枚举(添加一个字段来存放type对应的class)就好了,不赘述..

首先波需求便多得如此收手了,随着工作的上进,披萨店那给一个方便啊,虽然中也针对代码做了不少新的披萨,但是出于PizzaStore相当稳定,也并未发出什么坏题目。

初的问题(开分店):

1,旗舰店在芝加哥,现在如于纽约启幕平小新的宾馆

2,分店的披萨口味要依据当地的气味来拓展调,保证会不错过品牌特色的而,也能满足当地独特的风味

3,分店披萨的门类与少与洋舰店保持一致

厂子方法模式

预先管具有的披萨列出来

芝加哥底披萨:

图片 22图片 23

/**
 * 芝加哥芝士披萨
 * @author skysea
 */
public class ChicagoStyleCheesePizza extends Pizza {

    public ChicagoStyleCheesePizza() { 
        name = "芝加哥芝士披萨";
        dough = "芝加哥芝士披萨面团";
        sauce = "芝加哥芝士披萨酱料";

        toppings.add("芝加哥芝士披萨调料1");
        toppings.add("芝加哥芝士披萨调料2");
    }

    @Override
    void cut() {
        System.out.println("芝加哥芝士披萨版切片...");
    }
}
/**
 * 芝加哥蛤蜊披萨
 * @author skysea
 */
public class ChicagoStyleClamPizza extends Pizza {
    public ChicagoStyleClamPizza() {
        name = "芝加哥蛤蜊披萨";
        dough = "芝加哥蛤蜊披萨面团";
        sauce = "芝加哥蛤蜊披萨酱料";

        toppings.add("芝加哥蛤蜊披萨佐料1");
        toppings.add("芝加哥蛤蜊披萨佐料2");
    }

    @Override
    void cut() {
        System.out.println("芝加哥蛤蜊披萨版切片...");
    }
}
/**
 * 芝加哥意大利烤肠披萨
 * @author skysea
 */
public class ChicagoStylePepperoniPizza extends Pizza {
    public ChicagoStylePepperoniPizza() {
        name = "芝加哥意大利烤肠披萨";
        dough = "芝加哥意大利烤肠披萨面团";
        sauce = "芝加哥意大利烤肠披萨酱料";

        toppings.add("芝加哥意大利烤肠披萨调料1");
        toppings.add("芝加哥意大利烤肠披萨调料2");
        toppings.add("芝加哥意大利烤肠披萨调料3");
        toppings.add("芝加哥意大利烤肠披萨调料4");
    }

    @Override
    void cut() {
        System.out.println("芝加哥意大利烤肠披萨版切片...");
    }
}
/**
 * 芝加哥素食比萨
 * @author skysea
 */
public class ChicagoStyleVeggiePizza extends Pizza {
    public ChicagoStyleVeggiePizza() {
        name = "芝加哥素食比萨";
        dough = "芝加哥素食比萨的面团";
        sauce = "芝加哥素食比萨的酱料";

        toppings.add("芝加哥素食比萨调料1");
        toppings.add("芝加哥素食比萨调料2");
        toppings.add("芝加哥素食比萨调料3");
    }

    void cut() {
        System.out.println("芝加哥素食比萨版切片...");
    }
}

View Code

纽约的披萨:

图片 24图片 25

/**
 * 纽约芝士披萨
 * @author skysea
 */
public class NYStyleCheesePizza extends Pizza {

    public NYStyleCheesePizza() { 
        name = "纽约芝士披萨";
        dough = "纽约芝士披萨面团";
        sauce = "纽约芝士披萨酱料";

        toppings.add("纽约芝士披萨调料1");
        toppings.add("纽约芝士披萨调料2");
    }

    @Override
    void cut() {
        System.out.println("纽约芝士披萨版切片...");
    }
}
/**
 * 纽约蛤蜊披萨
 * @author skysea
 */
public class NYStyleClamPizza extends Pizza {
    public NYStyleClamPizza() {
        name = "纽约蛤蜊披萨";
        dough = "纽约蛤蜊披萨面团";
        sauce = "纽约蛤蜊披萨酱料";

        toppings.add("纽约蛤蜊披萨佐料1");
        toppings.add("纽约蛤蜊披萨佐料2");
    }

    @Override
    void cut() {
        System.out.println("纽约蛤蜊披萨版切片...");
    }
}
/**
 * 纽约意大利烤肠披萨
 * @author skysea
 */
public class NYStylePepperoniPizza extends Pizza {
    public NYStylePepperoniPizza() {
        name = "纽约意大利烤肠披萨";
        dough = "纽约意大利烤肠披萨面团";
        sauce = "纽约意大利烤肠披萨酱料";

        toppings.add("纽约意大利烤肠披萨调料1");
        toppings.add("纽约意大利烤肠披萨调料2");
        toppings.add("纽约意大利烤肠披萨调料3");
        toppings.add("纽约意大利烤肠披萨调料4");
    }

    @Override
    void cut() {
        System.out.println("纽约意大利烤肠披萨版切片...");
    }
}
/**
 * 纽约素食比萨
 * @author skysea
 */
public class NYStyleVeggiePizza extends Pizza {
    public NYStyleVeggiePizza() {
        name = "纽约素食比萨";
        dough = "纽约素食比萨的面团";
        sauce = "纽约素食比萨的酱料";

        toppings.add("纽约素食比萨调料1");
        toppings.add("纽约素食比萨调料2");
        toppings.add("纽约素食比萨调料3");
    }

    void cut() {
        System.out.println("纽约素食比萨版切片...");
    }
}

View Code

披萨倒是排了了,但是在其实的支出进程中,业务逻辑这么简单那是匪可能的,想如果反那什么旗舰店披萨的类名是很不便的

诚如要考虑:

1,是不是单机,有没有产生另外部系统以调用

2,改动原来的代码有什么补,更便于掌握为?迭代了几乎单本子后垃圾代码太多了吧?

3,影响挺未酷

当然,我此是以便造,你们吗,我哪怕非掌握了,嘿嘿嘿,所以遇到这种状态,一般的话要悠着点,看日子,也要扣押影响,开发就是如此,同一个成效,2天时有发生2龙的做法,5天有5上之做法,10龙来10龙之做法

披萨店改造:

/**
 * 披萨店抽象类
 * @author skysea
 */
public abstract class PizzaStore {

    abstract Pizza createPizza(String item);

    public Pizza orderPizza(String type) {
        Pizza pizza = createPizza(type);
        System.out.println("--- 制作 " + pizza.getName() + " ---");
        pizza.prepare();
        pizza.bake();
        pizza.cut();
        pizza.box();
        return pizza;
    }
}

/**
 * 芝加哥披萨店
 * @author skysea
 */
public class ChicagoPizzaStore extends PizzaStore {
    public static final String CHEESE = "cheese";
    public static final String VEGGIE = "veggie";
    public static final String CLAM = "clam";
    public static final String PEPPERONI = "pepperoni";
    Pizza createPizza(String item) {
        if (CHEESE.equals(item)) {
            return new ChicagoStyleCheesePizza();
        } else if (VEGGIE.equals(item)) {
            return new ChicagoStyleVeggiePizza();
        } else if (CLAM.equals(item)) {
            return new ChicagoStyleClamPizza();
        } else if (PEPPERONI.equals(item)) {
            return new ChicagoStylePepperoniPizza();
        } else {
            throw new NoSuchPizzaException(item);
        }
    }
}

纽约披萨店(和芝加哥披萨店几乎一毛一样,这里虽无进行了):

图片 26图片 27

/**
 * 纽约披萨店
 * @author skysea
 */
public class NYPizzaStore extends PizzaStore {

    public static final String CHEESE = "cheese";
    public static final String VEGGIE = "veggie";
    public static final String CLAM = "clam";
    public static final String PEPPERONI = "pepperoni";
    Pizza createPizza(String item) {
        if (CHEESE.equals(item)) {
            return new NYStyleCheesePizza();
        } else if (VEGGIE.equals(item)) {
            return new NYStyleVeggiePizza();
        } else if (CLAM.equals(item)) {
            return new NYStyleClamPizza();
        } else if (PEPPERONI.equals(item)) {
            return new NYStylePepperoniPizza();
        } else {
            throw new NoSuchPizzaException(item);
        }
    }
}

View Code

就段代码有三单问题使清楚掌握:

1,这个地方呢啥要干个泛类出来?

以此将要结合实际来掌握了,分店和分店里,需不需要统一规范化管理?需不需要保证自己的性状?答案肯定,都是待的

本条地方制造披萨底过程,毫无疑问是一定要一律的。就像外卖一样,下单,炒菜,配送。整套流程都是这么,不可知说你出去就起来炒菜了什么,这不得法。不雷同的地方就是,你做菜之啊菜,好不香。配送得赶紧不快,稳不妥当,服务好不好。

之所以,抽象类的意义就是是:规范、特色

2,factory咋个不见了?

因为把其跟现实的store合并在合了,这样以引申出另外一个题目:为啥要联合?因为store现在做的角色就是是facotry,刚才说了之造作过程都嵌入父类中实现了,现在单独需要在切切实实的store中失化解披萨的始建问题

3,为甚还要不用枚举了,弄个String来创造pizza?

使要单机,用枚举当然会比直接丢掉个string来得服服帖帖。

发端了分店,要是每个子公司还是同一模拟完整的劳务以戏,丢个string,要较枚举来得好。原因发生2:传输过程被的序列化和倒序列化、更加灵敏(客户端不用每次都坐是原因只要去提升对应的保险,特别是大半只版本在跑得上,升级了同时见面造成其他东西不能够玩)

测试类:

/**
 * 披萨测试类
 * @author skysea
 */
public class PizzaTest {

    public static void main(String[] args) {
        PizzaStore nyStore = new NYPizzaStore();
        PizzaStore chicagoStore = new ChicagoPizzaStore();

        Pizza pizza = nyStore.orderPizza(NYPizzaStore.CHEESE);
        System.out.println("Ethan ordered a " + pizza.getName() + "\n");

        pizza = chicagoStore.orderPizza(ChicagoPizzaStore.CHEESE);
        System.out.println("Joel ordered a " + pizza.getName() + "\n");

        pizza = nyStore.orderPizza(NYPizzaStore.CLAM);
        System.out.println("Ethan ordered a " + pizza.getName() + "\n");

        pizza = chicagoStore.orderPizza(ChicagoPizzaStore.CLAM);
        System.out.println("Joel ordered a " + pizza.getName() + "\n");

        pizza = nyStore.orderPizza(NYPizzaStore.PEPPERONI);
        System.out.println("Ethan ordered a " + pizza.getName() + "\n");

        pizza = chicagoStore.orderPizza(ChicagoPizzaStore.PEPPERONI);
        System.out.println("Joel ordered a " + pizza.getName() + "\n");

        pizza = nyStore.orderPizza(NYPizzaStore.VEGGIE);
        System.out.println("Ethan ordered a " + pizza.getName() + "\n");

        pizza = chicagoStore.orderPizza(ChicagoPizzaStore.VEGGIE);
        System.out.println("Joel ordered a " + pizza.getName() + "\n");
    }
}

结果(结果最好多矣,就不浑截图出来了):

图片 28

 

 

发表评论

电子邮件地址不会被公开。 必填项已用*标注