Java设计模式—单例模式,工厂模式,迭代器模式
一、单例模式
**单例模式:**保证一个类仅有一个实例,该类负责创造自己的唯一实例。这个类提供了一种访问其唯一实例的方式,可以直接访问,不需要实例化该类对象。
单例模式的特点:
(1)只有一个实例
(2)自我实例化
(3)提供全局访问点(静态方法)直接用类调用方法,便可获得该类的唯一实例
1.饿汉模式
类加载时就初始化
public class Singleton{
private static Singleton instance=new Singleton();
//让构造函数为private,这样该类就不会被实例化
private Singleton(){}
public static Singleton getInstance(){
return instance;
}
}
- 这种方式在类加载时就完成了初始化,所以类加载较慢,但获取对象的速度快。
- 这种方式基于类加载机制避免了多线程的同步问题,但是也不能确定有其他的方式(或者其他的静态方法)导致类装载,这时候初始化instance显然没有达到懒加载的效果。
2.懒汉模式(非线程安全)
public class Singleton {
private static Singleton instance;
//让构造函数为 private,这样该类就不会被实例化
private Singleton(){}
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
- 懒汉模式申明了一个静态对象,在用户第一次调用时初始化,后面的调用都返回同一个对象。虽然节约了资源,但第一次调用时需要实例化,翻反映稍慢一些,而且不是线程安全的。
3.懒汉模式(线程安全)
public class Singleton {
private static Singleton instance;
//让构造函数为 private,这样该类就不会被实例化
private Singleton(){}
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
- 线程安全的懒汉模式是线程安全的,它使用了sychronized关键字
- 每次调用getIstance方法是都需要进行线程同步,造成不必要的同步开销。而且大部分时候我们是用不到同步的,所以不建议使用这种模式。
二、工厂模式
1.简单的工厂模式
- **简单的工厂模式:**一个工厂类根据传入的参量决定创建出哪一种产品类的实例。(更多的是一种习惯)
- **应用场景:**创建一个可以绘制不同形状的绘图工具,可以绘制圆形,正方形,三角形,每个图形都会以一个draw()方法用于绘图。
- 创建过程:
编写具体的图形,每种图形都是先Shape接口
public class Rectangle implements Shape {
@Override
public void draw() {
System.out.println("Inside Rectangle::draw() method.");
}
}
public class Square implements Shape {
@Override
public void draw() {
System.out.println("Inside Square::draw() method.");
}
}
public class Circle implements Shape {
@Override
public void draw() {
System.out.println("Inside Circle::draw() method.");
}
}
- 创建一个工厂类,基于给定信息的实体类对象
public class ShapeFactory {
//使用 getShape 方法获取形状类型的对象
public static Shape getShape(String shapeType){
Shape shape = null;
if(shapeType.equalsIgnoreCase("CIRCLE")){
shape = new Circle();
} else if(shapeType.equalsIgnoreCase("RECTANGLE")){
shape = new Rectangle();
} else if(shapeType.equalsIgnoreCase("SQUARE")){
shape = new Square();
}
return shape;
}
}
- 总结
① 为所有的产品先创建一个抽象类或接口,然后通过实现抽象类或接口创建具体的产品类。
② 创建工厂类,工厂类中有一个get方法,可以通过传入的产品名称创建并返回具体的产品对象。
③ 使用时,通过调用工厂类的get方法并传入产品名称,便可以获得具体的产品对象。
2.工厂模式
- 工厂模式是简单工厂的仅一步深化,在工厂模式种,我们不再提供一个统一的工厂类来创建所有的对象,而是针对不同的对象提供不同的工厂。也就是说每个对象都有一个与之对应的工厂。
- 创建过程:
1.首先完成加载器的设计,再编写一个加载器的公共接口。
public interface Reader {
void read();
}
2.编写具体的加载类,妹子加载器都是先Reader接口
public class JpgReader implements Reader {
@Override
public void read() {
System.out.print("read jpg");
}
}
public class PngReader implements Reader {
@Override
public void read() {
System.out.print("read png");
}
}
public class GifReader implements Reader {
@Override
public void read() {
System.out.print("read gif");
}
}
3.定义一个抽象的工厂接口ReaderFactory
public interface ReaderFactory {
Reader getReader();
}
4.里面有一个getReader()方法返回我们的Reader来,为定义好的每个加载器都提供一个工厂类,这些工厂类实现了ReaderFactory
public class JpgReaderFactory implements ReaderFactory {
@Override
public Reader getReader() {
return new JpgReader();
}
}
public class PngReaderFactory implements ReaderFactory {
@Override
public Reader getReader() {
return new PngReader();
}
}
public class GifReaderFactory implements ReaderFactory {
@Override
public Reader getReader() {
return new GifReader();
}
}
- 总结
1.为所有的产品先创建一个抽象类或接口,然后通过实现抽象类或接口创建具体的产品类。
2.创建一个抽象的工厂类或者工厂接口,它里面有一个get方法。然后通过实现抽象的工厂类或工厂接口,针对每一种产品创建对应的工厂类。
3.使用时,通过创建产品对应的工厂类实例,调用get方法便可以获取具体的产品对象。
3.抽象工厂模式
抽象工厂模式: 是工厂方法的仅一步深化,在这个模式中的工厂类不单单可以创建一个对象,而是可以创建一组对象。这是和工厂方法最大的不同点
此模式不再做介绍了。。。
三、迭代器模式
迭代器模式提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露其内部的表示。
迭代器模式把游走的任务放在迭代器上,而不是聚合上。这样简化了聚合的接口和实现,也可以让责任各得其所。
迭代器模式的构成与使用
(1)迭代器角色(Iterator):定义遍历元素所需要的方法,一般来说会有这么三个方法:next()方法取到当前的元素的方法并且移动到下一个元素的位置,hasNext()方法:判断是否遍历结束的方法),remove()方法:移出当前对象的方法,
(2)具体迭代器角色(Concrete Iterator):实现迭代器接口中定义的方法,完成集合的迭代。ArrayList中的Itr
(3)容器角色(Aggregate): 一般是一个接口,提供一个iterator()方法,例如java中的Collection接口,List接口,Set接口等
(4)具体容器角色(ConcreteAggregate):就是抽象容器的具体实现类,比如List接口的有序列表实现ArrayList,List接口的链表实现LinkList,Set接口的哈希列表的实现HashSet等。ArrayList
使用方式:(1)首先得有聚合对象(2)迭代器角色(具体迭代器角色)