先来说说模式的概念吧。
模式就是:具有代表性的某些重复问题的解决方案,是进过多次证实,与业务无关的方案。
它们都有特定的名称和适用的环境。模式的使用为我们带来了复用性的提高和可维护性的提高,同时可以增强表达能力。因为它是整个解决方案的总结。
一、模式的主要分类
模式分为两大类:设计模式和架构模式。
根据group of four 定义的23种模式和MVC模式,总共有24种。
其中设计模式又分为三小类:设计模式是系统局部出现的某一核心问题的解决方案
1.1创建型模式
创建模式:是用于创建对象。
包括单列、工厂、建造者、原型四种模式。
1.2结构型模式
结构模式:是用于组织类和对象之间关系的,形象的说就是对象间的组织形式。
包括桥梁、装饰器、适配器、外观、代理模式等。
1.3行为型模式
行为模式:是用于对象交换和职责分配的,形象的说就是方法的组织形式。
包括方法模板、策略、观察者、命令模式等。
另外架构模式是用于指导整个系统的整体的组织结构,规划,指南,用来组织预定义的职责分明的子系统。
二、创建模式
2.1单列模式singleton
顾名思义:这种设计模式是为了保证整个类只会产生一个对象,它是唯一的存在,通常用于独一无二的最高控制者。
在应用系统开发时,经常需要让系统管理一些软件内外部资源,这些内外部资源中有些只能有一个实例。
共有3种方法实现,各有不同的效果:
2.1.1预加载
构造方法私有,有一个静态属性是本身的一个对象。加载类时直接赋值构造一个对象。有静态方法可以获取该对象的引用。
//单例(态)模式一
//优点:线程绝对安全,多线程情况下不排队
//缺点:预加载导致不使用也产生了对象
//public class Singleton {
//
// //静态的对象,保证了全类共享一个对象
// private static Singleton instance;
//
// static{
// instance = new Singleton();
// }
//
// //私有的构造方法
// private Singleton(){
//
// }
//
// public static Singleton getInstance(){
// return instance;
// }
//
//}
2.1.2延时加载
构造方法私有,有一个静态属性是本身的一个对象。用一个静态同步方法来赋值,第一次调用给静态属性赋值,之后直接提取值。
//单例模式二
//优点:延迟加载(当真正需要对象的时候才产生)
//缺点: 多线程情况下要排队
//public class Singleton{
// private static Singleton instance = null;
//
// private Singleton(){
//
// }
//
// public synchronized static Singleton getInstance(){
// if(instance == null){
// instance = new Singleton();
// }
// return instance;
// }
//}
2.1.3高并发延时加载
构造方法私有,有一个静态属性是本身的一个对象。有一个静态方法给它赋值,代码块中使用双锁机制来控制。
//单例模式三(Java不支持)
//别名:双锁机制
//实现延迟加载、并支持高并发!
public class Singleton{
private static Singleton instance = null;
private Singleton(){
}
public static Singleton getInstance(){
if(instance == null){
synchronized(Singleton.class){
if(instance == null){
instance = new Singleton();
}
}
}
return instance;
}
}
2.2工厂模式factory
2.2.1简单工厂
简单工厂中,工厂是单一的。产品有一种,有一个抽象父类,下面是各种产品。工厂有只能制造同一种类型产品的方法。不支持开闭。
对于消费者来说,同样的产品需求只有一种选择。
当工厂只生产同一品种的具体产品,而且产品数量有限的时候,可以考虑使用简单工厂模式。
package com.lovo.factory.simplefactory;
/**
* @author Administrator
* 简单工厂:静态的工厂,动态的产品
*/
public class KFCFactory {
public static KFCProduct order(String msg){
if(msg.equals("汉堡")){
return new Humburger();
}else if(msg.equals("薯条")){
return new Chips();
}else{
return null;
}
}
}
package com.lovo.factory.simplefactory;
public abstract class KFCProduct {
public abstract void tasty();
}
package com.lovo.factory.simplefactory;
public class Chips extends KFCProduct {
@Override
public void tasty() {
// TODO Auto-generated method stub
System.out.println("KFC的薯条!");
}
}
package com.lovo.factory.simplefactory;
public class Humburger extends KFCProduct{
@Override
public void tasty() {
// TODO Auto-generated method stub
System.out.println("鸡腿堡!!!");
}
}
2.2.2工厂方法
工厂方法中,工厂有多种,都有抽象类。只有一种类型的产品即一个产品族,下面有该类产品的具体实现子类。有工厂抽象父类,该类中定义所有工厂的公共方法,子类工厂可以有不同的实现,兼容各自的特色。
对于消费者来说,同样的产品需求有不同的选择。它只能生产同一种类的具体产品。
package com.lovo.factory.factorymethod;
/**
* @author Administrator
* 工厂是动态的,产品是不动的
*/
public abstract class HumburgerFactory {
public abstract Humburger order();
}
package com.lovo.factory.factorymethod;
public class KFCFactory extends HumburgerFactory{
@Override
public Humburger order() {
// TODO Auto-generated method stub
System.out.println("KFC汉堡");
return new Humburger();
}
}
package com.lovo.factory.factorymethod;
public class MCDFactory extends HumburgerFactory {
@Override
public Humburger order() {
// TODO Auto-generated method stub
Humburger hum = new Humburger();
System.out.println("MCD汉堡");
return hum;
}
}
2.2.3抽象工厂
抽象工厂中工厂和产品都具有抽象类,工厂和产品都可以多样化。产品有2个及以上的产品族,并且这些产品相互间有。抽象工厂集成了多个产品族的生产方法,具体的工厂实现自己的产品生产方法。消费者自由选择各种搭配。
工厂类层次与具体的产品类层次通常是平行的(即一一对应的)。
增加一个具体类,一般也要相应地增加一个工厂类,增加了系统复杂度。
在以下情况下,应当考虑使用抽象工厂模式:
1-这个系统的产品有多于一个的产品族。
2-同属于同一个产品族的产品是设计成在一起使用的。产品之间有特殊的相关或依赖关系。产品之间应该最少应该有两种关系,纵向来看每种产品组内部产品之间有继承关系,例如产品AbstractProductA与ProductA1和ProductA2之间有继承关系,是同一产品族产品;横向来看两个产品族之间的产品也应该有一一对应关系,例如ProductA1与ProductB1之间,或ProductA2与ProductB2之间的对应关系。
2.3建造者模式builder
建造模式(Builder Pattern)的定义为:把复杂对象的构造过程从对象的表示中分离出来,其直接效果是将一个复杂的对象简化为一个比较简单的目标对象。
一个产品经常由不同的组成成分作为产品的部件,不同的产品可以有不同的部件。使用建造模式,可以使客户端不需要知道所生成的产品有哪些部件、每个产品的对应部件有什么不同、是如何建造出来的、以及如何组装产品。
建造模式的使用时机:
当创建一个复杂对象的算法应该独立于组成该对象的部分以及如何组装时。
当构造过程必须允许要创建的对象有不同的表示时。
当我们想要将客户与实际创建过程或者结果产品隔离时
被创建的对象不需要知道其创建细节。
创建的代码与表示的代码分离,二者都很容易被替代而不至于相互影响。
我们可以控制创建过程。
我们可以独立地重用或者更改创建过程或产品。
public abstract class Builder { private PartA pa; private PartB pb; private PartC pc; private Result result; public abstract void buildA(); public abstract void buildB(); public abstract void buildC(); public Result getResult(){ return this.result; } }
public abstract class Director { private Builder builder; public Builder getBuilder() { return builder; } public void setBuilder(Builder builder) { this.builder = builder; } public abstract void contact(); }
2.4原型模式prototype
原型模式是通过拷贝一个现有对象生成新对象的。
为了实现深度克隆,经常要使用流来读取拷贝对象,在读出一个新的对象。
package com.lovo.prototype;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
//public class BasketballStar implements Cloneable {
public class BasketballStar implements Serializable{
private String name;
private int age;
private float height;
private Skill theSkill;
public BasketballStar() {
}
public BasketballStar(String name, int age, float height) {
super();
this.name = name;
this.age = age;
this.height = height;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public float getHeight() {
return height;
}
public void setHeight(float height) {
this.height = height;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Skill getTheSkill() {
return theSkill;
}
public void setTheSkill(Skill theSkill) {
this.theSkill = theSkill;
}
public BasketballStar deepClone(){
BasketballStar bs = null;
//序列化
ObjectOutputStream oos = null;
ByteArrayOutputStream bos = null;
try {
bos = new ByteArrayOutputStream();
oos = new ObjectOutputStream(bos);
oos.writeObject(this);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally{
if(oos != null){
try {
oos.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
//反序列化
ObjectInputStream ois = null;
ByteArrayInputStream bis = null;
try {
bis = new ByteArrayInputStream(bos.toByteArray());
ois = new ObjectInputStream(bis);
bs = (BasketballStar)ois.readObject();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally{
if(ois != null){
try {
ois.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
return bs;
}
// public Object clone() throws CloneNotSupportedException {
// BasketballStar bs = (BasketballStar)super.clone();
// bs.setTheSkill((Skill)this.getTheSkill().clone());
// return bs;
// }
@Override
public String toString() {
// TODO Auto-generated method stub
return this.name + " " + this.age + " " + this.height;
}
}
package com.lovo.prototype;
import java.io.Serializable;
//public class Skill implements Cloneable{
public class Skill implements Serializable{
private int shooting;
private int passing;
private int crossing;
private int jumping;
public Skill() {
}
public Skill(int shooting, int passing, int crossing, int jumping) {
super();
this.shooting = shooting;
this.passing = passing;
this.crossing = crossing;
this.jumping = jumping;
}
public int getCrossing() {
return crossing;
}
public void setCrossing(int crossing) {
this.crossing = crossing;
}
public int getJumping() {
return jumping;
}
public void setJumping(int jumping) {
this.jumping = jumping;
}
public int getPassing() {
return passing;
}
public void setPassing(int passing) {
this.passing = passing;
}
public int getShooting() {
return shooting;
}
public void setShooting(int shooting) {
this.shooting = shooting;
}
@Override
public String toString() {
// TODO Auto-generated method stub
return this.shooting + " " + this.passing + " " + this.crossing + " " + this.jumping;
}
// @Override
// public Object clone() throws CloneNotSupportedException {
// // TODO Auto-generated method stub
// return super.clone();
// }
}