设计模式 — 建立型模式

简介

建立型模式,就是建立对象的模式,抽象了实例化的过程。它帮助一个系统独立于如何建立、组合和表示它的那些对象。关注的是对象的建立,建立型模式将建立对象的过程进行了抽象,也能够理解为将建立对象的过程进行了封装,做为客户程序仅仅须要去使用对象,而再也不关心建立对象过程当中的逻辑html

单例模式

定义:确保一个类只有一个实例,并且自行实例化并向整个系统提供这个实例。
类图:java

clipboard.png

主要有三个部分:数据库

私有的构造方法
指向本身实例的私有静态引用
以本身实例为返回值的静态的公有的方法

特色:*
优势:编程

在内存中只有一个对象,节省内存空间。
避免频繁的建立销毁对象,能够提升性能。
避免对共享资源的多重占用。
能够全局访问。

适用场景:安全

须要频繁实例化而后销毁的对象。
建立对象时耗时过多或者耗资源过多,但又常常用到的对象。
有状态的工具类对象。
频繁访问数据库或文件的对象等等。

注意事项:多线程

只能使用单例类提供的方法获得单例对象,不要使用反射,不然将会实例化一个新对象。
不要作断开单例类对象与类中静态引用的危险操做。
多线程使用单例使用共享资源时,注意线程安全问题。

饿汉式:ide

/**
 * 一:饿汉式(类加载的时候就建立了实例)
 * 优势:实现了线程安全,编写简单;执行效率高
 * 缺点:初始化就建立了实例,对加载速度和内存有消耗,,因此这种方法要求单例对象初始化速度快且占用内存小
 */
// 一、成员变量静态化
private static Singleton3 instance = new Singleton3();
//二、构造函数私有化,防止外部实例化
private Singleton3(){}
//三、提供公共静态建立实例方法
public static Singleton3 getInstance(){
    return instance;
}

 /**
 * 二:枚举类型:根据枚举类型的特色,实现单例模式所须要的建立单例、线程安全、简洁的需求
 * 优势:实现比较简洁,保证了单实例,线程安全
 * 缺点:使用枚举类型,不是很熟悉
 */

/**
 * 枚举类型的特色:
 * 一、枚举类型 = 不可被继承的类(final):
 *      枚举本质上是经过普通类实现的,只是编译器为咱们进行了特殊处理
 *      每一个枚举类型都继承自java.lang.Enum,并自动添加了values(),valueOf()
 *      枚举类的实例 = 常量
 * 二、每一个枚举元素 = 类静态常量 = 1个实例
 *      枚举元素,都是经过静态代码来进行初始化,即在类加载期间进行初始化,保证了实例只被建立一次,线程安全
 *      获取枚举元素 = 获取实例
 * 三、构造方法 访问权限 默认=私有(private):他的构造器是私有的,底层没有可供调用的无参数的构造器;防止了其余人建立实例
 * 四、每个枚举类型&枚举变量在JVM中都是惟一的:
 *      即java在序列化和反序列化美剧时作了特殊的规定:枚举的writeObject(),readObject(),readObjectNoData()等方法是被禁用的,所以不存在序列化接口以后调用readObject会破环单例的问题
 *      保证了枚举元素的不可变行,即不能经过克隆、序列化&反序列化来复制枚举,即保证了1个枚举常量=1个实例 即单例
 */


public enum Singleton {
    INSTANCE;
    public void whateverMethod() {
    }
}

懒汉式:函数

//程序中建立类只有两种方式:1建立类的一个对象,用该对象去调用类中的方法;2使用类名直接调用类中方法,类名.方法名();单例模式防止外部new对象,只能使用类方法,且是静态的。

/**
 * 一:懒汉式(须要的时候建立实例),线程不安全。当多个线程同时访问时,不能正常工做。
 * 优势:按需加载
 * 缺点:线程不安全。多个线程同时访问时,会建立多个实例。
 */
// 一、成员变量静态化
private static Singleton1 instance;
//二、构造函数私有化,防止外部实例化
private Singleton1(){}
//三、提供公共静态建立实例方法
public static Singleton1 getInstance() {
    if (instance == null) {
        instance = new Singleton1();
    }
    return instance;
}
/**
 * 二:懒汉式:线程安全,加同步锁,
 * 优势:实现了线程安全
 * 缺点:每次访问都要进行线程同步(调用synchronized锁),形成过多的同步开销(加锁=耗时、耗能)
 */

