GOF 23设计模式之(创建型模式)

倖福魔咒の 提交于 2020-01-06 21:52:25

目录

1.单例模式

1.1饿汉模式

1.2懒汉模式

1.3其他单例模式

2.原型模式

2.1 浅克隆

2.2深克隆

3.工厂模式

3.1简单工厂模式

3.2工厂方法

4.抽象工厂模式

5.建造者模式

 

 

一、单例模式(Singleton)

  保证一个类只有一个实例,并且提供一个访问该实例的全局访问点。

  优点:由于只生成一个实例,减少了系统性能开销。可以在系统中设置全局的访问点,优化环境共享资源访问。如:可以设置一个单例类,负责所有数据表的映射处理。

 

  常见的单例模式:

    饿汉模式(线程安全,调用效率高,不能延迟加载)(主要)

    懒汉模式(线程安全,调用效率不高,可以延迟加载)(主要)

    双重检测锁(由于JVM底层内部模型原因,偶尔会出现问题,不推荐使用)

    静态内部类式(线程安全,调用效率高,可以延迟加载)

    枚举单例(线程安全,调用效率高,不能延迟加载)

 

  单例模式UML图:

  

 

  (1) 饿汉模式

    问题:如果只是加载本类、不调用本类的getInstance()方法,或永远不调用本类。就会造成资源的浪费。

class eh{
    
    //(1)直接创建私有实例对象
    private static final eh texteh = new eh();
    
    //(2)私有无参的构造函数
    private eh() {} 
    
    //(3)唯一一个公用的调用实例的方法
    public static eh getInstance() {
    
        return texteh;
    }
}
View Code

返回顶部

 

  (2) 懒汉模式

    问题:资源利用效率高了。但是,每次调用getInstance()方法都要同步,并发效率较低。

class lh{
    
    //(1)使用volatile保证所有线程安全
    private static volatile lh textlh = null;
    
    //(2)私有无参构造
    private lh() {}
    
    //(3)添加同步synchronized 
    public static synchronized lh getInstance() {
        
        //如果是第一次调用的,就创建。否则,使用原来创建的
        if(textlh == null) {
            textlh = new lh();
        }
        
        return textlh;
    }
}
View Code

返回顶部

 

  (3)其他单例模式

  双重检测锁:提高了利用效率,不必每一次都需要进行同步。只是同步第一次。其他的都不用同步。

class scjc{
    
    private static scjc jc = null;
    private scjc() {}
    
    private static scjc getInstance() {
        
        if(jc == null) {
            scjc jcs;
            synchronized (scjc.class) {
                jcs = jc;
                if(jcs == null) {
                    synchronized (scjc.class) {
                        if(jcs == null) {
                            jcs = new scjc();
                        }
                    }
                }
            }
        }
        return jc;
    }
}
View Code

 

  静态内部类:静态内部类不会立即加载,只要调用了getInstance()方法才会加载。tt的加载只会创建一次,只能被赋值一次,保证了线程的安全。兼备了高并发调用和延迟加载的优势。

class text{
    
    private static class text2{ //静态内部类
        
        private static final text tt = new text();
    }
    
    //私有无参构造
    private text() {}
    
    public static text getInstance(){
        return text2.tt;
    }
}
View Code

 

  枚举实现类式:枚举本身就是一个单例模式,有JVM的保障,避免了通过反射和反序列化的漏洞。

public enum text {

    tt; //直接调用,就可以获取单例对象
    
    //添加自己的方法
    public void getOther() {}

}

返回顶部

 

二、原型模式(Prototype)

  将一个对象作为原型,克隆复制出多个和原型类似的新实例。克隆类似于new,但是不同于new。new创建新的对象属性采用的是默认值。克隆出来的对象属性和原型的完全一样,并且改变新克隆出来的对象不会影响原型对象。克隆的实现需要实现Cloneable接口和重写clone方法。克隆出来的是一个新的对象,不是单例。

   克隆分为深克隆、浅克隆。

 

  核心角色:

    (1)抽象原型类:规定抽象原型对象必须实现的接口(Cloneable)

    (2)具体原型类:实现抽象原型类的clone方法,它是可被复制的

    (2)访问类:使用具体原型类中的clone方法来复制新的对象

 

  1、浅克隆:

    浅克隆克隆的不是全部的原型,如果原型在克隆的过程中被修改了。那么克隆的是修改后的东西

public class text implements Cloneable{
    
    private String name;

    public text(String name) {
        super();
        this.name = name;
    }
    //补全get、set方法

    @Override
    protected Object clone() throws CloneNotSupportedException {

        return (text)super.clone();//浅克隆
    }
    
    public static void main(String[] args){
        
        text tt = new text("huang");
        text clone = (text) tt.clone();//克隆
        
        tt.setName("ling"); //克隆的时候被修改了属性
        
        System.out.println(tt.getName());
        System.out.println(clone.getName());    
    }
}
View Code

 

  2、深克隆

    深克隆的是对整个对象进行克隆。就算在克隆途中改变了属性,也不会影响克隆体。

