JAVA基础9(设计模式 单例模式 工厂模式 建造者模式 原型模式)
2015-08-25 20:36
676 查看
创建型模式(新建对象): 单例模式 工厂模式 抽象工厂模式 建造者模式 原型模式
结构型模式: 适配器模式 桥接模式 装饰模式 组合模式 外观模式 享元模式 代理模式
行为型模式: 模板方法模式 命令模式 迭代器模式 观察者模式 中介者模式 备忘录模式 解释器模式 状态模式 策略模式 职责链模式 访问者模式
单例模式: 保证一个类只有一个实例 并且提供一个访问该实例的全局访问点
常见的五种单例模d式实现方式:
主要:饿汉式 (线程安全 调用效率高 但是 不能延时加载)
懒汉式 (线程安全 调用效率不高 但是 可以延时加载)
其他: 双重检测锁式(由于JVM底层内部模型原因,偶尔会出问题, 不建议使用)
静态内部类式( 线程安全,调用效率高 但是可以延时加载)
枚举单例(线程安全 调用效率高 不能延时加载)
如何使用?
单例对象 占用资源少 不需要 延时加载:
枚举式 好于饿汉式
单例对象 占用资源大 需要延时加载
静态内部类式 好于 懒汉式
工厂模式:
实现了创建者和调用者的分离
详细分类: 简单工厂模式 工厂方法模式 抽象工厂模式
面向对象设计的基本原则:
OCP: 一个软件的实体应该对扩展开放, 对修改关闭
DIP:(依赖倒转原则 Dependence Inversion Principle ) 要针对接口编程,不要针对实现编程
LOD :只与你直接的朋友通信 而避免和陌生人通信
由于实现了构建和装配的解耦 不同的构建器 相同的装配 也可以做出不同的对象;实现了构建算法 装配算法的解耦,实现了更好的复用
开放中应用场景:
StringBuilder 类的append方法
sql中的PreparedStatement
JDOM中 DomBuilder ,SAXBuilder
原型模式
通过new产生一个对象需要非常繁琐的数据准备或访问权限,则可以使用原型模式
就是JAVA中的克隆技术,一某个对象为原型,复制出新的对象,新的对象具备原型对象的特点
优势有:效率高(直接克隆,避免了重新执行构造过程步骤)
克隆类似于new ,但是不同于new .new创建新的饿对象属性采用的是默认值,克隆出的对象的属性值完全和原型对象相同,并且克隆出的新对象改变不会影响原型对象。然后,在修改克隆对象的值
注意 浅克隆 和深克隆
结构型模式: 适配器模式 桥接模式 装饰模式 组合模式 外观模式 享元模式 代理模式
行为型模式: 模板方法模式 命令模式 迭代器模式 观察者模式 中介者模式 备忘录模式 解释器模式 状态模式 策略模式 职责链模式 访问者模式
单例模式: 保证一个类只有一个实例 并且提供一个访问该实例的全局访问点
常见的五种单例模d式实现方式:
主要:饿汉式 (线程安全 调用效率高 但是 不能延时加载)
懒汉式 (线程安全 调用效率不高 但是 可以延时加载)
其他: 双重检测锁式(由于JVM底层内部模型原因,偶尔会出问题, 不建议使用)
静态内部类式( 线程安全,调用效率高 但是可以延时加载)
枚举单例(线程安全 调用效率高 不能延时加载)
如何使用?
单例对象 占用资源少 不需要 延时加载:
枚举式 好于饿汉式
单例对象 占用资源大 需要延时加载
静态内部类式 好于 懒汉式
案例:测试饿汉式单例模式
<span style="font-size:14px;">public class SingletonDemo1 { //类初始化时,立即加载这个对象(没有延时加载的优势)。加载类时,天然的是线程安全的! private static SingletonDemo1 instance = new SingletonDemo1(); private SingletonDemo1(){ } //方法没有同步,调用效率高! public static SingletonDemo1 getInstance(){ return instance; } }</span>
案例: 测试懒汉式单例模式
<span style="font-size:14px;">public class SingletonDemo2 { //类初始化时,不初始化这个对象(延时加载,真正用的时候再创建)。 private static SingletonDemo2 instance; private SingletonDemo2(){ //私有化构造器 } //方法同步,调用效率低! 资源利用率高了 但是并发得同步 public static synchronized SingletonDemo2 getInstance(){ if(instance==null){ instance = new SingletonDemo2(); } return instance; } }</span>
案例: 双重检测锁实现
偶后会出问题 不建议使用<span style="font-size:14px;">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() { } }</span>
案例 静态内部类的单例模式
<span style="font-size:14px;">外部类木有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; } }</span>
案例 枚举式实现单例模式(没有延时加载)
<span style="font-size:14px;">public enum SingletonDemo5 { //这个枚举元素,本身就是单例对象! INSTANCE; //添加自己需要的操作! public void singletonOperation(){ } }</span>
案例 测试懒汉式单例模式(如何防止反射和反序列化漏洞)
<span style="font-size:14px;">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<SingletonDemo6> clazz = (Class<SingletonDemo6>) Class.forName("com.bjsxt.singleton.SingletonDemo6"); // Constructor<SingletonDemo6> 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); } }</span>
案例:测试多线程环境下五种创建单例模式的效率
<span style="font-size:14px;">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<threadNum;i++){ new Thread(new Runnable() { @Override public void run() { for(int i=0;i<1000000;i++){ // Object o = SingletonDemo4.getInstance(); Object o = SingletonDemo5.INSTANCE; } countDownLatch.countDown(); } }).start(); } countDownLatch.await(); //main线程阻塞,直到计数器变为0,才会继续往下执行! long end = System.currentTimeMillis(); System.out.println("总耗时:"+(end-start)); } }</span>
工厂模式:
实现了创建者和调用者的分离
详细分类: 简单工厂模式 工厂方法模式 抽象工厂模式
面向对象设计的基本原则:
OCP: 一个软件的实体应该对扩展开放, 对修改关闭
DIP:(依赖倒转原则 Dependence Inversion Principle ) 要针对接口编程,不要针对实现编程
LOD :只与你直接的朋友通信 而避免和陌生人通信
案例 简单工厂
<span style="font-size:14px;">简单工厂模式也叫静态工厂模式 就是工厂类一般是使用静态方法 通过接受的参数不同来放回不同的对象实例 对于增加新产品无能无力 不能修改代码的话 是无法扩展的 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; } } } </span>
案例 工厂方法模式
<span style="font-size:14px;">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(); } }</span>
案例 抽象工厂模式
<span style="font-size:14px;">增加产品族,而不是增加个别产品 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("不能按摩!"); } }</span>
案例 建造者模式
分离了对象子组件单独构造(由Builder来负责) 和装配(由Director负责) 从而可以构造出复杂的对象,这个模式适用于:某个对象的构建过程复杂的情况下使用由于实现了构建和装配的解耦 不同的构建器 相同的装配 也可以做出不同的对象;实现了构建算法 装配算法的解耦,实现了更好的复用
开放中应用场景:
StringBuilder 类的append方法
sql中的PreparedStatement
JDOM中 DomBuilder ,SAXBuilder
<span style="font-size:14px;">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(); } }</span>
原型模式
通过new产生一个对象需要非常繁琐的数据准备或访问权限,则可以使用原型模式
就是JAVA中的克隆技术,一某个对象为原型,复制出新的对象,新的对象具备原型对象的特点
优势有:效率高(直接克隆,避免了重新执行构造过程步骤)
克隆类似于new ,但是不同于new .new创建新的饿对象属性采用的是默认值,克隆出的对象的属性值完全和原型对象相同,并且克隆出的新对象改变不会影响原型对象。然后,在修改克隆对象的值
注意 浅克隆 和深克隆
案例 克隆的深浅克隆
<span style="font-size:14px;">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() { } } </span>
案例 使用序列化和反序列化实现深复制
<span style="font-size:14px;">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()); } }</span>
相关文章推荐
- java 生产者消费者问题 并发问题的解决
- java框架篇---struts之OGNL详解
- Java Servlet完全教程
- java多线程之三
- 简单原理来介绍java编程之反射
- java综合(二)springmvc与spring整合
- Java并发编程:Lock
- java成员的初始化 --thinking in java学习笔记(三)
- Java(十三)--Set的添加,删除,修改
- HBase总结(十二)Java API 与HBase交互实例
- Java String浅析
- Java通过Mathematica实现人脸识别
- Spring整合quartz实现定时任务
- Java中的HashSet和TreeSet
- java_NIO入门教程
- 从零开始学JAVA DAY6
- java--线程池
- java内存:堆、栈、常量池、方法区
- HBase总结(十一)hbase Java API 介绍及使用示例
- 解决Initializing Java Tooling 和 Initializing Java Tooling卡死问题