// 一、成员变量静态化
private static Singleton1 instance;
//二、构造函数私有化,防止外部实例化
private Singleton1(){}
//三、提供公共静态建立实例方法
public static synchronized Singleton1 getInstance() {
    if (instance == null) {
        instance = new Singleton1();
    }
    return instance;
}

// 一、成员变量静态化
private static Singleton1 instance;
//二、构造函数私有化,防止外部实例化
private Singleton1(){}
//三、提供公共静态建立实例方法
public static Singleton1 getInstance() {
    synchronized(Singleton.class){
        if (instance == null) {
            instance = new Singleton1();
        }
    }
    return instance;
}


/**
 *三:懒汉式改进—双重校验锁;在同步锁的基础上,添加一层if判断,若单例已经建立,则不须要再执行加锁操做就能够获取实例,从而提升了性能。
 *优势:避免了每次调用都要调用synchronized锁,同时双重校验又保证了线程安全,不会重复建立实例。
 * 缺点:较为复杂,容易出错
 */

// 一、成员变量静态化
private static Singleton1 instance = null;
//二、构造函数私有化,防止外部实例化
private Singleton1(){}
//三、提供公共静态建立实例方法

public static Singleton1 getInstance() {
    if (instance == null) {
        synchronized (Singleton1.class) {
            if (instance == null) {
                instance = new Singleton1();
            }
        }
    }
    return instance;
}

/**
 * 四:静态内部类。在静态内部类中建立单例,在加载内部类时才会建立单例
 * 优势:根据静态内部类的特性,实现了线程安全,按需加载,同时比较简洁
 */
// 一、建立静态内部类
private static class Singleton2{
    // 静态类里面建立单例
    private static Singleton1 instance = new Singleton1();
}

//二、构造函数私有化,防止外部实例化
private Singleton1(){}

//三、提供公共静态建立实例方法
public static Singleton1 getInstance() {
    //调用静态类的实例方法
    return Singleton2.instance;
}
/**
 * 调用过程说明
 * 一、外部调用类的getInstance()方法
 * 二、getInstance()方法自动调用内部类的方法,实现初始化
 * 三、而该类在装载 & 被初始化时,会初始化他的静态域,从而建立单例
 * 四、因为是静态域,所以JVM只会加载一遍,java虚拟机保证了线程安全
 * 五、最终实现只建立一个实例。
 */

简单工厂模式

定义:又静态工厂模式,能够根据参数的不一样返回不一样类的实例。
类图:工具

clipboard.png

由此能够看出:简单工厂模式由三部分组成:具体工厂、具体产品和抽象产品性能

工厂类(Creator)角色:担任这个角色的是简单工厂模式的核心,含有与应用紧密相关的商业逻辑。工厂类在客户端的直接调用下建立产品对象,它每每由一个具体Java类实现。

抽象产品(AbstractProduct)角色:担任这个角色的类是由简单工厂模式所建立的对象的父类,或它们共同拥有的接口。抽象产品角色能够用一个Java接口或者Java抽象类实现。

具体产品(ConcreteProduct)角色:简单工厂模式所建立的任何对象都是这个角色的实例,具体产品角色由一个具体Java类实现。

总结:

简单工厂只有一个工厂类,经过switch语句来区分建立哪一个产品。
工厂方法模式是扩展了简单工厂模式,区分为抽象工厂和具体工厂实现。

工厂方法模式

定义:定义一个建立对象的工厂接口,让子类决定实例化哪个类,将实际的建立工做推迟到子类当中。

类图:

clipboard.png

工厂方法模式包含

抽象产品:通常是产品接口或者抽象产品类。主要目的是定义产品的规范,全部的产品实现都必须遵循产品接口定义的规范。产品接口是调用者最为关心的,产品接口定义的优劣直接决定了调用者代码的稳定性。
具体产品:实现产品接口的具体类,决定了产品在客户端中的具体行为。
抽象工厂:通常是工厂接口或者抽象工厂类。是工厂方法模式的核心,与调用者直接交互用来提供产品。
具体工厂:在编程中,工厂实现决定如何实例化产品,是实现扩展的途径,须要有多少种产品,就须要有多少个具体的工厂实现。

