狠狠撸

狠狠撸Share a Scribd company logo
设计模式
目录
1 什么是设计模式
2 单例模式
3 享元模式
4 工厂模式
5 抽象工厂模式
1 什么是设计模式
设计模式是一套被反复使用的、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了重用代码、让代码更容易被他人理解、保证代码可靠性。
2 设计模式分为三大类
创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。
结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。
行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模
式。
3 四种设计模式
3.1 单例模式
?什么是单例模式
顾名思义,单例模式的意思就是只有一个实例。单例模式确保某一个
类只有一个实例,而且自行实例化并向整个系统提供这个实例。这个类称
为单例类。
?单例模式的要点
(1)某个类只能有一个实例;
(2)它必须自行创建这个实例;
(3)它必须自行向整个系统提供这个实例。
? 饿汉模式和懒汉模式
饿汉式:静态初始化方式,在启动加载单例类时就实例化对象,只实例化一次,以后用到的时候就不需要再去实例化了,加载类的时候速度比较慢,但以后获得对象时
的速度比较快,该对象从加载到应用结束一直占用资源。
懒汉式:相当于一个延迟加载机制,即你需要这个对象时候才去实例化,加载类的时候速度比较快,但以后获得对象时的速度比较慢,该对象在整个应用的生命周期只
有一部分时间占用资源。面临多线程访问的安全性问题,需要做双重锁定处理才可以保证安全。
?几种常见写法:
1、饿汉式(静态常量)[可用]
public class Singleton {
private final static Singleton INSTANCE = new Singleton();
private Singleton(){}
public static Singleton getInstance(){
return INSTANCE;
}
}
  优点:这种写法比较简单,就是在类装载的时候就完成实例化。避免了线程同步问题。
  缺点:在类装载的时候就完成实例化,没有达到Lazy Loading的效果。如果从始至终从未使用过这个实例,则会造成内存的浪费。
2、饿汉式(静态代码块)[可用]
public class Singleton {
private static Singleton instance;
static {
instance = new Singleton();
}
private Singleton() {}
public Singleton getInstance() {
return instance;
}
}
  这种方式和上面的方式其实类似,只不过将类实例化的过程放在了静态代码块中,也是在类装载的时候,就执行静态代码块中的代码,初始化类的实例。优缺点和