public class text implements Cloneable{
    
    private String name;
    private Date date;

    public text(String name,Date date) {
        super();
        this.name = name;
        this.date = date;
    }
    //补全get、set方法

    @Override
    protected Object clone() throws CloneNotSupportedException {
        
        Object obj = super.clone();
        text tt = (text)obj;
        
        tt.name = (String)this.name; //如果是一般数据类型。
        tt.date = (Date)this.date.clone();//其他类型

        return obj;//浅克隆
    }
    
    public static void main(String[] args) throws CloneNotSupportedException {
        
        text tt = new text("huang",new Date(2020,1,3));
        text clone = (text) tt.clone();//克隆
        
        tt.setName("ling");    //属性被修改
        tt.setDate(new Date(2020,1,2));
        
        System.out.println(tt.getName()+","+tt.getDate());
        System.out.println(clone.getName()+","+clone.getDate());    
    }
}
View Code

返回顶部

 

三、工厂模式(Factory Method)

  定义一个创建产品对象的工厂接口,将产品对象的实际创建交给具体的子类去完成。

  工厂模式分为:简单工厂模式、工厂方法模式。

 

  核心角色:

    (1)抽象工厂(Abstract Factory):提供了创建产品的接口

    (2)具体工厂(Concrete Factory):实现抽象工厂中的方法,完成具体产品的创建

    (3)抽象产品(Product):描述产品的主要特性和功能。

    (4)具体产品(Concrete Product):实现抽象产品中的接口,由具体工厂来创建。

 

  优点:

    (1)用户只需知道工厂名就可以获取产品,无需知道产品生产的过程。

    (2)添加产品时,只需要添加对应的具体产品类、具体工厂类。无需改动原工厂。满足开闭原则

 

  缺点:

    (1)每添加一个产品都要添加具体产品类和具体工厂类。增加了系统的复杂度。

 

  简单工厂方法:

  如果只要一个工厂类就可以完成的。不属于GOF的模式。

  

public class textFactory {

    public static void main(String[] args) {
        // TODO Auto-generated method stub

        //实现工厂
        Factory factory = new Factory();
        
        factory.createMD().show(); //生产美的空调
        factory.createGL().show(); //生产格力空调
    }

}


interface Product{ //定义接口
    
    public void show();
}

class md implements Product{ //实现接口的产物

    @Override
    public void show() {
        System.out.println("我是美的空调!");
    }
    
}

class gl implements Product{ //实现接口的产物

    @Override
    public void show() {
        System.out.println("我是格力空调!");
    }
    
}

class Factory{ //定义工厂类 只有一个简单的工厂
    
    public Product createMD() {//生产美的
        
        return new md();
    };
    
    public Product createGL() { //生成格力
        
        return new gl();
    }
}
View Code

返回顶部

 

  工厂方法:

  就是专门创建一个工厂类的接口,来进行工厂类的管理。

  

public class textFactory {

    public static void main(String[] args) {
        // TODO Auto-generated method stub

        //创建美的工厂
        AbstractFactory md = new ConcreateFactory1();
        md.newProduct().show(); //生产美的空调
        
        //创建格力工厂
        AbstractFactory gl = new ConcreateFactory2();
        gl.newProduct().show(); //生产格力空调
        
    }

}


interface Product{ //定义接口
    
    public void show();
}

class md implements Product{ //实现接口的产物

    @Override
    public void show() {
        System.out.println("我是美的空调!");
    }
}

class gl implements Product{ //实现接口的产物

    @Override
    public void show() {
        System.out.println("我是格力空调!");
    }
}

interface AbstractFactory{ //工厂接口类
    
    public Product newProduct();
}

//创建美的空调的工厂
class ConcreateFactory1 implements AbstractFactory{

    @Override
    public Product newProduct() {
        
        return new md();
    }
}

//创建格力空调工厂
class ConcreateFactory2 implements AbstractFactory{

    @Override
    public Product newProduct() {
        
        return new gl();
    }
}
View Code

返回顶部

 

四、抽象工厂方法(Abstract Factory)

  提供一个创建一组相关或相互依赖对象的接口,且访问类无需指定所要产品的具体类就能得到同族的不同等级的产品的模式结构。

  产品族:同一个具有工厂所生产的位于不同等级的一组产品。

 

  核心角色:

    (1)抽象工厂(Abstract Factory):创建产品的接口,可以创建多个不同等级的产品。

    (2)具体工厂(Conrete Factory):实现抽象工厂中多个抽象方法,完成具体的产品创建

    (3)抽象产品(Product):描述产品主要特性和功能,抽象工厂中有多个抽象产品

    (4)具体产品(Concrete Product):实现抽象产品定义的接口,由工厂来创建。

 

  优点:(除了工厂方法的优点外)

    (1)可以在类的内部对产品族的多等级产品共同管理,而不必引入新类来进行管理

    (2)当增加一个新的产品族时,不需要修改原代码,满足开闭原则。

 

  缺点:

    (1)当产品族中添加新的产品族时,所有的工厂类都要进行修改。

  

  

