23种设计模式(三)-对象创建

  • Factory Method 工厂方法

模式定义:
定义一个用于创建对象的接口,让子类决定实例化哪一个类。Factory Method使得一个类的实例化延迟(目的:解耦,手段:虚函数)到子类。

组件:
抽象工厂(AbstractFactory):提供了创建产品的接口,调用者通过它访问具体工厂的工厂方法 newProduct() 来创建产品。
具体工厂(ConcreteFactory):主要是实现抽象工厂中的抽象方法,完成具体产品的创建。
抽象产品(Product):定义了产品的规范,描述了产品的主要特性和功能。
具体产品(ConcreteProduct):实现了抽象产品角色所定义的接口,由具体工厂来创建,它同具体工厂之间一一对应。

类图.png
package com.lillcol.designmodel;

/**
 * @author lillcol
 * 2019/6/16-21:36
 */
public class FactoryMethod {
    public static void main(String[] args) {
        ConcreteFactory1 concreteFactory1 = new ConcreteFactory1();
        Product product = concreteFactory1.newProduct();
        product.show();
        System.out.println("-------------------------------------------");
        ConcreteFactory2 concreteFactory2 = new ConcreteFactory2();
        Product product2 = concreteFactory2.newProduct();
        product2.show();
    }
}

abstract class Product {//定义了产品的规范,描述了产品的主要特性和功能

    abstract void show();
}

class ConcreteProductA extends Product { //具体产品ProductA

    @Override
    void show() {
        System.out.println("ConcreteProductA");
    }
}

class ConcreteProductB extends Product { //具体产品ProductB

    @Override
    void show() {
        System.out.println("ConcreteProductB");
    }
}

abstract class AbstractFactory{ //提供了创建产品的抽象
    abstract Product newProduct();
}

class ConcreteFactory1 extends AbstractFactory{ //实现抽象工厂中的抽象方法,完成具体产品的创建。

    @Override
    Product newProduct() {
        return  new ConcreteProductA();
    }
}

class ConcreteFactory2 extends AbstractFactory{//实现抽象工厂中的抽象方法,完成具体产品的创建。

    @Override
    Product newProduct() {
        return  new ConcreteProductB();
    }
}
//输出结果:
ConcreteProductA
-------------------------------------------
ConcreteProductB

工厂方法模式的优点:
用户只需要知道具体工厂的名称就可得到所要的产品,无须知道产品的具体创建过程;
在系统增加新的产品时只需要添加具体产品类和对应的具体工厂类,无须对原工厂进行任何修改,满足开闭原则;

工厂方法模式的缺点:
每增加一个产品就要增加一个具体产品类和一个对应的具体工厂类,这增加了系统的复杂度。

  • AbstractFactory 抽象工厂

模式定义:
定义一个接口,让该借口负责创建一系列“相关或者相互依赖的对象”,无需指定它们具体的类。

抽象工厂模式是工厂方法模式的升级版本,工厂方法模式只生产一个等级的产品,而抽象工厂模式可生产多个等级的产品。

使用抽象工厂模式条件:
系统中有多个产品族,每个具体工厂创建同一族但属于不同等级结构的产品。
系统一次只可能消费其中某一族产品,即同族的产品一起使用。

组件:
抽象工厂(AbstractFactory):提供了创建产品的接口,它包含多个创建产品的方法 newProduct(),可以创建多个不同等级的产品。
具体工厂(ConcreteFactory):主要是实现抽象工厂中的多个抽象方法,完成具体产品的创建。
抽象产品(Product):定义了产品的规范,描述了产品的主要特性和功能,抽象工厂模式有多个抽象产品。
具体产品(ConcreteProduct):实现了抽象产品角色所定义的接口,由具体工厂来创建,它 同具体工厂之间是多对一的关系。

类图.png
package com.lillcol.designmodel;

/**
 * @author lillcol
 * 2019/6/16-22:38
 */
public class AbstractFactory {
    public static void main(String[] args) {
        ConcreteFactory1 concreteFactory1 = new ConcreteFactory1();
        concreteFactory1.newProduct1().show();
        concreteFactory1.newProduct2().show();
        System.out.println("-----------------------------------------");
        ConcreteFactory2 concreteFactory2 = new ConcreteFactory2();
        concreteFactory2.newProduct1().show();
        concreteFactory2.newProduct2().show();
    }
}
//中国 飞机:J20  航母:辽宁舰
//美国 飞机:F22  航母:福特级航母

abstract class Product1 {  //飞机
    abstract void show();
}

class ConcreteProduct11 extends Product1 {//中国飞机

    @Override
    void show() {
        System.out.println("中国 飞机:J20");
    }
}

class ConcreteProduct12 extends Product1 {//美国飞机:F22

    @Override
    void show() {
        System.out.println("美国 飞机:F22 ");
    }
}

abstract class Product2 {  //航母
    abstract void show();
}

class ConcreteProduct21 extends Product2 {//中国 航母:辽宁舰

    @Override
    void show() {
        System.out.println("中国 航母:辽宁舰");
    }
}

class ConcreteProduct22 extends Product2 {//美国 航母:福特级航母

    @Override
    void show() {
        System.out.println("美国 航母:福特级航母 ");
    }
}

abstract class Factory {
    abstract Product1 newProduct1();

    abstract Product2 newProduct2();
}
class ConcreteFactory1 extends Factory {//中国
    @Override
    Product1 newProduct1() {
        return new ConcreteProduct11();
    }

    @Override
    Product2 newProduct2() {
        return new ConcreteProduct21();
    }

}

class ConcreteFactory2 extends Factory {//美国
    @Override
    Product1 newProduct1() {
        return new ConcreteProduct12();
    }

