Java设计模式的代码演示(创建型模式)

写在前面

本篇文章通过代码演示的形式,记录创建型设计模式的相关学习总结,包括:单例模式、工厂模式(三种)、建造者模式
详细内容可参考 Java设计模式图说设计模式

一、单例模式

单例模式确保某一个类只有一个实例,并提供全局访问方法供整个系统使用该实例(类构造方法设置为私有)。
单例模式主要有以下几种写法:

1、饿汉模式

/**
 * 饿汉模式
 */
public class HungrySingleton {

    private static HungrySingleton sInstance = new HungrySingleton();

    private HungrySingleton() {}

    public static HungrySingleton getInstance() {
        return sInstance;
    }
}

避免了线程安全问题,但浪费资源(不管用没用到都会创建实例)

2、懒汉模式

/**
 * 懒汉模式
 */
public class LazySingleton {

    private static LazySingleton sInstance;

    private LazySingleton() {}

    public static synchronized LazySingleton getInstance() {
        if (sInstance == null) {
            sInstance = new LazySingleton();
        }
        return sInstance;
    }
}

时间换空间,用到时才创建,每次获取都判断实例是否已创建;通过synchronized关键字来保证线程安全,无该关键字的懒汉模式是线程不安全的
系统开销大,效率较低

3、双检锁

/**
 * 双检锁
 */
public class DoubleCheck {

    private static DoubleCheck sInstance;

    private DoubleCheck() {}

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

减少了使用锁时的系统开销,兼容性能及线程安全。JVM指令发生重排可能导致的问题这里不讨论,感兴趣的朋友请自行查询

4、静态内部类方法

/**
 * 静态内部类模式
 */
public class StaticInner {
    private static class SingletonHolder {
        private static final StaticInner sInstance = new StaticInner();
    }

    private StaticInner() {}

    public static StaticInner getInstance() {
        return SingletonHolder.sInstance;
    }
}

延迟加载不增加访问开销,同时保证线程安全

二、工厂模式

工厂模式,顾名思义就是创建一个工厂来生产产品,即实例化对象;对外封装产品细节,暴露接口供外部调用来创建实例。

1、简单工厂模式

先创建一些食物的实体类,实现Food接口,表示他们都属于Food类型

/**
 * 构建实体类
 */
public interface Food {
    void create();
}

public class Meat implements Food {

    public Meat() {}

    @Override
    public void create() {
        System.out.println("You got meat");
    }
}

public class Vegetable implements Food {

    public Vegetable() {}

    @Override
    public void create() {
        System.out.println("You got vegetable");
    }
}

public class Fruit implements Food {

    public Fruit() {}

    @Override
    public void create() {
        System.out.println("You got fruit");
    }
}

再构造一个Food的工厂,来生产Food

/**
 * 简单工厂模式
 */
public class SimpleFoodFactory {

    public static Food createFood(String type) {
        if ("meat".equals(type)) {
            return new Meat();
        } else if ("fruit".equals(type)) {
            return new Fruit();
        } else if ("vegetable".equals(type)) {
            return new Vegetable();
        }
        return null;
    }
}

这就是一个简单工厂模式的例子,通过告诉工厂需要什么样的实例类型,即可获得相应的实例对象
简单工厂模式的缺点是不方便维护,每次新增产品类型都要修改工厂类的方法,成本较高

2、工厂方法模式

依旧用上面的食物类型做例子,下面我们来看看工厂方法模式

/**
 * 工厂类实现的接口
 */
public interface IFoodMethodFactory {
    Food createFood();
}

public class MeatMethodFactory implements IFoodMethodFactory {
    @Override
    public Food createFood() {
        return new Meat();
    }
}

public class VegetablesMethodFactory implements IFoodMethodFactory {
    @Override
    public Food createFood() {
        return new Vegetable();
    }
}

public class FruitMethodFactory implements IFoodMethodFactory {
    @Override
    public Food createFood() {
        return new Fruit();
    }
}

与简单工厂模式不同的是,工厂方法模式给每个实体类型都创建了一个对应的工厂,每个工厂只生产一种产品,这样如果新增产品类型,只需要新增一个对应的工厂类即可,不必去修改原有的结构
这种模式的问题是,工程文件数和复杂度会随着实体类型的增加而不断增加

3、抽象工厂模式

再创建两个实体类

public class Apple extends Fruit {
    public Apple() {}
}

public class Banana extends Fruit {
    public Banana() {}
}

他们都是水果,我们还需要一个水果工厂来创建各种类型的水果

/**
 * 抽象工厂模式
 */
public interface IAbstractFactroy {
    Food createFoodA();
    Food createFoodB();
}

/**
 * 水果工厂,负责生产不同类型的水果
 */
public class FruitFactory implements IAbstractFactroy {
    @Override
    public Food createFoodA() {
        return new Apple();
    }

