秋招准备-Java-设计模式(总)

11 篇文章 0 订阅
2 篇文章 0 订阅

1.单例模式

    一个类仅有一个实例,并提供它的全局访问点。

    1.饿汉单例

            线程安全,非Lazy Loading(延迟加载),类加载时就初始化。较为常用。

class Singleton
{
	private static Singleton instance = new Singleton();//初始化可以放到static{}代码块中
	private Singleton() {}
	public static Singleton getInstance()
	{	return instance;	}
}

    2.懒汉单例(非线程安全)

            由于某种执行时序下可能执行返回两个new Singleton(),因此线程不安全。实现Lazy Loading。

class Singleton
{
	private static Singleton instance =null;
	private Singleton() {}
	public static Singleton getInstance()
	{	if(instance==null)
			instance = new Singleton();
		return instance;	}
}

    3.懒汉单例(线程安全)

            通过对静态方法getInstance()添加类锁,完成同步。线程安全,实现Lazy Loading,但因为synchronized而使多线程运行时频繁阻塞,影响效率。

    4.双检锁(DCL)

            同样是添加类锁,但不对方法加锁,而使用synchronized代码块,对instance=null判断语句后的情况加类锁,然后再次进行判断(考虑到在第一个拿锁者实例化之前,其他线程进入也进入到该区域阻塞)。

    5.静态内部类实现

            写个静态内部类,在里边放个静态的外部类对象的实例。

    6.枚举enum

            支持自动序列化,线程安全,绝对防止多次实例化。

            Singleton.Instance.set(5)这样来访问单例。

enum Singleton
{
	Instance;
	
	private int value;
	public void set(int i) {value=i;}
}



2.工厂模式

    1.简单工厂(Single Factory)模式

        专门定义一个工厂类来(根据参数不同)创建其他类(产品)的实例。,被创建的实例通常拥有共同的父类。

        缺点:增添一个新的产品生成类需要改动整个工厂类

class SingleFactory
{
        public static Product createProduct(T t,……)
        {
           /**
             * Product是抽象类或者接口,含有代表其作用的抽象函数func();
             * Product1,2…是继承或者实现了Product,重写func()后的实现类,通过if-else分支来实例化与返回相应的对象
             */
           if(exp1)       return new Product1();
           else if(exp2)  return new Product2();
           else if(exp3)  return new Product3();
           ……
           //调用SingleFactory.createProduct(参数),就可以完成对应对象的实例化,用的静态方法所以也叫静态工厂
        }
}

    2.多工厂方法

        实际上是在简单工厂的基础上,将if-else的分支判断改成了多个static的方法。

        即本来应该是单个静态方法传入参数,根据参数与分支条件来判断返回哪个实例。

        现在变为多个写入多个返回不同Product子类对象的static方法,然后通过调用时选择方法来返回实例。

        这样,增添修改对应的产品类实例时,就只需要在对应的静态方法中作修改。

    3.工厂方法(Factory Method)模式

        在基类中定义创建对象的一个接口,让子类决定实例化哪个类。工厂方法让一个类的实例化延迟到子类中进行

        结构是,先定义一个工厂的接口,这个接口是需要返回产品的,接口有个抽象函数创建产品。

interface FactoryMethod
{
	public Product createProduct();
}

        然后再实现不同的子工厂类,这些工厂类重写createProduct()方法,返回相应的产品对象

class Factory1 implements FactoryMethod
{
	public Product createProduct()
	{	return new Product1();	}
}
class Factory2 implements FactoryMethod
{
	public Product createProduct()
	{	return new Product2();	}
}
……

        和简单工厂比较,其实就是将if-else分支,变成了选择工厂类。我要产生产品1,那就:

        FactoryMethod factory = new Factory1();

        Product product = factory.createProduct();

        评价:实际上和多方法工厂比较更合适,多工厂方法是在要添加修改产品类时,操作相应的静态方法。工厂方法则是操作相应的工厂类。产品类是两者都要修改的。工厂方法会在产品过多时,造成工厂类也很多的问题。

    4.抽象工厂(Abstract Factory)

        在工厂方法的基础上,由单产品系,变成了多产品系。

        可以理解为其起作用的抽象方法createProduct()变成了createSizeOne()+createSizeTwo()+……

        工厂方法的具体工厂类,本身有Product的单子类来决定。

        抽象工厂则是从ProductSize1()里选一种,再从ProductSize2()里选一种,构成具体工厂。

interface AbstractFactory
{
	public SizeOne createSizeOne();
	public SizeTwo createSizeTwo();
	……
}
class Factory1 implements AbstractFactory
{
	/**
	 * 抽象类或者接口SizeOne代表某个产品线(平板),SizeOne1(ipad2),SizeOne2(ipadmini)……是这个产品的实现
	 * 抽象类或者接口SizeTwo代表另一个产品线(手机),SizeTwo1(iphone8),SizeOne2(iphoneX)……是这个产品的实现
	 */
	public SizeOne createSizeOne()
	{	return new SizeOne1();	}
	public SizeTwo createSizeTwo()
	{	return new SizeTwo1();	}
	//那么这个具体工厂Factory就是生产SizeOne1(ipad2)与SizeTwo1(iphone8)的工厂
}



3.适配器模式

    将一个类的接口转换成客户端所需要的另一种接口。

    主要适用于“望复用一些现存的类,但接口又与复用环境要求不一致。”的情况,在遗留代码复用,类库迁移等方面有用。

    1.Adapter_Class适配器类

        通过写一个类,继承现有类且实现所需要的接口,然后在该接口含有的抽象方法中,利用现有类的方法,实现预想的功能。

    2.Adapter_Object适配器对象

        与适配器类的区别,是关系从继承变成了组合,在编写的类中,不是继承现有类,而是定义一个该类的对象,并且在构造函数或者其他中完成该对象的初始化,然后再利用该对象的方法,来完成接口抽象方法需要的功能。

    3.接口适配器模式

        当不需要全部实现接口提供的方法时,可以先设计一个抽象类实现该接口,然后在该抽象类中编写其抽象方法的默认方法(一般为空?),那么该抽象类的子类可以有选择的重写抽象类中的方法。

        在java.awt包中处理监听时运用了许多Adapter,MouseAdatper(MouseMotionAdapter)就是用到接口适配器模式的抽象类,可以继承它然后有选择的重写其中的方法,完成鼠标点击的事件监听。



4.装饰器模式

    允许向一个现有的对象添加新的功能,同时又不改变其结构。

    在JavaIO流中运用较多,如BufferedInputStream对FileInputStream的读入进行了一个缓冲优化,就是实现了装饰器模式。

    实际上,就是装饰类中应该含有被装饰类的引用,然后通过构造函数读入被装饰类的引用完成构造,再对其中的一些功能做优化。

    比如,FileInputStream类中的read()方法,不管是读入单个字节,还是读入一个byte数组的长度(或者给定length),一次read就是一次IO读入,这个操作就比较耗时。而在BufferedInputStream中,同样是通过FileInputStream对象来读入,只是它有一个内置的byte[]数组当缓冲区,那么一次read()后,先将一个默认长度的byte[]数据读入到缓冲区,然后再从缓冲区读入数据。那么在没有将缓冲区内容读完前,调用read()方法都不需要再进行IO的读写操作,因此效率得到了提高。


5.享元模式

    享元实际上是对不可变类的对象进行的一种共享模式,以获得在内存开销上的优化。

    最简单的例子就是String对象。


6.观察者模式

    ……


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值