JAVA基础9(设计模式 单例模式 工厂模式 建造者模式 原型模式)

创建型模式(新建对象): 单例模式 工厂模式 抽象工厂模式 建造者模式 原型模式
结构型模式: 适配器模式 桥接模式 装饰模式 组合模式 外观模式 享元模式 代理模式
行为型模式: 模板方法模式 命令模式 迭代器模式 观察者模式 中介者模式 备忘录模式 解释器模式 状态模式 策略模式 职责链模式 访问者模式


单例模式: 保证一个类只有一个实例 并且提供一个访问该实例的全局访问点
常见的五种单例模d式实现方式:
主要:饿汉式 (线程安全 调用效率高 但是 不能延时加载)
      懒汉式  (线程安全 调用效率不高 但是 可以延时加载)
其他: 双重检测锁式(由于JVM底层内部模型原因,偶尔会出问题, 不建议使用)
       静态内部类式( 线程安全,调用效率高 但是可以延时加载)
  枚举单例(线程安全 调用效率高 不能延时加载)
 
如何使用?
 单例对象 占用资源少  不需要 延时加载:
   枚举式 好于饿汉式

  单例对象  占用资源大  需要延时加载

    静态内部类式 好于 懒汉式


案例:测试饿汉式单例模式

public class SingletonDemo1 {
	//类初始化时,立即加载这个对象(没有延时加载的优势)。加载类时,天然的是线程安全的!
	private static SingletonDemo1 instance = new SingletonDemo1();  
	private SingletonDemo1(){
	}
	//方法没有同步,调用效率高!
	public static SingletonDemo1  getInstance(){
		return instance;
	}
}


案例: 测试懒汉式单例模式

public class SingletonDemo2 {
	//类初始化时,不初始化这个对象(延时加载,真正用的时候再创建)。
	private static SingletonDemo2 instance;  
	private SingletonDemo2(){ //私有化构造器
	}
	//方法同步,调用效率低! 资源利用率高了 但是并发得同步
	public static  synchronized SingletonDemo2  getInstance(){
		if(instance==null){
			instance = new SingletonDemo2();
		}
		return instance;
	}
}

案例: 双重检测锁实现

偶后会出问题 不建议使用
public class SingletonDemo3 { 
  private static SingletonDemo3 instance = null; 
  public static SingletonDemo3 getInstance() { 
    if (instance == null) { 
      SingletonDemo3 sc; 
      synchronized (SingletonDemo3.class) { 
        sc = instance; 
        if (sc == null) { 
          synchronized (SingletonDemo3.class) { 
            if(sc == null) { 
              sc = new SingletonDemo3(); 
            } 
          } 
          instance = sc; 
        } 
      } 
    } 
    return instance; 
  } 
  private SingletonDemo3() { 
  }  
}

案例 静态内部类的单例模式

外部类木有static属性, 则不会像饿汉式那样立即加载对象
只有真正调用getInstance(),才会加载内部类,加载类时是线程安全的, instance 是static final类型,保证了内存中只有一个实例存在,而且只能被赋值一次,从而保证了线程安全
兼备了并发高校调用和延迟加载的优势

/**
 * 测试静态内部类实现单例模式
 * 这种方式:线程安全,调用效率高,并且实现了延时加载!
 * @author 尚学堂高淇 www.sxt.cn
 *
 */
public class SingletonDemo4 {
	private static class SingletonClassInstance {
		private static final SingletonDemo4 instance = new SingletonDemo4();
	}
	private SingletonDemo4(){
	}
	//方法没有同步,调用效率高!
	public static SingletonDemo4  getInstance(){
		return SingletonClassInstance.instance;
	}
}


案例 枚举式实现单例模式(没有延时加载)

public enum SingletonDemo5 {
	//这个枚举元素,本身就是单例对象!
	INSTANCE;
	//添加自己需要的操作!
	public void singletonOperation(){
	}
}


案例 测试懒汉式单例模式(如何防止反射和反序列化漏洞)

public class SingletonDemo6 implements Serializable {
	//类初始化时,不初始化这个对象(延时加载,真正用的时候再创建)。
	private static SingletonDemo6 instance;  
	
	private SingletonDemo6(){ //私有化构造器
	     //以下代码 防止 反射 来创建对象 
		if(instance!=null){
			throw new RuntimeException();
		}
	}
	
	//方法同步,调用效率低!
	public static  synchronized SingletonDemo6  getInstance(){
		if(instance==null){
			instance = new SingletonDemo6();
		}
		return instance;
	}
	//反序列化时,如果定义了readResolve()则直接返回此方法指定的对象。而不需要单独再创建新对象!
	private Object readResolve() throws ObjectStreamException {
		return instance;
	}
}

public class Client2 {
	
