JAVA设计模式之单例模式,工厂模式,迭代器模式
一,单例模式
单例模式保证一个类只有一个实例,该类负责创造自己的唯一实例。这个类提供了一种访问其唯一实例的方式,可以直接访问,不需要实例化该对象
单例模式的特点:
1.只有一个实例(构造函数私有)
2.自我实例化
3.类内部自己实例化唯一实例
1.饿汉模式
public class Singleton{
private static final Singleton instance=new Singleton();
//让构造函数为private,这样该类就不会被实例化
private Singleton(){}
public static Singleton getInstance(){
return instance;
}
}
特点:
1.线程安全(类加载保证)
2.类加载过程完成初始化,所以类加载过程慢一些,但获取对象速度较快
2.懒汉模式(非线程安全)
//懒汉式单例类.在第一次调用的时候实例化自己
public class Singleton {
private Singleton() {}
private static Singleton single=null;
//静态工厂方法
public static Singleton getInstance() {
if (single == null) {
single = new Singleton();
}
return single;
}
}
特点:
1.线程不安全
2.第一次调用的时候实例化对象,速度慢但节省资源
3.懒汉模式(线程安全)
1.在getInstance方法上加同步
public static synchronized Singleton getInstance() {
if (single == null) {
single = new Singleton();
}
return single;
}
二,双重锁检查锁定,效率更高
public static Singleton getInstance() {
if (singleton == null) {
synchronized (Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
三,静态内部类
这种方法比12都好些,即实现了线程安全,又避免了同步带来的影响
public static Singleton getInstance() {
if (singleton == null) {
synchronized (Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
二,工厂模式
1.简单工厂模式
一个工厂根据数据传入的参量决定创建出那一种产品类的实例
Phone类:手机标准规范类(AbstractProduct)
public interface Phone {
void make();
}
制造小米手机与苹果手机
public class MiPhone implements Phone {
public MiPhone() {
this.make();
}
@Override
public void make() {
// TODO Auto-generated method stub
System.out.println("make xiaomi phone!");
}
}
public class MiPhone implements Phone {
public MiPhone() {
this.make();
}
@Override
public void make() {
// TODO Auto-generated method stub
System.out.println("make xiaomi phone!");
}
}
PhoneFactory类:手机代工厂(Factory)
public class PhoneFactory {
public Phone makePhone(String phoneType) {
if(phoneType.equalsIgnoreCase("MiPhone")){
return new MiPhone();
}
else if(phoneType.equalsIgnoreCase("iPhone")) {
return new IPhone();
}
return null;
}
}
演示
public class Demo {
public static void main(String[] arg) {
PhoneFactory factory = new PhoneFactory();
Phone miPhone = factory.makePhone("MiPhone"); // make xiaomi phone!
IPhone iPhone = (IPhone)factory.makePhone("iPhone"); // make iphone!
}
}
优点:实现对象的创建和对象使用分离
客户端程序员不关心怎么创建,只关心怎么使用
缺点:工厂类不够灵活,
新增一个产品,就要修改工厂类
总结
① 为所有的产品先创建一个抽象类或接口,然后通过实现抽象类或接口创建具体的产品类。
② 创建工厂类,工厂类中有一个x方法,可以通过传入的产品名称创建并返回具体的产品对象。
③ 使用时,通过调用工厂类的x方法并传入产品名称,便可以获得具体的产品对象。
2.工厂模式
1.工厂模式是简单工厂模式的进一步深化,在工厂模式中,我们不再提供一个统一的工厂类来创建所有对象,
而是针对不同对象提供不同的工厂。也就是说每个对象都有一个对应的工厂。
创建过程:
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来,为定义好的每个加载器都提供一个工厂类,这些工厂类实现了ReaderFactor
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.抽象工厂模式
抽象工厂模式
抽象工厂模式: 是工厂方法的仅一步深化,在这个模式中的工厂类不单单可以创建一个对象,而是可以创建一组对象。这是和工厂方法最大的不同点
//抽象工厂
interface AbstractFactory{
Phone createPhone(string param);
Hask createNask(String param);
}
//具体工厂
class superFactory implements AbstractFactory{
override
public Phone createPhone(string param) {
return new iPhone(;
}
override
public Mask createHask(String param) {
//产品大类-手机
interface Phone{ }
class iPhone implements Phone{ }
override
public Phone createPhone(string param) {
return new iPhone(;
}
//产品大类---口罩
interface Mask{ }
class N95 implements Mask{ }
三,迭代器模式
定义:提供一种方法访问一个容器中的各个元素,而又不暴露该对象的内部细节
类型:行为类模式
类图:
java使用最多的一种模式,迭代器模式
迭代器模式的结构:
1.抽象容器:一般是一个接口,提供一个Iteator方法,例如
Collection接口,set,map接口等。
Iterator<E> iterator();
2.具体容器:就是抽象容器的具体实现类,比如List接口ArrayList,LinkList,HashSet
public Iterator<E> iterator() {
return new Itr();
}
3.抽象迭代器:定义遍历元素所需要的方法,获、next()
has next()
public interface Iterator<E> {
4.迭代器实现:实现迭代器接口中定义的方法,完成集合的迭代。
private class Itr implements Iterator<E> {
int cursor; // index of next element to return
int lastRet = -1; // index of last element returned; -1 if no such
int expectedModCount = modCount;
Itr() {}
public boolean hasNext() {
return cursor != size;
}
@SuppressWarnings("unchecked")
public E
迭代器的优缺点:
1.简化了遍历方式,对于对像集合的遍历,还是比较麻烦的。内部结构不一样,引入迭代器就简单多了。
2.可以提供多种遍历方式。
比如说对有序列表,我们可以根据需要提供正序遍历,倒序遍历两种迭代器,用户用起来只需要得到我们实现好的迭代器,就可以方便的对集合进行遍历了。
3.封装性良好,用户只需要得到迭代器就可以遍历,而对于遍历算法则不用去关心。
缺点:
对于比较简单的遍历(像数组或者有序列表),使用迭代器方式遍历较为繁琐,大家可能都有感觉,像ArrayList,我们宁可愿意使用for循环和get方法来遍历集合。
迭代器模式的适用场景
迭代器模式是与集合共生共死的,一般来说,我们只要实现一个集合,就需要同时提供这个集合的迭代器,就像java中的Collection,List、Set、Map等,这些集合都有自己的迭代器。假如我们要实现一个这样的新的容器,当然也需要引入迭代器模式,给我们的容器实现一个迭代器。
但是,由于容器与迭代器的关系太密切了,所以大多数语言在实现容器的时候都给提供了迭代器,并且这些语言提供的容器和迭代器在绝大多数情况下就可以满足我们的需要,所以现在需要我们自己去实践迭代器模式的场景还是比较少见的,我们只需要使用语言中已有的容器和迭代器就可以了。