设计模式系列-Builder模式,工厂方法模式和抽象工厂模式

建造者的模式

定义:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示

使用场景:
1.多个部件或零件,都可以装配到一个对象中,但产生的结果又不相同时。
2.当初始化一个对象特别复杂的时候,比如参数多,而且很多参数都有默认值。

builder.png

它分为抽象建造者(Builder)角色、具体建造者(ConcreteBuilder)角色、导演者(Director)角色、产品(Product)角色四个角色。

抽象建造者(Builder)角色:给 出一个抽象接口,以规范产品对象的各个组成成分的建造。

具体建造者(ConcreteBuilder)角色:要完成的任务包括:1.实现抽象建造者Builder所声明的接口,给出一步一步地完成创建产品实例的操作。2.在建造过程完成后,提供产品的实例。

导演者(Director)角色:担任这个角色的类调用具体建造者角色以创建产品对象。

产品(Product)角色:产品便是建造中的复杂对象。

    public interface Builder {
        public Builder setName(String name);
        public Builder setSex(boolean sex);
        public Builder setAge(int age);
        public Person create();
    }

    public class ConcreteBuilder implements Builder {
        private String name;
        private boolean sex;
        private int age;
        public Builder setName(String name) {
            this.name = name;
            return this;
        }
        public Builder setSex(boolean sex) {
            this.sex = sex;
            return this;
        }
        public Builder setAge(int age) {
            this.age = age;
            return this;
        }
        public Person create() {
            return new Person(name, sex, age);
        }
    }

    public class Director {
        private Builder builder;
        public Director(Builder builder){
            this.builder = builder;
        }
        public void construct(String name, boolean sex, int age) {
            builder.setName(name);
            builder.setSex(sex);
            builder.setAge(age);
        }
    }

    public class Test {
        public static void main(String[] args) {
            Builder builder = new ConcreteBuilder();
            Director pcDirector = new Director(builder);
            pcDirector.construct("zhangtao", true, 23);
            Person person = builder.create();
        }
    }

工厂方法模式

定义:定义一个用于创建对象的接口,让子类决定实例化哪个类。

factory.png

任何需要生成复杂对象的地方,都可以使用工厂方法模式。用new就能创建的对象不需要使用工厂模式,因为使用工厂模式就要增加一个工厂类,增加了系统复杂度。

关于工厂方法模式的实现

    public abstract class Product {
        public abstract void method();
    }

    public class ConcreteProductA extends Product {
        @Override
        public void method() {
            System.out.println("产品A");
        }
    }

    public abstract class Factory {
        public abstract Product createProduct();
    }

    public class ConcreteFactory extends Factory {
        @Override
        public Product createProduct() {
            return new ConcreteProductA();
        }
    }

    public class Test {
        public static void main(String[] args) {
            Factory factory = new ConcreteFactory();
            Product product = factory.createProduct();
            product.method();
        }
    }

当确定工厂类只有一个的时候,简单工厂模式

    public class Factory{
        public static Product createProduct(){
            return new ConcreteProductA();
        }
    }

工厂方法模式VS建造者模式

工厂方法模式注重的是整体对象的创建方法,而建造者模式注重的是部件构建的过程,旨在通过一步一步地精确构造创建出一个复杂的对象。
我们举个简单例子来说明两者的差异,如要制造一个超人,如果使用工厂方法模式,直接产生出来的就是一个力大无穷、能够飞翔、内裤外穿的超人;
而如果使用建造者模式,则需要组装手、头、脚、躯干等部分,然后再把内裤外穿,于是一个超人就诞生了。

工厂方法模式创建的产品一般都是单一性质产品,如成年超人,都是一个模样,而建造者模式创建的则是一个复合产品,它由各个部件复合而成,部件不同产品对象当然不同。
这不是说工厂方法模式创建的对象简单,而是指它们的粒度大小不同。一般来说,工厂方法模式的对象粒度比较粗,建造者模式的产品对象粒度比较细。

两者的区别有了,那在具体的应用中,我们该如何选择呢?
是用工厂方法模式来创建对象,还是用建造者模式来创建对象,这完全取决于我们在做系统设计时的意图,如果需要详细关注一个产品部件的生产、安装步骤,则选择建造者,否则选择工厂方法模式。