优缺点:

优势:(1)封装了建立产品的方法,用户无须关心具体实现;(2)添加新产品时,只须要添加具体产品类和具体工厂类(实现或继承抽象产品、工厂类);(3)将建立工厂方法推迟到子类当中,实现了多态。工厂方法模式也叫多态工厂模式,之因此是多态,由于全部具体工厂类都具备同一父类。
缺点:(1)在添加新产品时,须要添加具体产品类、具体工厂类。当存在较多产品时,致使产品、产品工厂类增多,必定程度上增长了系统的复杂度,更多的类须要编译和运行,给系统带来了一些额外的开销。(2) 因为考虑到系统的可扩展性,须要引入抽象层,在客户端代码中均使用抽象层进行定义,增长了系统的抽象性和理解难度,且在实现时可能须要用到DOM、反射等技术,增长了系统的实现难度。

代码举例

//一、抽象产品类
public interface Moveable {
    public void run();
}
//二、具体产品实现类
public class Car implements Moveable {
    @Override
    public void run() {
        System.out.println("小汽车!");
    }
}
public class Plane implements Moveable {
    @Override
    public void run() {
        System.out.println("大飞机!");
    }
}
//三、抽象工厂类
public abstract  class Factory {
    public abstract Moveable create();
}
//四、具体工厂实现类
public class CarFactory extends Factory {
    @Override
   public Moveable create() {
        return new Car();
    }
}
public class PlaneFactory extends Factory {
    @Override
    public Moveable create() {
        return new Plane();
    }
}
//测试类
public class FactoryTest {
    @Test
    public  void FactoryTest(){
        Factory car = new CarFactory();
        Moveable m = car.create();
//        Factory plane = new PlaneFactory();
//        Moveable m= plane.create();
        m.run();
    }
}

抽象工厂模式

定义:提供一个建立一系列相关或相互依赖对象的接口,而无需指定它们具体的类。

类图:

clipboard.png

能够看到,抽象工厂模式也是包含抽象产品、具体产品、抽象工厂、具体工厂。
可是抽象工厂中有产品等级结构和产品族的概念。

产品等级结构:产品等级结构即产品的继承结构,如一个抽象类是电视机,其子类有海尔电视机、海信电视机、TCL电视机,则抽象电视机与具体品牌的电视机之间构成了一个产品等级结构,抽象电视机是父类,而具体品牌的电视机是其子类。
产品族:在抽象工厂模式中,产品族是指由同一个工厂生产的,位于不一样产品等级结构中的一组产品,如海尔电器工厂生产的海尔电视机、海尔电冰箱,海尔电视机位于电视机产品等级结构中,海尔电冰箱位于电冰箱产品等级结构中。

和工厂方法模式的区别:
工厂方法模式提供的是一个产品等级结构的实现,抽象工厂模式提供多个不一样的产品等级结构的实现。

优缺点:

优势:能够在类的内部对产品族进行约束
缺点:产品族扩展比较麻烦。当增长新的产品时,全部的工厂类都要添加其相关代码。

代码举例:

//一、抽象产品类
public abstract class Vehicle{
    public abstract void run();
}

public abstract class Food {
    public abstract void printName();
}

public abstract class Weapon {
    public abstract void shoot();
}
//二、具体实现类
//第一个产品族
public class Car extends Vehicle {
    @Override
    public void run() {
        System.out.println("小汽车!");
    }
}
public class Apple extends Food{
    @Override
    public void printName() {
        System.out.println("红苹果");
    }
}
public class AK47 extends Weapon {
    @Override
    public void shoot() {
        System.out.println("大火球,huhuhu。。。。。。");
    }
}
//第2个产品族
public class Plane extends Vehicle {
    @Override
    public void run() {
        System.out.println("大灰机");
    }
}
public class Pizza  extends Food{
    @Override
    public void printName() {
        System.out.println("披萨");
    }
}
public class _98K extends Weapon{
    @Override
    public void shoot() {
        System.out.println("砰砰砰。。。。。。");
    }
}
//三、抽象工厂类
public  abstract class AbstractFactory {

