****#设计模式
单例模式
概念:
1.只有一个实例
2.必须自己创建自己唯一实例
3.必须给所有其他对象提供这个实例
懒汉式
私有化构造函数,一个私有静态属性为该类的对象,一个静态方法里面new对象,判断是不是为空才new。
代码:public class Test(){
private Test(){
}
private static Test test = null;
public static Test getTest(){
if(test == null){
test = new Test();
}
return test;
}
}
如果两个线程都没有new,都判断成功,就不再是单例,所以:多线程处理
1)将get方法加上同步
public static synchronized Test getTest(){
if(test == null){
test = new Test();
}
return test;
}
每一次调用都排对之后再判断。
2)双重检查锁定
private *volatile* static Test test = null;
public static Test getTest(){
if(test == null){
synchronized(Test.class){
if(test == null){
test = new Test();
}
}
}
return test;
}
volatile保证数据是直接从内存中获取,不是从缓存中。保证多线程都是同一份,但是volatile会屏蔽一些JVM必要的优化,所以不建议采用。
3)静态内部类
public class Test(){
private Test(){
}
private static class TestHolder(){
private static test = new Test();
}
public static Test getTest(){
return TestHolder.test;
}
}
线程安全,效率高,不需要判断。(加载时会初始化静态域,所以加载就产生了对象,后面不再创建)
饿汉式
在加载类的时候就已经创建好静态对象,以后不在改变,所以是天生的线程安全的。
代码:
public class Test(){
private Test(){}
private static Test test = new Test();
public static Test getTest(){
return test;
}
}
饿汉式,懒汉式区别
1)对象生成时间:
懒汉式:调用get方法时才创建对象。
饿汉式:初始化时创建,调用get时已经存在。
2)线程安全:
懒汉式:非线程安全,在创建时考虑线程安全问题。
饿汉式:天生线程安全。
3)性能:1),2),3)
1.每次都同步,性能低。
2.做两次判断,第一次时同步。
3.不做判断,第一次调用时创建。
建造者模式
概念:
对象的创建模式。建造模式可以将一个产品的内部表象与产品的生产过程分隔开来,从而使一个建造过程生成不同内部表象的产品对象。
1.产品的内部表象
一个产品有不同的组成成分(零件),有些成分是对象,有些不是,它们通常叫做产品的内部表象。
建造者模式,使客户端不需要知道生成的产品内部信息等。
2.建造者模式的结构
例子:建造房屋
1)产品类: 房子,知道房子的属性(卧室,厨房)。
2)建造者类:工人,知道房子的每个属性的具体值(建造方式)。
3)导演类:指挥工人先建造哪个。(卧室,厨房)
即:导演指挥工人去建造产品。
3.什么时候用?
创建一些复杂对象时,对象内部的构造顺序是稳定的,但是内部构造面临复杂变化。即:产品类和导演类不变,建造者类变化。
工厂模式
问题:轻松构造对象实例,不关心构造时的细节和过程。
解决方案:建立工厂模式。
三种工厂模式
简单工厂模式,工厂方法模式,抽象工厂模式
1)简单的工厂模式
客户告诉工厂需要一辆宝马,而工厂生产车,根据是宝马还是奔驰去new对象,输出的是Car(奔驰和宝马的接口类型)。
抽象产品角色
public interface Car {
public void drive();
}
具体产品类
public class benzCar implements Car {
@Override
public void drive() {
System.out.println("驾驶奔驰车......");
}
}
public class bmwCar implements Car {
@Override
public void drive() {
System.out.println("驾驶宝马车......");
}
}
工厂类角色
public class driverFactory {
//返回类型必须为抽象产品角色
public static Car dirveCar(String params) throws Exception{
//判断逻辑,返回具体的产品角色给Client
if(params.equals("benzCar")){
return new benzCar();
}else if(params.equals("bmwCar")){
return new bmwCar();
}else{
throw new Exception();
}
}
}
客户
public class Client {
public static void main(String[] args) throws Exception {
//告诉(工厂) 需要奔驰车
Car car=driverFactory.dirveCar("benzCar");
//开车
car.drive();
}
}
缺点:每增加一种车,就要修改工厂类的业务逻辑。
工厂方法模式
简单工厂模式是把实体类抽象。
工厂方法模式是将实体类抽象和工厂类抽象,具体生产角色(生产线)都实现工厂类。用户创建工厂类型对象,调用自己想要车的生产角色对象。
增加一种车型,就增加一个生产角色类(生产线)。
缺点:有大量的流水线类。
抽象工厂模式
多个抽象流水线,每个流水线有多个实体类,多个抽象工厂类,每个工厂类有一条流水线生产多个实体类。
原型模式:克隆对象,浅度克隆,深度克隆
实现Cloneable接口 重写clone方法
浅度:不克隆其引用的其他对象。只克隆基本和String
深度:克隆所有
适配器模式
把一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起工作的两个类能够在一起工作。
一个标准接口有A方法,另一个类中有B方法,让B能够和A一起使用,即:不改变AB结构,调用B方法时可以使用和A方法同名方法去调用。
方法一:一个适配类C,有属性为B方法的所属类,实现标准接口,重写A方法,其中属性调用B方法。即:能常见C对象调用A同名方法,达到调用B的目的。
方法二:适配类C集成B的类实现A的类,重写A,其中调用this.B();
网友评论