上面是一样的。
3、双重检查[推荐用]
public class Singleton {
private static volatile Singleton singleton;
private Singleton() {}
public static Singleton getInstance() {
if (singleton == null) {
synchronized (Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
}
  Double-Check概念对于多线程开发者来说不会陌生,如代码中所示,我们进行了两次if (singleton == null)检查,这样就可以保证线程安全了。这样,实例
化代码只用执行一次,后面再次访问时,判断if (singleton == null),直接return实例化对象。
  优点:线程安全;延迟加载;效率较高。
4、静态内部类[推荐用]
public class Singleton {
private Singleton() {}
private static class SingletonInstance {
private static final Singleton INSTANCE = new Singleton();
}
public static Singleton getInstance() {
return SingletonInstance.INSTANCE;
}
}
  这种方式跟饿汉式方式采用的机制类似,但又有不同。两者都是采用了类装载的机制来保证初始化实例时只有一个线程。不同的地方在饿汉式方式是只要
Singleton类被装载就会实例化,没有Lazy-Loading的作用,而静态内部类方式在Singleton类被装载时并不会立即实例化,而是在需要实例化时,调用
getInstance方法,才会装载SingletonInstance类,从而完成Singleton的实例化。
  类的静态属性只会在第一次加载类的时候初始化,所以在这里,JVM帮助我们保证了线程的安全性,在类进行初始化时,别的线程是无法进入的。
  优点:避免了线程不安全,延迟加载,效率高。
? 适用场合:
1. 需要频繁的进行创建和销毁的对象;
2. 创建对象时耗时过多或耗费资源过多,但又经常用到的对象;
3. 工具类对象;
4. 频繁访问数据库或文件的对象。
? 设计原则:
其实可以说单例模式违反了“单一职责”的设计原则,因为不只要维护自己先关的功能,还要管理自己的实例化,但是这样可以让整体设计更简单
3.2 享元模式:
单例模式(Singleton)的定义:是为了确保一个类只能产生一个实例,从而节省对象创建所花费的时间,从而对系统内存使用频率也会减低。
享元模式(FlyWeight)的定义:是为系统中存在多个相同的对象,那么只需要共享一个对象的拷贝。
就单例和享元两个模式的定义而言,它们的目的是一样的,至少就内存的开销问题这点,两者是相同的。而享元模式可以看成是单例的一个扩展。
?定义
有很多个相同的对象,他们有很多相同的属性,我们把这些对象抽象成一个,把不同的属性作为方法参数传递进来。相同的属性称为内部状态,不同的属性称为外
部状态
享元模式的意图是通过共享有效支持大量细粒度的对象,来提供应用程序的性能,节省系统中重复创建对象实例的性能消耗
这个怎么理解呢?
1、当我们系统中某个对象类型的实例较多的情况。
2、并且要求这些实例进行分类后,发现真正有区别的分类很少的情况。
?模式结构中的四种角色
1.享元接口(Flyweight)
2.具体享元(Concrete Flyweight)
3.享元工厂(Flyweight Factory)
4.客户端(Client)
?结构图
? 核心代码
public class FlyweightFactory {
Map<String, Employer> map=new HashMap<String, Employer>();
public Employer getEmployer(String name){
Employer e=map.get(name);
if(e==null){
System.out.println("map is empty");
e=new Employer(name);
map.put(name, e);
}
return e;
}
}
?享元模式的使用场景
1、当我们发现某个类型的对象有大量的实例时,我们是否可以对这些实例进行分类,经过分类后,我们发现只有很少的类别的情况下。
2、我们发现通过使用享元模式后能够提高系统的性能和不会带来更多的复杂度时
?例子:
Integer 一个字节 也就是-128 127的整数会被放在常量池里面,因为小的整数应用特别频繁:
Integer i1 = 137;
Integer i2 = 137;
Integer i3 = 13;
Integer i4 = 13;
System.out.println(i1 == i2);
System.out.println(i3 == i4);
?享元模式优点
?使用享元可以节省内存的开销,特别适合处理大量细粒度对象,这些对象的许多属性值是相同的,而且一旦创建则不容许修改
?享元模式中的享元可以使用方法的参数接受外部状态中的数据,但外部状态数据不会干扰到享元中的内部数据,这就使得享元可以在不同的环境中被共享
http://blog.csdn.net/superbeck/article/details/4446177
3.3 工厂方法设计模式:
?概念
?角色分类
1 抽象工厂角色
2 具体工厂角色
3 抽象产物角色
4 具体产物角色
?缩略图
?结构图
?优点
这种抽象的结果,使这种工厂方法模式可以用来允许系统不修改具体工厂角色的情况下引进新产物,这一特点无疑使得工厂模式具有超过简单工厂模式的优越性。
在工厂方法模式中,一般都有一个平行的等级结构,也就是说工厂和产物是对应的的。抽象工厂对应抽象产物,具体工厂对应具体产物。简单的示意图如下:
3.4 抽象工厂模式:
?概念
?结构和角色
抽象工厂(AbstractFactory)角色:
担任这个角色的是工厂方法模式的核心,它是与应用系统的商业逻辑无关的。通常使用JAVA接口或者抽象JAVA类来实现,而所有的具体工厂类必须实现该接口或者
继承抽象类。
具体工厂类(Conrete Factory)角色:
这个角色直接在客户端的调用下创建产物的实例。这个角色含有选择合适的产物对象的逻辑。通常使用具体类来实现这个角色。
抽象产物(Abstract Product)角色:
担任这个角色的类是工厂方法模式所创建的对象的父类,或它们共同拥有的接口。通常使用接口或者抽象类来实现这一角色。
具体产物(Concrete Product)角色:
抽象工厂模式所创建的任何产物对象都是某一个具体产物类的实例。通常使用具体JAVA类来实现。
?结构图
?优点
程序设计中有三种耦合:零耦合、抽象耦合、具体耦合。抽象工厂设计可以很好的把具体耦合转换到抽象耦合来减少耦合程度。
具体产物从客户代码中被分离出来。
容易改变产物的系列。
将一个系列的产物族统一到一起创建。
?缺点
由于每个类的产生都要继承抽象类(或接口),并由工厂来创建,这样就增加了代码长度和工作量。
在产物族中扩展新的产物是很困难的,它需要修改抽象工厂的接口。
使软件结构更复杂。
?抽象工厂和工厂方法的区别
工厂方法模式:
工厂方法模式是一种极端情况的抽象工厂模式,而抽象工厂模式可以看成是工厂方法模式的推广。
工厂方法模式用来创建一个产物的等级结构的,而抽象工厂模式是用来创建多个产物的等级结构的。
工厂方法模式只有一个抽象产物类,而抽象工厂模式有多个抽象产物类。
一个抽象产物类,可以派生出多个具体产物类。
一个抽象工厂类,可以派生出多个具体工厂类。
每个具体工厂类只能创建一个具体产物类的实例。
抽象工厂模式:
多个抽象产物类,每个抽象产物类可以派生出多个具体产物类。
一个抽象工厂类,可以派生出多个具体工厂类。
每个具体工厂类可以创建多个具体产物类的实例。
区别:
工厂方法模式只有一个抽象产物类,而抽象工厂模式有多个。
工厂方法模式的具体工厂类只能创建一个具体产物类的实例,而抽象工厂模式可以创建多个。
两者皆可。
?总结
工厂的实现通常使用Singleton模式。一个应用中一般每个系列产物只需要使用一个具体工厂的实例。
抽象工厂模式提供了一个创建一系列相关或相互依赖的对象的接口,关键点在于应对”多系列对象创建”的需求变化。
简单工厂:
优点:简单工厂模式主要用于隔离类对象的使用者和具体类型之间的耦合关系。面对一个经常变化的具体类型,紧耦合关系会导致软件的脆弱。通过使用工厂类,外界可
以从直接创建具体产物对象的尴尬局面摆脱出来,仅仅需要负责“消费”对象就可以了。而不必管这些对象究竟如何创建及如何组织的.明确了各自的职责和权利,有利
于整个软件体系结构的优化。
缺点:由于工厂类集中了所有实例的创建逻辑,违反了高内聚责任分配原则,将全部创建逻辑集中到了一个工厂类中;它所能创建的类只能是事先考虑到的,如果需要
添加新的类,则就需要改变工厂类了

More Related Content

设计模式-单例、享元、工厂与抽象工厂