JVerice Java Dev Engineer

设计模式


设计模式是一套被反复使用的、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了重用代码、让代码更容易被他人理解、保证代码 可靠性

这些模式可以分为三大类:创建型模式(Creational Patterns)、结构型模式(Structural Patterns)、行为型模式(Behavioral Patterns)。

工厂模式

意图:定义一个创建对象的接口,让其子类自己决定实例化哪一个工厂类,工厂模式使其创建过程延迟到子类进行。

  • 优点:

    1、一个调用者想创建一个对象,只要知道其名称就可以了。

    2、扩展性高,如果想增加一个产品,只要扩展一个工厂类就可以。

    3、屏蔽产品的具体实现,调用者只关心产品的接口。

  • 缺点:

    每次增加一个产品时,都需要增加一个具体类和对象实现工厂,使得系统中类的个数成倍增加,在一定程度上增加了系统的复杂度,同时也增加了系统具体类的依赖。这并不是什么好事。

  • 使用场景:

    1、日志记录器:记录可能记录到本地硬盘、系统事件、远程服务器等,用户可以选择记录日志到什么地方。

    2、数据库访问,当用户不知道最后系统采用哪一类数据库,以及数据库可能有变化时。

    3、设计一个连接服务器的框架,需要三个协议,”POP3”、 “IMAP”、”HTTP”,可以把这三个作为产品类,共同实现一个接口。

    public interface Shape {
      void draw();
    }
    public class Squeare implements Shape {
      public void draw() {
          System.out.println("Squeare draw() method.");
      }
    }
    public class Circle implements Shape {
      public void draw() {
          System.out.println("Circle draw() method.");
      }
    }
    public class ShapeFactory {
      public Shape getShape(String shapeType){
          if(shapeType==null)
              return null;
          if(shapeType.equalsIgnoreCase("Circle")){
              return new Circle();
          }
          if(shapeType.equalsIgnoreCase("Squeare")){
              return new Squeare();
          }
          return null;
      }
    }
    public class FactoryPatternTest {
      public static void main(String[] args) {
          ShapeFactory shapeFactory = new ShapeFactory();
          Shape shape1 = shapeFactory.getShape("Circle");
          shape1.draw();
          Shape shape2 = shapeFactory.getShape("Squeare");
          shape2.draw();
      }
    }
    

抽象工厂模式

接口是负责创建一个相关对象的工厂,不需要显式指定它们的类。每个生成的工厂都能按照工厂模式提供对象。

