设计模式是一套被反复使用的、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了重用代码、让代码更容易被他人理解、保证代码 可靠性
这些模式可以分为三大类:创建型模式(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 读取二进制流。