public class textFactory {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        
        //这里使用了用抽象工厂来创建不同品质等级的汽车零件。
        
        //1、生产高质量汽车零件
        AbstractFactory gzl = new gcar();//高质量汽车工厂
        gzl.newProduct1().showWK();
        gzl.newProduct2().showFDJ();
        
        //2、生产低质量汽车零件
        AbstractFactory dzl = new dcar();//低质量汽车工厂
        dzl.newProduct1().showWK();
        dzl.newProduct2().showFDJ();
        
    }
}


interface Product1{ //产品一 (生产汽车外壳)
    
    public void showWK();
}

interface Product2{//产品二 (生产汽车发动机)
    
    public void showFDJ();
}

//不同品质的成品
class gcs implements Product1{ //高品质外壳

    @Override
    public void showWK() {
        System.out.println("高质量外壳");
    }
}

class dcs implements Product1{ //低品质外壳

    @Override
    public void showWK() {
        System.out.println("低质量外壳");
    }
}

class gfdj implements Product2{    //高品质发动机

    @Override
    public void showFDJ() {
        System.out.println("高质量发动机");
    }
}

class dfdj implements Product2{ //低品质发动机

    @Override
    public void showFDJ() {
        System.out.println("低质量发动机");
    }
}


//抽象工厂
interface AbstractFactory{//需要产出的不同的品质的产品。(产品族)
    
    public Product1 newProduct1();    //生产不同品质的外壳
    public Product2 newProduct2();    //生产不同品质的发动机
}

class gcar implements AbstractFactory{//高质量汽车

    @Override
    public Product1 newProduct1() {
        return new gcs(); //高质量外壳
    }

    @Override
    public Product2 newProduct2() {
        return new gfdj(); //高质量发动机
    }
}

class dcar implements AbstractFactory{//低质量汽车

    @Override
    public Product1 newProduct1() {
        return new dcs();//低质量外壳
    }

    @Override
    public Product2 newProduct2() {
        return new dfdj(); //低质量发动机
    }
}
View Code

返回顶部

 

五、建造者(Builder)

  指将一个复杂对象的构造与它的表示分离,使同样的构建过程可以创建不同的表示。就是将对象的构建和装配进行解耦。

  

  核心角色:  

    (1)产品角色(Product):包含多个组成部件的复杂对象,由具体建造者类创建

    (2)抽象建造者(Builder):包含创建产品各个子部件的抽象方法的接口

    (3)具体建造者(Conrete Builder):实现Builder接口,完成复杂的具体部件的创建

    (4)指挥者(Director):调用建造者对象中的部件构造与装配方法完成复杂对象的创建,在指挥者中不涉及具体商品的信息。

 

  优点:

    (1)各个具体建造者互相独立,有益于系统的扩展

    (2)客户端不必知道产品内部组成的细节,便于控制细节风险

 

  缺点:

    (1)产品的组成部分必须相同,这限制了其使用范围。

    (2)如果产品的内部变化复杂,该模式会增加很多的建造者类

 

  

public class textBuilder {

    public static void main(String[] args) {
        // TODO Auto-generated method stub

        //先产出材料 (炫彩材料)
        Builder xc = new xc(); //或者换回 普通材料
        
        //指挥者进行指挥
        Director director = new Director(xc);
        
        //显示墙
        director.construct().show();
        
        
    }
}

//实体产物

class Product{
    
    private String zt;//砖头
    private String sn;//水泥

    public void setZt(String zt) {
        this.zt = zt;
    }
    public void setSn(String sn) {
        this.sn = sn;
    }

    
    //建造出来的墙
    public void show() {
        
        System.out.println("建造出来的墙:使用砖头:"+zt+";水泥:"+sn);
    }
}

//抽象建造者
abstract class Builder{
    
    //使用protected,为了可以给子类使用
    protected Product p = new Product();
    
    abstract void getzt();//给子类工厂进行修饰
    abstract void getsn();//给子类工厂进行修饰
    
    public Product getResult() {
        
        return p;
    }
}

//第一个修饰工厂
class xc extends Builder{//炫彩材料

    @Override
    void getzt() {
        p.setZt("七彩砖");
    }

    @Override
    void getsn() {
        p.setSn("混合凝土");
    }
}

class pt extends Builder{//普通材料

    @Override
    void getzt() {
        p.setZt("沙砖");
    }

    @Override
    void getsn() {
        p.setSn("单一凝土");
    }
}

//指挥者
class Director{
        
    private Builder builder;

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


    //指挥者进行指挥装配
    public Product construct() {
        
        builder.getzt();
        builder.getsn();
    
        return builder.getResult();
    }
}
View Code

返回顶部

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!