设计模式读书笔记

这段时间学习了一下软件开发中的设计模式,这篇读书笔记就谈谈我对设计模式的理解。java

设计模式不是一套api,而是一种可复用的、通常性的解决方式,相似于之前谈过的MSF,其官方定义以下:设计模式(design pattern)是软件开发人员在软件开发过程当中面临的通常问题的解决方案。设计模式的提出自己是基于面向对象的语言的,没有了面向对象的继承与多态,全部设计模式都玩不转了。设计模式分为三大类,建立型、结构型、行为型,此次就主要谈谈建立型设计模式。程序员

首先是最多见的工厂模式,官方的说法是:定义一个建立对象的接口,让其子类本身决定实例化哪个工厂类,工厂模式使其建立过程延迟到子类进行。这句话真的很难懂,因此不如举个例子,到汽车厂提车,不管宝马、奥迪仍是奥拓只要提就好了,没必要管具体的制造细节。这样的说法感受清晰了些,能够看出工厂模式提供了必定程度上的封装,但具体它要实现怎样的目的呢?放一段Java源码:设计模式

public interface Shape {
   void draw();
}

public class Rectangle implements Shape {

   @Override
   public void draw() {
      System.out.println("Inside Rectangle::draw() method.");
   }
}

public class Square implements Shape {

   @Override
   public void draw() {
      System.out.println("Inside Square::draw() method.");
   }
}

public class Circle implements Shape {

   @Override
   public void draw() {
      System.out.println("Inside Circle::draw() method.");
   }
}

public class ShapeFactory {

   public Shape getShape(String shapeType){
      if(shapeType == null){
         return null;
      }        
      if(shapeType.equalsIgnoreCase("CIRCLE")){
         return new Circle();
      } else if(shapeType.equalsIgnoreCase("RECTANGLE")){
         return new Rectangle();
      } else if(shapeType.equalsIgnoreCase("SQUARE")){
         return new Square();
      }
      return null;
   }
}

 

这样一切都清晰了,用我本身的话说,工厂模式实现的是对一类产品族的封装。其实你们多少都用过工厂模式,当初学习C++虚基类以及Java接口的时候,确定尝试过经过一个抽象类实现各类相应的实体类,这个过程其实即便工厂模式的核心,即基于接口与实现技术,对于C++也能够说是虚基类与继承技术。要说工厂模式比咱们原来写的东西多了什么,就是最后的 ShapeFactory 类以及其 getShape 方法,我相信当初大部分人都不会使用这种写法,但仔细一下这种方式实现了对上层很是干净的封装,对于用户来讲不再须要想着new一个什么样的对象,须要的只是产生一个 ShapeFactory 对象,而后从中 getShape 获得想要的对象,即只要走进汽车工厂就能够取到各类各样的车。api

有句题外话,就是我在看工厂模式的过程当中忽然模糊了Java中虚基类与接口的区别,查了查才想起来虚基类的部分函数是已经实现了的,子类只需实现那些没有实现的类,而接口的函数所有都是虚函数,实现类必须实现其中所有的函数。安全

 

下面看看单例模式,这种模式要求该类本身负责建立本身,且需确保只有单个对象被建立。为了确保该类不会被实例化,有种骚操做就是把构造函数设为 private ,这样若是该类被 new 则编译器报错,这种操做真的是长见识。具体的单例模式代码还分为懒汉模式和饿汉模式。多线程

懒汉模式:ide

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

 

其中 synchronized 关键字是为了保证线程安全,即多线程访问时给对象上锁。从下能够看到饿汉模式不存在这种问题。函数

饿汉模式:性能

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

 

这二者的区别就在于,懒汉模式的初始化在被调用时进行,而饿汉模式的初始化在类加载时就进行了,这带来的结果就是懒汉模式更节省内存,可是其自己存在线程不安全的问题,必须使用 sychronized 关键字,因此性能会比较低,通常在单例用的次数少且消耗资源大时使用。学习

单例模式这样就讲清楚了,可是带来的新的问题是类到底什么时候被初始化?我查了相关资料发现,JVM并无规定类什么时候被加载(加载到JVM方法区和堆区),但严格规定了什么时候被初始化,其中最多见的两种状况就是 new 一个类或者调用其静态方法(还包括读取、设置静态字段等状况),一旦出现上述状况类就必须被初始化,而饿汉模式中的static成员instance在类加载时被赋值,同时 new 了自身,因此该类在加载时就初始化,懒汉模式就能够等到被调用再初始化。

可见,这么短短两段代码中蕴藏着那么多知识,充分体现了第一次提出规范单例模式的程序员的智慧。

最后再谈谈原型模式。原型模式的目的是建立重复的对象,好比说,若是类的初始化须要不少资源,不如只保存一份相应的对象。从这个角度看,原型模式很像是单例模式的扩展,能够当作是一个产品族的单例集合。看看以下java代码:

public abstract class Shape implements Cloneable {
   
   private String id;
   protected String type;
   
   abstract void draw();
   
   public String getType(){
      return type;
   }
   
   public String getId() {
      return id;
   }
   
   public void setId(String id) {
      this.id = id;
   }
   
   public Object clone() {
      Object clone = null;
      try {
         clone = super.clone();
      } catch (CloneNotSupportedException e) {
         e.printStackTrace();
      }
      return clone;
   }
}

public class ShapeCache {
    
   private static Hashtable<String, Shape> shapeMap 
      = new Hashtable<String, Shape>();

   public static Shape getShape(String shapeId) {
      Shape cachedShape = shapeMap.get(shapeId);
      return (Shape) cachedShape.clone();
   }

   public static void loadCache() {
      Circle circle = new Circle();
      circle.setId("1");
      shapeMap.put(circle.getId(),circle);

      Square square = new Square();
      square.setId("2");
      shapeMap.put(square.getId(),square);

      Rectangle rectangle = new Rectangle();
      rectangle.setId("3");
      shapeMap.put(rectangle.getId(),rectangle);
   }
}

 

java中自带的 Cloneable 类能够很好地实现原型模式的目的。虽然上述代码有些工厂模式的感受,但其实原型模式的目的与工厂模式彻底不一样。可是,原型模式最大的用处之一就是和工厂模式结合,若是把上述代码中的形状改成工厂,具体的形状改成不一样的工厂,那么最后的 Cache 提供的就是不一样工厂的克隆,这很好地实现了工厂的单例性。

 

本文描述了工厂模式、单例模式、原型模式三种常见的建立型设计模式,下次再来讲说结构型设计模式。

相关文章
相关标签/搜索