什么叫模式
模式描述的是具有代表性的重复性问题及其解答方案. 这类问题会以不同的形式反复出现,允许使用者举一反三, 应用到不同的环境中去.
模式包含的要素:
1、模式名称
2、该模式所能解决的问题
3、解决方案
4、使用该模式后的效果(优点和缺点)
为什么要学习设计模式?
模式从经验中总结出来的,经过证实的方案,模式只有在实际系统中经过多次验证之后才能成为模式.
1) 促进复用,提高系统的重用性。
2) 提高系统的可维护性, 通过使用设计模式,在系统面临升级和维护时,将把维护成本控制在最低的水平上.
3) 增加表达能力: 设计模式有很强的语言表述性. 设计模式是对解决方案的总结,使得设计模式能够更好的传达和交流,成为开发人员之间的一种共通语言,从而被更多的开发人员使用,反过来促进设计模式的发展和应用.
4)帮助我们更好的进行软件设计.
模式分类
架构模式:架构是指一个软件系统整体的组织结构。架构模式描述软件系统的组织结构的一些规则和指南。通过这些规则和指南,我们可以把预定义的、职责明确的子系统有效地组织起来。
设计模式:设计模式描述的是在软件系统的某一局部不断重现的核心解决方案,这种解决方案以完善的设计结构出现,可以被应用到以后出现的类似的环境中。和架构模式相比,设计模式关注的是更为微观的问题。
设计模式的分类
基础设计模式(Gof)(23种): 不与特定域,平台或编程语言关联
根据目的, 也就是这个设计模式是干什么的进行分类:
1)创建模式: 涉及对象的创建
单例模式, 工厂模式, 建造者模式,原型模式
2)结构模式:涉及类和对象的组合
Facade外观模式, 代理模式, 适配器模式, 装饰模式
3)行为模式: 刻画了类和对象交换及分配职责的方式.主要目标是解耦
观察者模式, 命令模式, 模板模式
工厂模式Factory
定义:工厂模式就是集中创建实例对象
使用工厂模式的好处:
1)客户类和工厂类分开。消费者任何时候需要某种产 品,只需向工厂请求即可。消费者无须修改就可以接纳新产品
2)对象的创建由工厂来完成, 类之间的耦合大大减少,变成为类和工厂之间的耦合了.
3)对象的创建和使用分离,达到解耦合的目的。
对面向对象设计原则的支持:
1)简单工厂模式一定程序上是支持开闭原则的;但是对开闭原则支持不够。(引入新产品的时候要修改工厂类)
2)工厂方法模式可以满足开闭原则
3) 为了满足依赖倒置原则常常需要使用工厂模式
Factory-简单工厂模式(静态工厂)
public class Factory{
public static Sample creator(int which){
//getClass 产生Sample 一般可使用动态类装载装入类。
if (which==1)
return new SampleA();
else if (which==2) return new SampleB();
}
} //Sample sampleA=Factory.creator(1);
//不涉及到Sample的具体子类,达到封装效果,也就减少错误修改的机会
Factory-工厂方法模式
使用工厂方法 要注意几个角色
首先你要定义产品接口,如上面的Sample,产品接口下有Sample接口的实现类,如SampleA,
其次要有一个factory类,用来生成产品Sample
interface IFactory{
Sample createProduct();
}
Class AFactory implements IFactory{
Sample createProduct(){
return new SampleA();
}
}对象的创建委托给子类来实现, 子类实现工厂方法来创建对象. 当然也可以在子类中实现对系列具体产品的实现. 由子类来决定实例化到底哪个具体的产品.
Factory-工厂方法模式
产品B的制造工厂
class BFactory implements IFactory{
Sample createProduct(){
return new SampleB();
}
} 也可以在createProduct()方法中根据具体的上下文计算或者配置文件信息来生成不同的具体产品;
//测试:
IFactory factory = new BFactory();
Sample product = factory.createProduct();
Factory-抽象工厂
public abstract class Factory{
public abstract Sample creator();
public abstract Sample2 creator(String name);
}
public class SimpleFactory extends Factory{
public Sample creator(){
.........
return new SampleA
}
public Sample2 creator(String name){
.........
return new Sample2A
}
}
public class BombFactory extends Factory{
public Sample creator(){
......
return new SampleB
}
public Sample2 creator(String name){
......
return new Sample2B
}
}
多个产品系列,多个工厂方法一起就构成了抽象工厂模式。
单例模式Singleton
主要作用是保证在Java应用程序中,一个类Class只有一个实例存在。
比如建立目录 ,数据库连接都需要这样的单线程操作
好处在于可以节省内存,因为它限制了实例的个数,有利于Java垃圾回收 (用在数据共享时)
使用单例模式Singleton(1)(饿汉式)(预加载)
public class Singleton {
//构造方法为private
private Singleton(){}
//在自己内部定义自己一个实例,注意这是private
//预加载
private static Singleton instance = new Singleton();
//这里提供了一个供外部访问本class的静态方法,
//可以直接访问
public static Singleton getInstance() {
return instance;
}
}
使用单例模式Singleton(2)(懒汉式)(懒加载)
public class Singleton {
//延迟加载 private static Singleton instance = null;
public static synchronized Singleton getInstance() {
//这个方法比上面有所改进,不用每次都进行生成
//对象,只是第一次使用时生成实例,提高了效率!
if (instance==null)
instance=new Singleton();
return instance;
}
}
这种方式在多线程的情况下,由于每次获取实例的时候都要对getInstance()方法加锁,获取锁才能运行,效率会受影响。
使用单例模式Singleton(3)
双锁机制:
public class Singleton {
private static Singleton instance = null;
public static Singleton getInstance(){
if (instance==null)
--1 synchronized(Singleton.class) {
---2 if (instance == null) {
---3 instance = new Singleton();
}
}
return instance;
}
}
这种方式只是在初始化Singleton那部分代码的时候添加同步锁,这样提高了效率。
原型模式-Prototype
定义:用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象.允许一个对象再创建另外一个可定制的对象,根本无需知道任何如何创建的细节
实现方式:
通过将一个原型对象传给那个要发动创建的对象,这个要发动创建的对象通过请求原型对象拷贝它们自己来实施创建。
使用情况:
1)很多时候,创建对象的时候,只是在某些属性值上有区别,而大部分都很相似,该类的用户对于该类的对象是怎么创建的,对类的内部结构这些都不关心的情况,但是这样的对象的初始化相对来说比较复杂,而且需要耗费较长的时间或资源,这种情况下,我们可以考虑使用Prototype模式。
原型模式-Prototype(浅度克隆)(克隆的是基本数据类型)
public class AbstractSpoon implements Cloneable{
String spoonName;
public void setSpoonName(String spoonName) {
this.spoonName = spoonName;
}
public String getSpoonName() {
return this.spoonName;
}
public Object clone() {
Object object = null;
try {
object = super.clone();
} catch (CloneNotSupportedException exception) {
System.err.println("AbstractSpoon is not Cloneable");
}
return object; 或return (Object )super.clone();
}
}
原型模式-Prototype(深度克隆)(克隆的是引用数据类型)
public Man deepClone(){
try {
ByteArrayOutputStream bo = new ByteArrayOutputStream();
ObjectOutputStream outObj = new ObjectOutputStream(bo);
outObj.writeObject(this);
ByteArrayInputStream bi = new ByteArrayInputStream(bo.toByteArray());
ObjectInputStream outIn = new ObjectInputStream(bi);
Man m = (Man)outIn.readObject(); return m;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
设计模式-Builder( 建造者模式 )—创建模式
用于一步一步创建一个复杂的对象
Builder模式是把创建复杂对象的过程和部件的创建分别开来,分别用Builder类和Director类来表示,从而达到解耦的目的.
适用于以下情况:
1)当创建复杂对象的算法应该独立于该对象的组成部分以及它们的装配方式时。
2)当构造过程必须允许被构造的对象有不同的表示时。
注意: Builder模式强调的是有相同建造顺序的过程,而具体建造细节不同。创建的复杂对象的内部构建间的建造顺序通常是稳定的,但是对象内部的构建通常面临着复杂的变化.
设计模式-Builder—创建模式
先需要一个接口, 表示一个稳定的顺序建造过程. 将这个对象需要创建的部分列出来.
public interface Builder {
//创建部件A比如创建汽车车轮
void buildPartA();
//创建部件B 比如创建汽车方向盘
void buildPartB();
//创建部件C 比如创建汽车发动机
void buildPartC();
//返回最后组装成品结果 (返回最后装配好的汽车)
//成品的组装过程不在这里进行,而是转移到下面的Director类中进行.
//从而实现了解耦过程和部件
Product getResult();
}
Builder的具体实现,其实就是造的是不同的汽车,车轮,方向盘,发动机建造过程不同当然是不同的汽车了。
设计模式-Builder—创建模式
用Director指挥者,控制建造过程, 隔离用户和建造过程的关联。
public class Director {
private Builder builder;
//用户告诉指挥者,我需要什么样的汽车,传入不同的builder就表示需要的汽车不同
public Director( Builder builder ) {
this.builder = builder;
}
// 将部件partA partB partC最后组成复杂对象
//这里是将车轮 方向盘和发动机组装成汽车的过程
public void construct() {
builder.buildPartA();
builder.buildPartB();
builder.buildPartC();
}
}
设计模式-Builder—创建模式
Builder的具体实现ConcreteBuilder:
通过具体完成接口Builder来构建或装配产品的部件;
public class ConcreteBuilder implements Builder {
Part partA, partB, partC;
public void buildPartA() {
//这里是具体如何构建partA的代码
}
public void buildPartB() {
//这里是具体如何构建partB的代码
}
public void buildPartC() {
//这里是具体如何构建partc的代码
}
public Product getResult() {
//返回最后组装成品结果
}
}
用Builder模式—创建模式
//部件的具体构造
ConcreteBuilder builder = new ConcreteBuilder();
//不同的构建过程,比如顺序…
Director director = new Director( builder );
//开始构建
director.construct();
//得到最终产品
Product product = builder.getResult();