    @Override
    Product2 newProduct2() {
        return new ConcreteProduct22();
    }

}
//输出结果:
中国 飞机:J20
中国 航母:辽宁舰
-----------------------------------------
美国 飞机:F22 
美国 航母:福特级航母 

抽象工厂模式除了具有工厂方法模式的优点外,其他主要优点如下:
可以在类的内部对产品族中相关联的多等级产品共同管理,而不必专门引入多个新的类来进行管理。
当增加一个新的产品族时不需要修改原代码,满足开闭原则。

抽象工厂模式缺点:
当产品族中需要增加一个新的产品时,所有的工厂类都需要进行修改。

  • Prototype 原型模式
    模式定义:
    使用原型实例指定创建对象的种类,然后通过拷贝这些原型来创建新的对象

原型模式组件:
抽象原型类:规定了具体原型对象必须实现的接口。
具体原型类:实现抽象原型类的 clone() 方法,它是可被复制的对象。
访问类:使用具体原型类中的 clone() 方法来复制新的对象。

类图.png
package com.lillcol.designmodel;

/**
 * @author lillcol
 * 2019/6/17-21:48
 */
public class Prototype {
    public static void main(String[] args) throws CloneNotSupportedException {
        Realizetype realizetype = new Realizetype();
        Realizetype clone = (Realizetype)realizetype.clonePrototype();
        System.out.println("realizetype==clone?  "+ (realizetype==clone));
    }
}


abstract class AbstractPrototype implements Cloneable{
    abstract Object clonePrototype() throws CloneNotSupportedException;
}
class Realizetype  extends   AbstractPrototype{
    Realizetype(){
        System.out.println("Real  King of Monkey");
    }
    Object clonePrototype() throws CloneNotSupportedException {
        System.out.println("fake King of Monkey");
        return (Realizetype)super.clone();
    }
}

//输出结果:
Real  King of Monkey
fake King of Monkey
realizetype==clone?  false

用一个已经创建的实例作为原型,通过复制该原型对象来创建一个和原型相同或相似的新对象。
在这里,原型实例指定了要创建的对象的种类。用这种方式创建对象非常高效,根本无须知道对象创建的细节。

  • Builder 构建器

模式定义:
将一个复杂对象的构建与其表示相分离,使得同样的构建过程(稳定)可以创建不同的表示(变化)。

建造者(Builder)模式组件:
产品角色(Product):它是包含多个组成部件的复杂对象,由具体建造者来创建其各个滅部件。
抽象建造者(Builder):它是一个包含创建产品各个子部件的抽象方法的接口,通常还包含一个返回复杂产品的方法 getResult()。
具体建造者(ConcreteBuilder):实现 Builder接口,完成复杂产品的各个部件的具体创建方法。
指挥者(Director):它调用建造者对象中的部件构造与装配方法完成复杂对象的创建,在指挥者中不涉及具体产品的信息。

类图.png
package com.lillcol.designmodel;

/**
 * @author lillcol
 * 2019/6/17-22:32
 */
//组装电脑
public abstract class Builder {
    Product product = new Product();

    abstract void buyKey();

    abstract void buyMouse();

    abstract Product returnComputer();
}


class ConcreteBuilder1 extends Builder {

    @Override
    void buyKey() {
        product.setKey("ConcreteBuilder1 key :双飞燕无线鼠标");
    }

    @Override
    void buyMouse() {
        product.setMouse("ConcreteBuilder1 mouse :双飞燕机械键盘");
    }

    @Override
    Product returnComputer() {
        return product;
    }
}

class ConcreteBuilder2 extends Builder {

    @Override
    void buyKey() {
        product.setKey("ConcreteBuilder1 key :无线鼠标");
    }

    @Override
    void buyMouse() {
        product.setMouse("ConcreteBuilder1 mouse :雷柏机械键盘");
    }

    @Override
    Product returnComputer() {
        return product;
    }
}

class Product {
    String key;

    String mouse;

    public void setKey(String key) {
        this.key = key;
    }

    public void setMouse(String mouse) {
        this.mouse = mouse;
    }

    public void show() {
        System.out.println(key + "    " + mouse);
    }
}

class Director {
    Builder builder;

    public Director(Builder builder) {
        this.builder = builder;
    }

    public Product construct() {
        builder.buyKey();
        builder.buyMouse();
        return builder.returnComputer();
    }

}

class BuilderTest {
    public static void main(String[] args) {
        ConcreteBuilder1 concreteBuilder1 = new ConcreteBuilder1();
        Director dirctor = new Director(concreteBuilder1);
        Product product = dirctor.construct();
        product.show();
        System.out.println("-----------------");
        ConcreteBuilder2 concreteBuilder2 = new ConcreteBuilder2();
        Director dirctor2 = new Director(concreteBuilder2);
        Product product2 = dirctor2.construct();
        product2.show();

    }
}

//输出结果:
ConcreteBuilder1 key :双飞燕无线鼠标    ConcreteBuilder1 mouse :双飞燕机械键盘
-----------------
ConcreteBuilder1 key :无线鼠标    ConcreteBuilder1 mouse :雷柏机械键盘

优点:

  1. 各个具体的建造者相互独立,有利于系统的扩展。
  2. 客户端不必知道产品内部组成的细节,便于控制细节风险。

缺点:

  1. 产品的组成部分必须相同,这限制了其使用范围。
  2. 如果产品的内部变化复杂,该模式会增加很多的建造者类。

参考文档:
http://c.biancheng.net/view/1364.html
李建忠23中设计模式

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

推荐阅读更多精彩内容