设计模式-创建型
* [1. 单例(Singleton)](#1-单例singleton)
* [2. 简单工厂(Simple Factory)](#2-简单工厂simple-factory)
* [3. 工厂方法(Factory Method)](#3-工厂方法factory-method)
* [4. 抽象工厂(Abstract Factory)](#4-抽象工厂abstract-factory)
* [5. 生成器(Builder)](#5-生成器builder)
* [6. 原型模式(Prototype)](#6-原型模式prototype)
一,单例模式
单例模式(Singleton Pattern):主要是为了避免因为创建了多个实例造成资源的浪费,
且多个实例由于多次调用容易导致结果出现错误,而使用单例模式能够保证整个应用中有且只有一个实例。
public class App {
public static void main(String[] args) {
// 饿汉式[可用]
SingletonHungry instance = SingletonHungry.getInstance();
SingletonHungry instance2 = SingletonHungry.getSingletonHungry();
// 懒汉式[双重校验锁 推荐用]
SingletonLazy singletonLazy = SingletonLazy.getInstance();
SingletonLazy singletonLazy2 = SingletonLazy.getSingletonLazyTwo();
SingletonLazy singletonLazy3 = SingletonLazy.getSingletonLazyThree();
SingletonLazy singletonLazy4 = SingletonLazy.getSingletonLazyFour();
//内部类[推荐用]
SingletonIn singletonIn = SingletonIn.getSingletonIn();
// 枚举[推荐用]
SingletonEnum.instance.whateverMethod();
}
}
1.单例模式的饿汉式[可用]
(1)私有化该类的构造函数
(2)通过new在本类中创建一个本类对象
(3)定义一个公有的方法,将在该类中所创建的对象返回
优点:从它的实现中我们可以看到,这种方式的实现比较简单,在类加载的时候就完成了实例化,避免了线程的同步问题。
缺点:由于在类加载的时候就实例化了,所以没有达到Lazy Loading(懒加载)的效果,也就是说可能我没有用到这个实例,但是它
也会加载,会造成内存的浪费(但是这个浪费可以忽略,所以这种方式也是推荐使用的)。
public class SingletonHungry {
private SingletonHungry() {}
/**
* 1.单例模式-饿汉式[可用]
*/
private static SingletonHungry singletonHungry = new SingletonHungry();
public static SingletonHungry getInstance() {
return singletonHungry;
}
/**
* 2. 单例模式的饿汉式变换写法[可用]
* 基本没区别
*/
private static SingletonHungry singletonHungryTwo = null;
static {
singletonHungryTwo = new SingletonHungry();
}
public static SingletonHungry getSingletonHungry() {
if (singletonHungryTwo == null) {
singletonHungryTwo = new SingletonHungry();
}
return singletonHungryTwo;
}
}
2.单例模式-懒汉式
public class SingletonLazy {
private SingletonLazy() {
}
/**
* 3.单例模式的懒汉式[线程不安全,不可用]
*/
private static SingletonLazy singletonLazy;
public static SingletonLazy getInstance() {
if (singletonLazy == null) { // 这里线程是不安全的,可能得到两个不同的实例
singletonLazy = new SingletonLazy();
}
return singletonLazy;
}
/**
* 4. 懒汉式线程安全的:[线程安全,效率低不推荐使用]
* <p>
* 缺点:效率太低了,每个线程在想获得类的实例时候,执行getInstance()方法都要进行同步。
* 而其实这个方法只执行一次实例化代码就够了,
* 后面的想获得该类实例,直接return就行了。方法进行同步效率太低要改进。
*/
private static SingletonLazy singletonLazyTwo;
public static synchronized SingletonLazy getSingletonLazyTwo() {
if (singletonLazyTwo == null) { // 这里线程是不安全的,可能得到两个不同的实例
singletonLazyTwo = new SingletonLazy();
}
return singletonLazyTwo;
}
/**
* 5. 单例模式懒汉式[线程不安全,不可用]
* <p>
* 虽然加了锁,但是等到第一个线程执行完instance=new Singleton()跳出这个锁时,
* 另一个进入if语句的线程同样会实例化另外一个Singleton对象,线程不安全的原理跟3类似。
*/
private static SingletonLazy instanceThree = null;
public static SingletonLazy getSingletonLazyThree() {
if (instanceThree == null) {
synchronized (SingletonLazy.class) {// 线程不安全
instanceThree = new SingletonLazy();
}
}
return instanceThree;
}
/**
* 6.单例模式懒汉式双重校验锁[推荐用]
* 懒汉式变种,属于懒汉式的最好写法,保证了:延迟加载和线程安全
*/
private static SingletonLazy singletonLazyFour;
public static SingletonLazy getSingletonLazyFour() {
if (singletonLazyFour == null) {
synchronized (SingletonLazy.class) {
if (singletonLazyFour == null) {
singletonLazyFour = new SingletonLazy();
}
}
}
return singletonLazyFour;
}
}
3.单例模式-枚举
枚举[极推荐使用]
这里SingletonEnum.instance
这里的instance即为SingletonEnum类型的引用所以得到它就可以调用枚举中的方法了。
借助JDK1.5中添加的枚举来实现单例模式。不仅能避免多线程同步问题,而且还能防止反序列化重新创建新的对象
public enum SingletonEnum {
instance;
private SingletonEnum() {
}
public void whateverMethod() {
}
// SingletonEnum.instance.method();
}
4.单例模式-内部类
内部类[推荐用]
这种方式跟饿汉式方式采用的机制类似,但又有不同。
两者都是采用了类装载的机制来保证初始化实例时只有一个线程。
不同的地方:
在饿汉式方式是只要Singleton类被装载就会实例化,
内部类是在需要实例化时,调用getInstance方法,才会装载SingletonHolder类
优点:避免了线程不安全,延迟加载,效率高。
public class SingletonIn {
private SingletonIn() {
}
private static class SingletonInHolder {
private static SingletonIn singletonIn = new SingletonIn();
}
public static SingletonIn getSingletonIn() {
return SingletonInHolder.singletonIn;
}
}
二,工厂模式
1工厂模式-简单工厂
Product类
/**
* Created by zhxh on 2019/4/7
*/
public abstract class Product {
public void method() {
//业务逻辑处理
System.out.println("Product-->method");
}
//抽象方法
public abstract void absMethod();
}
ConcreteProduct1 类,ConcreteProduct2同样如此
/**
* Created by zhxh on 2019/4/7
*/
public class ConcreteProduct1 extends Product {
@Override
public void absMethod() {
System.out.println("ConcreteProduct1-->absMethod");
}
}
Creator 类
/**
* Created by zhxh on 2019/4/7
*/
public class Creator {
public static <T extends Product> T createProduct(Class<T> c) {
Product product = null;
try {
product = (Product) Class.forName(c.getName()).newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return (T) product;
}
}
场景类Client
/**
* Created by zhxh on 2019/4/7
* 相对于工厂方法类,去掉了继承抽象类
*/
public class Client {
public static void main(String[] args) {
Product product1 = Creator.createProduct(ConcreteProduct1.class);
product1.absMethod();
Product product2 = Creator.createProduct(ConcreteProduct2.class);
product2.method();
product2.absMethod();
}
}
2工厂模式-工厂方法
工厂方法相当于简单工厂方法,多了具体的创造类
ConcreteCreator
/**
* Created by zhxh on 2019/4/7
*/
public class ConcreteCreator extends Creator {
@Override
public <T extends Product> T createProduct(Class<T> c) {
Product product = null;
try {
product = (Product) Class.forName(c.getName()).newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return (T) product;
}
}
Creator抽象类
/**
* Created by zhxh on 2019/4/7
*/
public abstract class Creator {
public abstract <T extends Product> T createProduct(Class<T> c);
}
场景类
/**
* Created by zhxh on 2019/4/7
*/
public class Client {
public static void main(String[] args) {
Creator creator = new ConcreteCreator();
Product product1 = creator.createProduct(ConcreteProduct1.class);
product1.absMethod();
Product product2 = creator.createProduct(ConcreteProduct2.class);
product2.method();
product2.absMethod();
}
}
3工厂模式-抽象工厂
场景类:
public class Client {
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();
a1.doSomething();
a2.doSomething();
b1.doSomething();
b2.doSomething();
}
}
抽象工厂类
/*
抽象工厂类
*/
public abstract class AbstractCreator {
//创建A产品家族
public abstract AbstractProductA createProductA();
public abstract AbstractProductB createProductB();
}
/*
产品等级1的实现类
*/
public class Creator1 extends AbstractCreator {
@Override
public AbstractProductA createProductA() {
return new ProductA1();
}
@Override
public AbstractProductB createProductB() {
return new ProductB1();
}
}
3,建造者模式
建造者模式(Builder Pattern)
建造模式是对象的创建模式。建造模式可以将一个产品的内部表象(internal representation)与产品的生产过程分割开来,
从而可以使一个建造过程生成具有不同的内部表象的产品对象。
Builder 类是关键,然后定义一个Builder实现类,再之后就是处理实现类的逻辑。
优点:
- 首先,建造者模式的封装性很好。使用建造者模式可以有效的封装变化,在使用建造者模式的场景中,
一般产品类和建造者类是比较稳定的,因此,将主要的业务逻辑封装在导演类中对整体而言可以取得比较好的稳定性。 - 其次,建造者模式很容易进行扩展。如果有新的需求,通过实现一个新的建造者类就可以完成,
基本上不用修改之前已经测试通过的代码,因此也就不会对原有功能引入风险。
总结:
建造者模式与工厂模式类似,他们都是建造者模式,适用的场景也很相似。
一般来说,如果产品的建造很复杂,那么请用工厂模式;如果产品的建造更复杂,那么请用建造者模式。
抽象建造者Builder类:
/**
* Created by zhxh on 2020-01-31.
* 抽象建造者
*/
public abstract class Builder {
public abstract void setPart(String name, String type);
public abstract Product getProduct();
}
具体建造者ConcreteBuilder类:
/**
* Created by zhxh on 2020-01-31.
* 具体建造者
*/
public class ConcreteBuilder extends Builder {
private Product product = new Product();
@Override
public void setPart(String name, String type) {
product.setName(name);
product.setType(type);
}
@Override
public Product getProduct() {
return product;
}
}
产品类:
/**
* Created by zhxh on 2020-01-31.
* 产品类
*/
public class Product {
private String name;
private String type;
public void showProduct() {
Log.e("---", "名称:" + name);
Log.e("---", "型号:" + type);
}
public void setName(String name) {
this.name = name;
}
public void setType(String type) {
this.type = type;
}
}
导演类
/**
* Created by zhxh on 2020-01-31.
* 导演类
*/
public class Director {
private Builder builder = new ConcreteBuilder();
public Product getAProduct() {
builder.setPart("奥迪汽车", "Q5");
return builder.getProduct();
}
public Product getBProduct() {
builder.setPart("宝马汽车", "X7");
return builder.getProduct();
}
}
场景演示类:
public class App {
public static void main(String[] args) {
Director director = new Director();
Product product = director.getAProduct();
product.showProduct();
Director director2 = new Director();
Product product2 = director2.getBProduct();
product2.showProduct();
}
}
4,享元模式(Flyweight Pattern)
享元模式(Flyweight Pattern)
主要用于减少创建对象的数量,以减少内存占用和提高性能。
这种类型的设计模式属于结构型模式,它提供了减少对象数量从而改善应用所需的对象结构的方式。
/**
* Created by zhxh on 2020-02-01.
* 1. 创建一个接口。
*/
public interface Shape {
void draw();
}
/**
* Created by zhxh on 2020-02-01.
* 2. 创建实现接口的实体类。
*/
public class Circle implements Shape {
private String color;
private int x;
private int y;
private int radius;
public Circle(String color) {
this.color = color;
}
public void setX(int x) {
this.x = x;
}
public void setY(int y) {
this.y = y;
}
public void setRadius(int radius) {
this.radius = radius;
}
@Override
public void draw() {
Log.e("---", "Circle: Draw() [Color : " + color
+ ", x : " + x + ", y :" + y + ", radius :" + radius);
}
}
/**
* Created by zhxh on 2020-02-01.
* 3. 创建一个工厂,生成基于给定信息的实体类的对象。
*/
public class ShapeFactory {
private static final HashMap<String, Shape> circleMap = new HashMap<String, Shape>();
public static Shape getShape(String color) {
Shape shape = circleMap.get(color);
if (shape == null) {
shape = new Circle(color);
circleMap.put(color, shape);
Log.e("getShape", "Creating circle of color : " + color);
}
return shape;
}
}
场景测试类:
/*
* 享元模式(Flyweight Pattern)
* 主要用于减少创建对象的数量,以减少内存占用和提高性能。
* 这种类型的设计模式属于结构型模式,它提供了减少对象数量从而改善应用所需的对象结构的方式。
*/
public class App {
private static final String color[] = {"Red", "Blue", "Yellow", "White", "Black"};
public static void main(String[] args) {
// 4. 使用该工厂,通过传递颜色信息来获取实体类的对象。
for (int i = 0; i < 20; i++) {
Circle circle = (Circle) ShapeFactory.getShape(getRandomColor());
circle.setX(getRandomX());
circle.setY(getRandomY());
circle.setRadius(100);
circle.draw();
}
}
/**
* 0.0-1.0 * [1-6]
*/
private static String getRandomColor() {
return color[(int) (Math.random() * color.length)];
}
private static int getRandomX() {
return (int) (Math.random() * 100);
}
private static int getRandomY() {
return (int) (Math.random() * 100);
}
}