    public abstract Vehicle createVehicle();
    public  abstract  Weapon createWeapon();
    public abstract Food createFood();
}
//四、具体工厂实现类
public class DefaultFactory extends AbstractFactory{

    @Override
    public Vehicle createVehicle() {
        return new Car();
    }

    @Override
    public Weapon createWeapon() {
        return new AK47();
    }

    @Override
    public Food createFood() {
        return new Apple();
    }
}

public class SuperFactory extends AbstractFactory{

    @Override
    public Vehicle createVehicle() {
        return new Plane();
    }

    @Override
    public Weapon createWeapon() {
        return new _98K();
    }

    @Override
    public Food createFood() {
        return new Pizza();
    }
}
//五、测试类
public class AbstractFactoryTest {
    @Test
    public void abstractFactoryTest(){
//        AbstractFactory a = new DefaultFactory();
        AbstractFactory a = new SuperFactory();
        Vehicle v= a.createVehicle();
        v.run();
        Weapon w = a.createWeapon();
        w.shoot();
        Food f= a.createFood();
        f.printName();
    }

}

总结:

建造者模式

定义:将一个复杂对象的构建与它的表示分离,使得一样的构建过程能够建立不一样的表示。

类图:

clipboard.png

建造者模式包含四个要素:

产品类:通常是一个较为复杂的对象,也就是说建立对象的过程比较复杂,通常会有比较多的代码量。在本类图中,产品类是一个具体的类,而非抽象类。实际编程中,产品类能够是由一个抽象类与它的不一样实现组成,也能够是由多个抽象类与他们的实现组成。
抽象建造者:引入抽象建造者的目的,是为了将建造的具体过程交与它的子类来实现。这样更容易扩展。通常至少会有两个抽象方法,一个用来建造产品,一个是用来返回产品。
建造者:实现抽象类的全部未实现的方法,具体来讲通常是两项任务:组建产品;返回组建好的产品。
导演类:负责调用适当的建造者来组建产品,导演类通常不与产品类发生依赖关系,与导演类直接交互的是建造者类。通常来讲,导演类被用来封装程序中易变的部分。

优缺点:
优势:

将具体的业务逻辑实现封装在了导演类中,无须知道具体产品类的结构;
当添加新的产品时,只须要实现一个新的建造者类,并添加相应的导演类实现建立具体的产品。

代码实现:

class Product {
        private String name;
        private String type;
        public void showProduct(){
            System.out.println("名称:"+name);
            System.out.println("型号:"+type);
        }
        public void setName(String name) {
            this.name = name;
        }
        public void setType(String type) {
            this.type = type;
        }
    }

    abstract class Builder {
        public abstract void setPart(String arg1, String arg2);
        public abstract Product getProduct();
    }
    class ConcreteBuilder extends Builder {
        private Product product = new Product();

        public Product getProduct() {
            return product;
        }

        public void setPart(String arg1, String arg2) {
            product.setName(arg1);
            product.setType(arg2);
        }
    }

    public class Director {
        private Builder builder = new ConcreteBuilder();
        public Product getAProduct(){
            builder.setPart("宝马汽车","X7");
            return builder.getProduct();
        }
        public Product getBProduct(){
            builder.setPart("奥迪汽车","Q5");
            return builder.getProduct();
        }
    }
    public class Client {
        public static void main(String[] args){
            Director director = new Director();
            Product product1 = director.getAProduct();
            product1.showProduct();

            Product product2 = director.getBProduct();
            product2.showProduct();
        }
    }

与工厂模式的区别:
从结构上看,建造者模式只比工厂模式多了一个“导演类”的角色,若是没有这个导演类,就相似简单工厂模式了。
工厂模式是将对象的建立过程封装在工厂类中,由工厂类向客户端提供最终的产品。
建造者模式中,建造类通常只提供产品类中各个组件的建造,而将具体的建造过程交由导演类,由导演类实现具体的产品。
因此建造者模式通常用来建立更复杂的对象。

原型模式

待续。

参考资料

http://design-patterns.readth...
https://www.w3cschool.cn/java...

相关文章
相关标签/搜索