	public static void main(String[] args) throws Exception {
		SingletonDemo6 s1 = SingletonDemo6.getInstance();
		SingletonDemo6 s2 = SingletonDemo6.getInstance();
		
		System.out.println(s1);
		System.out.println(s2);
		
		//通过反射的方式直接调用私有构造器
//		Class clazz = (Class) Class.forName("com.bjsxt.singleton.SingletonDemo6");
//		Constructor c = clazz.getDeclaredConstructor(null);
//		c.setAccessible(true);
//		SingletonDemo6  s3 = c.newInstance();
//		SingletonDemo6  s4 = c.newInstance();
//		System.out.println(s3);
//		System.out.println(s4);
		
		//通过反序列化的方式构造多个对象 
		FileOutputStream fos = new FileOutputStream("d:/a.txt");
		ObjectOutputStream oos = new ObjectOutputStream(fos);
		oos.writeObject(s1);
		oos.close();
		fos.close();
		
		ObjectInputStream ois = new ObjectInputStream(new FileInputStream("d:/a.txt"));
		SingletonDemo6 s3 =  (SingletonDemo6) ois.readObject();
		System.out.println(s3);
	}
}


案例:测试多线程环境下五种创建单例模式的效率

public class Client3 {
	public static void main(String[] args) throws Exception {
		long start = System.currentTimeMillis();
		int threadNum = 10;
		final CountDownLatch  countDownLatch = new CountDownLatch(threadNum);
		for(int i=0;i


 工厂模式: 
 实现了创建者和调用者的分离
 详细分类: 简单工厂模式  工厂方法模式  抽象工厂模式
 面向对象设计的基本原则:
 OCP: 一个软件的实体应该对扩展开放, 对修改关闭
 DIP:(依赖倒转原则 Dependence Inversion Principle ) 要针对接口编程,不要针对实现编程
 LOD :只与你直接的朋友通信  而避免和陌生人通信

案例 简单工厂  

简单工厂模式也叫静态工厂模式 就是工厂类一般是使用静态方法 通过接受的参数不同来放回不同的对象实例
对于增加新产品无能无力 不能修改代码的话  是无法扩展的
Client02 中不必需要知道  Audi ,Byd 类的细节  
 Audi ,byd  实现了 car 接口 
public class Client02 {   //调用者
	public static void main(String[] args) {
		Car c1 =CarFactory.createCar("奥迪");
		Car c2 = CarFactory.createCar("比亚迪");
		c1.run();
		c2.run();	
	}
}
public class CarFactory {
	public static  Car createCar(String type){
		if("奥迪".equals(type)){
			return new Audi();
		}else if("比亚迪".equals(type)){
			return new Byd();
		}else{
			return null;
		}
	}
} 



案例 工厂方法模式

 Audi ,byd  实现了 car 接口  一般我们还是使用简单工厂模式
public class Client {
	public static void main(String[] args) {
		Car c1 = new AudiFactory().createCar();
		Car c2 = new BydFactory().createCar();
		c1.run();
		c2.run();
	}
}
public interface CarFactory {
	Car createCar();
}
public class AudiFactory implements CarFactory {
	@Override
	public Car createCar() {
		return new Audi();
	}
}
public class BydFactory implements CarFactory {

	@Override
	public Car createCar() {
		return new Byd();
	}
}



案例 抽象工厂模式

增加产品族,而不是增加个别产品
public class Client {
	public static void main(String[] args) {
		CarFactory  factory = new LuxuryCarFactory();
		Engine e = factory.createEngine();
		e.run();
		e.start();
	}
}

public interface CarFactory {
	Engine createEngine();
	Seat createSeat();
}


public class LowCarFactory implements CarFactory {
	@Override
	public Engine createEngine() {
		return new LowEngine();
	}
	@Override
	public Seat createSeat() {
		return new LowSeat();
	}
}

public class LuxuryCarFactory implements CarFactory {

	@Override
	public Engine createEngine() {
		return new LuxuryEngine();
	}

	@Override
	public Seat createSeat() {
		return new LuxurySeat();
	}
}


public interface Engine {
	void run();
}
class LuxuryEngine implements Engine{

	@Override
	public void run() {
		System.out.println("转的快!");
	}
}

class LowEngine implements Engine{
	
	@Override
	public void run() {
		System.out.println("转的慢!");
	}	
}
public interface Seat {
	void massage();
}

class LuxurySeat implements Seat {

	@Override
	public void massage() {
		System.out.println("可以自动按摩!");
	}
	
}
class LowSeat implements Seat {
	@Override
	public void massage() {
		System.out.println("不能按摩!");
	}
	
}


案例 建造者模式

分离了对象子组件单独构造(由Builder来负责) 和装配(由Director负责) 从而可以构造出复杂的对象,这个模式适用于:某个对象的构建过程复杂的情况下使用
由于实现了构建和装配的解耦 不同的构建器 相同的装配 也可以做出不同的对象;实现了构建算法 装配算法的解耦,实现了更好的复用
  开放中应用场景: 
   StringBuilder 类的append方法
   sql中的PreparedStatement
   JDOM中 DomBuilder ,SAXBuilder 

public class AirShip {
	
	private OrbitalModule orbitalModule;  //轨道舱
	private Engine engine; //发动机
	private EscapeTower escapeTower;  //逃逸塔
	public void launch(){
		System.out.println("发射!");
	}
	public OrbitalModule getOrbitalModule() {
		return orbitalModule;
	}
	public void setOrbitalModule(OrbitalModule orbitalModule) {
		this.orbitalModule = orbitalModule;
	}
	public Engine getEngine() {
		return engine;
	}
	public void setEngine(Engine engine) {
		this.engine = engine;
	}
	public EscapeTower getEscapeTower() {
		return escapeTower;
	}
	public void setEscapeTower(EscapeTower escapeTower) {
		this.escapeTower = escapeTower;
	}
}
class OrbitalModule{
	private String name;
	public OrbitalModule(String name) {
		this.name = name;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
}

class Engine {
	private String name;
	public Engine(String name) {
		this.name = name;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
}

class EscapeTower{
	private String name;
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public EscapeTower(String name) {
		super();
		this.name = name;
	}
}
public interface AirShipBuilder {
	Engine builderEngine();
	OrbitalModule builderOrbitalModule();
	EscapeTower  builderEscapeTower();
}
public class SxtAirShipBuilder implements AirShipBuilder {
	//StringBuilder, 以后学习XML解析中,JDOM库中的类:DomBuilder,SaxBuilder
	@Override
	public Engine builderEngine() {
		System.out.println("构建尚学堂牌发动机!");
		return new Engine("尚学堂牌发动机!");
	}

	@Override
	public EscapeTower builderEscapeTower() {
		
		System.out.println("构建逃逸塔");
		return new EscapeTower("尚学堂牌逃逸塔");
	}

	@Override
	public OrbitalModule builderOrbitalModule() {
		System.out.println("构建轨道舱");
		return new OrbitalModule("尚学堂牌轨道舱");
	}	
	
}

public interface AirShipDirector {
	
	/**
	 * 组装飞船对象
	 * @return
	 */
	AirShip   directAirShip();
	
}

public class SxtAirshipDirector implements AirShipDirector {

	private AirShipBuilder builder;

	public SxtAirshipDirector(AirShipBuilder builder) {
		this.builder = builder;
	}

	@Override
	public AirShip directAirShip() {
		Engine e = builder.builderEngine();
		OrbitalModule o = builder.builderOrbitalModule();
		EscapeTower et = builder.builderEscapeTower();
		
		//装配成飞船对象
		AirShip ship = new AirShip();
		ship.setEngine(e);
		ship.setEscapeTower(et);
		ship.setOrbitalModule(o);
		
		return ship;
	}

}
public class Client {
	public static void main(String[] args) {
		
		AirShipDirector director = new SxtAirshipDirector(new SxtAirShipBuilder());
		AirShip ship = director.directAirShip();
		System.out.println(ship.getEngine().getName());
		ship.launch();
	}
}




原型模式
  通过new产生一个对象需要非常繁琐的数据准备或访问权限,则可以使用原型模式
  就是JAVA中的克隆技术,一某个对象为原型,复制出新的对象,新的对象具备原型对象的特点
  优势有:效率高(直接克隆,避免了重新执行构造过程步骤)
  克隆类似于new ,但是不同于new .new创建新的饿对象属性采用的是默认值,克隆出的对象的属性值完全和原型对象相同,并且克隆出的新对象改变不会影响原型对象。然后,在修改克隆对象的值


注意 浅克隆 和深克隆


案例 克隆的深浅克隆

public class Sheep2 implements Cloneable {   //1997,英国的克隆羊,多利!
	private String sname;
	private Date birthday;
	@Override
	protected Object clone() throws CloneNotSupportedException {
		Object obj = super.clone();  //直接调用object对象的clone()方法!
		
		//添加如下代码实现深复制(deep Clone)
		Sheep2 s = (Sheep2) obj;
		s.birthday = (Date) this.birthday.clone();  //把属性也进行克隆!
		//添加如上代码实现深复制(deep Clone)
		return obj;
	}

	public Sheep2(String sname, Date birthday) {
		super();
		this.sname = sname;
		this.birthday = birthday;
	}
	
	public Sheep2() {
	}
}  


案例 使用序列化和反序列化实现深复制

public class Client3 {
	public static void main(String[] args) throws CloneNotSupportedException, Exception {
		Date date = new Date(12312321331L);
		Sheep s1 = new Sheep("少利",date);
		System.out.println(s1);
		System.out.println(s1.getSname());
		System.out.println(s1.getBirthday());

		
//		使用序列化和反序列化实现深复制
		ByteArrayOutputStream bos = new ByteArrayOutputStream();
		ObjectOutputStream    oos = new ObjectOutputStream(bos);
		oos.writeObject(s1);
		byte[] bytes = bos.toByteArray();
		
		ByteArrayInputStream  bis = new ByteArrayInputStream(bytes);
		ObjectInputStream	  ois = new ObjectInputStream(bis);
		
		Sheep s2 = (Sheep) ois.readObject();   //克隆好的对象!
		System.out.println("修改原型对象的属性值");  
		date.setTime(23432432423L);
		System.out.println(s1.getBirthday());
		s2.setSname("多利");
		System.out.println(s2);
		System.out.println(s2.getSname());
		System.out.println(s2.getBirthday());
		
		
	}
}

你可能感兴趣的:(javase)