意图:提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。在一个产品族里面,定义多个产品。在一个工厂里聚合多个同类产品。

  • 优点:当一个产品族中的多个对象被设计成一起工作时,它能保证客户端始终只使用同一个产品族中的对象。
  • 缺点:产品族扩展非常困难,要增加一个系列的某一产品,既要在抽象的 Creator 里加代码,又要在具体的里面加代码。
  • 使用场景: 1、QQ 换皮肤,一整套一起换。 2、生成不同操作系统的程序。
  • 注意事项:产品族难扩展,产品等级易扩展。 ``` public interface Color { void fill(); } public interface Shape { void draw(); } public class Blue implements Color { public void fill() { System.out.println(“Blue Color fill() method.”); } } public class Red implements Color { public void fill() { System.out.println(“Rad Color fill() method.”); } } public class Circle implements Shape { public void draw() { System.out.println(“Circle Shape draw() method.”); } } public class Squeare implements Shape { public void draw() { System.out.println(“Squeare Shape draw() method.”); } }

//抽象工厂 public abstract class AbstractFactory { public abstract Shape getShape(String shape); public abstract Color getColor(String color); } public class ColorFactory extends AbstractFactory { public Color getColor(String color) { if(color==null) return null; if(color.equalsIgnoreCase(“Red”)) return new Red(); if(color.equalsIgnoreCase(“Bule”)) return new Blue(); return null; } public Shape getShape(String shape) { return null; } } public class ShapeFactory extends AbstractFactory { public Shape getShape(String shape) { if(shape==null) return null; if(shape.equalsIgnoreCase(“Circle”)) return new Circle(); if(shape.equalsIgnoreCase(“Squeare”)) return new Squeare(); return null; } public Color getColor(String color) { return null; } }

//实例化工厂 public class FactoryProducer { public static AbstractFactory getFactory(String choice){ if(choice.equalsIgnoreCase(“Color”)) return new ColorFactory(); else if(choice.equalsIgnoreCase(“Shape”)) return new ShapeFactory(); return null; } } public class FactoryPatternTest { public static void main(String[] args) { AbstractFactory shapeFactory = FactoryProducer.getFactory(“Shape”); Shape shape = shapeFactory.getShape(“Circle”); shape.draw(); AbstractFactory colorFactory = FactoryProducer.getFactory(“Color”); Color color = colorFactory.getColor(“Red”); color.fill(); } }

---
## 单例模式

> 意图:保证一个类仅有一个实例,并提供一个访问它的全局访问点。

* 优点: 
1、在内存里只有一个实例,减少了内存的开销,尤其是频繁的创建和销毁实例(比如管理学院首页页面缓存)。 
2、避免对资源的多重占用(比如写文件操作)。 

* 缺点:
没有接口,不能继承,与单一职责原则冲突,一个类应该只关心内部逻辑,而不关心外面怎么样来实例化。

//单例模式:饿汉式,多线程安全 //优点:没有加锁,执行效率会提高。 //缺点:类加载时就初始化,浪费内存。 public class SingleObject {

private static SingleObject instance = new SingleObject();
private SingleObject(){}
public static SingleObject getInstance(){
	return instance;
} } //单例模式:懒汉式  ,多线程下加锁synchronized才算单例模式 class SingleObject2{
private static SingleObject2 instance;
private SingleObject2(){}
public static synchronized SingleObject2 getInstance(){
	if(instance==null)
		instance=new SingleObject2();
	return instance;
} } //单例模式:双检锁/双重校验锁,多线程安全 //这种方式采用双锁机制,安全且在多线程情况下能保持高性能。 class Singleton{
private volatile static Singleton instance;
private Singleton(){}
public static Singleton getInstance(){
	if(instance==null){
		synchronized (Singleton.class) {
			if(instance==null)
				instance = new Singleton();
		}
	}
	return instance;
} } //单例模式:登记式/静态内部类,线程安全 //这种方式能达到双检锁方式一样的功效,但实现更简单 class Singleton2{
private static class SingletonHolder{
	private static final Singleton2 INSTANCE = new Singleton2();
}
private Singleton2(){}
public static final Singleton2 getInstance(){
	return SingletonHolder.INSTANCE;
} } //单例模式:枚举,多线程安全 enum Singleton3{
INSTANCE;
public void whateverMethod(){
	System.out.println("Something");
} } Singleton3.INSTANCE.whateverMethod();

//JVM会保证enum不能被反射并且构造器方法只执行一次。 public class EnumSingleton{ private EnumSingleton(){} public static EnumSingleton getInstance(){ return Singleton.INSTANCE.getI nstance(); }

private static enum Singleton{
    INSTANCE;
    
    private EnumSingleton singleton;
    //JVM会保证此方法绝对只调用一次
    private Singleton(){
        singleton = new EnumSingleton();
    }
    public EnumSingleton getInstance(){
        return singleton;
    }
} } ``` --- ## 建造者模式

使用多个简单的对象一步一步构建成一个复杂的对象。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。

意图:将一个复杂的构建与其表示相分离,使得同样的构建过程可以创建不同的表示。

  • 优点: 1、建造者独立,易扩展。 2、便于控制细节风险。

  • 缺点: 1、产品必须有共同点,范围有限制。 2、如内部变化复杂,会有很多的建造类。

  • 使用场景: 1、需要生成的对象具有复杂的内部结构。 2、需要生成的对象内部属性本身相互依赖。
  • 注意事项:与工厂模式的区别是:建造者模式更加关注与零件装配的顺序。

原型模式

用于创建重复的对象,同时又能保证性能。

意图:用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。

  • 如何解决:利用已有的一个原型对象,快速地生成和原型对象一样的实例。
  • 关键代码: 1、实现克隆操作,在 JAVA 继承 Cloneable,重写 clone()
  • 优点: 1、性能提高。 2、逃避构造函数的约束。

  • 缺点: 1、配备克隆方法需要对类的功能进行通盘考虑,这对于全新的类不是很难,但对于已有的类不一定很容易,特别当一个类引用不支持串行化的间接对象,或者引用含有循环结构的时候。 2、必须实现 Cloneable 接口。 3、逃避构造函数的约束。
  • 注意事项: 与通过对一个类进行实例化来构造新对象不同的是,原型模式是通过拷贝一个现有对象生成新对象的。浅拷贝实现 Cloneable,重写clone(),深拷贝是通过实现 Serializable 读取二进制流。

上一篇 Java基础

下一篇 Web Service

Comments