    @Override
    public Food createFoodB() {
        return new Banana();
    }
}

水果工厂生产不同类型的水果,我们还可以建造一个肉类工厂来生产各种肉食;每个工厂创建一系列有关联性的产品,这就是抽象工厂模式

三、建造者模式

建造者模式将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示,有两种写法,先来看基础的写法

/**
 * 建造者模式:生产一辆车
 */
public interface Product {
}

public class Car implements Product {
    private String mWheel;
    private String mLights;
    private String mSpeaker;

    public void setWheel(String mWheel) {
        this.mWheel = mWheel;
    }

    public void setLights(String mLights) {
        this.mLights = mLights;
    }

    public void setSpeaker(String mSpeaker) {
        this.mSpeaker = mSpeaker;
    }
}

/**
 * Builder接口
 */
public interface Builder {
    void buildWheel();
    void buildLights();
    void buildSpeaker();
    Product build();
}

/**
 * 车的建造器
 */
public class CarBuilder implements Builder {

    private Car mCar = new Car();

    @Override
    public void buildWheel() {
        mCar.setWheel("four Wheels");
    }

    @Override
    public void buildLights() {
        mCar.setLights("two Lights");
    }

    @Override
    public void buildSpeaker() {
        mCar.setSpeaker("one Speaker");
    }

    public Product build() {
        return mCar;
    }
}

/**
 * 车的组装类
 */
public class CarDirector {

    Builder mBuild;

    public CarDirector(Builder builder) {
        this.mBuild = builder;
    }

    public Product construct() {
        mBuild.buildLights();
        mBuild.buildSpeaker();
        mBuild.buildWheel();
        return mBuild.build();
    }
}

/**
 * 买车的客户
 */
public class Client {
    public static void main(String[] args) {
        System.out.println("I need a car");
        Builder builder = new CarBuilder();
        CarDirector director = new CarDirector(builder);
        Car car = (Car)director.construct();
        System.out.println("I got my car " + car);
    }
}

以上就是建造者模式的基本写法,包括4个组成部分(以下部分来源于网络):

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

在开发中我们用到更多的是建造者模式的另一种写法,即链式写法

/**
 * Builder接口
 */
public interface Builder {
    Builder buildWheel();
    Builder buildLights();
    Builder buildSpeaker();
    Product build();
}

/**
 * 车的建造器
 */
public class CarBuilder implements Builder {

    private Car mCar = new Car();

    @Override
    public CarBuilder buildWheel() {
        mCar.setWheel("four Wheels");
        return this;
    }

    @Override
    public CarBuilder buildLights() {
        mCar.setLights("two Lights");
        return this;
    }

    @Override
    public CarBuilder buildSpeaker() {
        mCar.setSpeaker("one Speaker");
        return this;
    }

    public Product build() {
        return mCar;
    }
}

/**
 * 买车的客户
 */
public class Client {
    public static void main(String[] args) {
        System.out.println("I need a car");
        Builder builder = new CarBuilder();
        Car car = (Car) builder.buildWheel()
                .buildLights()
                .buildSpeaker()
                .build();
        System.out.println("I got my car " + car);
    }
}

这种写法更加方便我们去定制想要的产品,源码中也有很多类似的用法,大家在日常开发中可以体会它的优势

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值