抽象工厂模式

定义:为创建一组相关或相互依赖的对象提供一个接口,而且无须指定它们的具体类

absfactory.png
    public abstract class AbstractProductA {
         //每个产品共有的方法
         public void shareMethod(){
         }
         //每个产品相同方法,不同实现
         public abstract void doSomething();
    }

    public class ProductA1 extends AbstractProductA {
         public void doSomething() {
                 System.out.println("产品A1的实现方法");
         }
    }

    public class ProductA2 extends AbstractProductA {
         public void doSomething() {
                 System.out.println("产品A2的实现方法");
         }
    }

    //抽象工厂类
    public abstract class AbstractCreator {
         //创建A产品家族
         public abstract AbstractProductA createProductA();
         //创建B产品家族
         public abstract AbstractProductB createProductB();
    }

    public class Creator1 extends AbstractCreator {
         //只生产产品等级为1的A产品
         public AbstractProductA createProductA() {
                 return new ProductA1();
         }
         //只生产产品等级为1的B产品
         public AbstractProductB createProductB() {
                 return new ProductB1();
         }
    }

    public class Creator2 extends AbstractCreator {
         //只生产产品等级为2的A产品
         public AbstractProductA createProductA() {
                 return new ProductA2();
         }
         //只生产产品等级为2的B产品
         public AbstractProductB createProductB() {
                 return new ProductB2();
         }
    }

    public class Test {
         public static void main(String[] args) {
                 //定义出两个工厂
                 AbstractCreator creator1 = new Creator1();
                 AbstractCreator creator2 = new Creator2();
                 //产生A1对象
                 AbstractProductA a1 =  creator1.createProductA();
                 //产生A2对象
                 AbstractProductA a2 = creator2.createProductA();
                 //产生B1对象
                 AbstractProductB b1 = creator1.createProductB();
                 //产生B2对象
                 AbstractProductB b2 = creator2.createProductB();
         }
    }

抽象工厂模式的使用场景定义非常简单:一个对象族(或是一组没有任何关系的对象)都有相同的约束,则可以使用抽象工厂模式。

通过工厂类,只要知道工厂类是谁,我就能创建出一个需要的对象

注意事项:
在抽象工厂模式的缺点中,我们提到抽象工厂模式的产品族扩展比较困难,但是一定要清楚,是产品族扩展困难,而不是产品等级。
在该模式下,产品等级是非常容易扩展的,增加一个产品等级,只要增加一个工厂类负责新增加出来的产品生产任务即可。
也就是说横向扩展容易,纵向扩展困难。
抽象类AbstractCreator要增加一个方法createProductC(),然后两个实现类都要修改,想想看,这严重违反了开闭原则。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,287评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,346评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,277评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,132评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,147评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,106评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,019评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,862评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,301评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,521评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,682评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,405评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,996评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,651评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,803评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,674评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,563评论 2 352

推荐阅读更多精彩内容

  • 设计模式汇总 一、基础知识 1. 设计模式概述 定义:设计模式(Design Pattern)是一套被反复使用、多...
    MinoyJet阅读 3,937评论 1 15
  • 没有人买车会只买一个轮胎或者方向盘,大家买的都是一辆包含轮胎、方向盘和发动机等多个部件的完整汽车。如何将这些部件组...
    justCode_阅读 1,837评论 1 6
  • 创建型模式 抽象工厂模式(abstract facroty) 3.1模式动机 在工厂方法模式中具体工厂负责生产具体...
    僚机KK阅读 737评论 0 2
  • 文/小哲小诗 走过树林 那苍翠的松林 一片连成一片 近近的触动你的神经 远远的感受生命的情怀 青色的树海 你边走边...
    小哲小诗阅读 426评论 2 0
  • 老城中,藏于繁华之后的那些蜿蜒交错的胡同,不仅仅是这座城市的脉络,交通的衢道,更是老北京人生活在这的纹理。灰墙灰瓦...
    小满生活公会阅读 592评论 0 0