-
单例模式
-
工厂模式
-
抽象工厂模式
-
建造者模式
-
原型模式
单例模式
/**
* 单例模式
* 饿汉式
*/
public class Simple01 {
//类初始化时,立即创建对象
private static Simple01 s=new Simple01();
private Simple01(){
}
//方法没有同步,调用效率高
public static Simple01 getNew(){
return s;
}
}
/**
* 单例模式
* 懒汉式
*/
public class Simple02 {
//调用时再创建
private static Simple02 s;
private Simple02(){}
//线程同步
public static synchronized Simple02 getNew(){
if(s==null){
s=new Simple02();
}
return s;
}
}
双重检测锁(由于JVM底层内部模型原因,偶尔会出问题,不建议使用
静态内部类式(线程同步,懒汉式加载)
/**
* 单例模式
* 静态内部类式
*/
public class Singleton03 {
private Singleton03(){}
private static class Singletoninner{
private static final Singleton03 instance=new Singleton03();
}
public static Singleton03 getInstance(){
return Singletoninner.instance;
}
}
枚举式(没有延时加载,防止反射和反序列化)
/**
* 单例模式
* 枚举式
*/
public enum Singleton04 {
INSTANCE;//本身就是一个单例对象
public void operation(){
}
}
单例对象 占用资源少 不需要延时加载
枚举式 好于 饿汉式
单例对象 占用资源大 需要延时加载
静态内部类式 好于 懒汉式
使用反射和反序列化破解单例模式与防止
import java.io.*;
import java.lang.reflect.Constructor;
/**
* 用反射和反序列化破解单例模式
*/
public class Client{
public static void main(String[] args) throws Exception {
Simple01 s1=Simple01.getNew();
Simple01 s2=Simple01.getNew();
System.out.println(s1);
System.out.println(s2);
/* //反射调用
Class cc=Class.forName("gof32.Simple01");
Constructor<Simple01> c=cc.getDeclaredConstructor(null);
c.setAccessible(true);
System.out.println(c.newInstance(null));*/
//反序列化调用
FileOutputStream fos=new FileOutputStream("D:/Simple.txt");
ObjectOutputStream oos=new ObjectOutputStream(fos);
oos.writeObject(s2);
oos.flush();
oos.close();
fos.close();
FileInputStream fis=new FileInputStream("D:/Simple.txt");
ObjectInputStream ois=new ObjectInputStream(fis);
Simple01 ss=(Simple01)ois.readObject();
System.out.println(ss);
}
}
防止
import java.io.Serializable;
/**
* 单例模式
* 饿汉式
* 防止反射调用
*/
public class Simple01 implements Serializable {
//类初始化时,立即创建对象
private static Simple01 s=new Simple01();
private Simple01(){
if(s!=null){
throw new RuntimeException();//防止反射调用
}
}
//方法没有同步,调用效率高
public static Simple01 getNew(){
return s;
}
}
import java.io.Serializable;
/**
* 单例模式
* 饿汉式
* 防止反序列化调用
*/
public class Simple01 implements Serializable {
//类初始化时,立即创建对象
private static Simple01 s=new Simple01();
private Simple01(){
if(s!=null){
throw new RuntimeException();//防止反射调用
}
}
//方法没有同步,调用效率高
public static Simple01 getNew(){
return s;
}
//反序列化会自动调用readResolve()
private Object readResolve(){//防止反序列化的破解
return s;
}
}
测试多线程环境下各种单例模式的速度
import java.util.concurrent.CountDownLatch;
/**
* 测试多线程环境下设计模式的速度
*/
public class Client2 {
public static void main(String[] args) throws InterruptedException {
long start=System.currentTimeMillis();
int threadNum=10;
final CountDownLatch count=new CountDownLatch(threadNum);//内部类不能调用外部类的局部变量,final变为常量
for(int j=0;j<10;j++) {
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 100000; i++) {
Singleton03 s=Singleton03.getInstance();
}
count.countDown();
}
}).start();
}
count.await();
long end=System.currentTimeMillis();
System.out.println("耗时:"+(end-start));
}
}
工厂模式
实现了创建者和调用者的分离
简单工厂模式
工厂方法模式
抽象工厂模式
面向对象的设计基本原则
OCP(开闭原则,Open Closed principle):一个软件的实体应对扩展开放,修改关闭
DIP(依赖倒转原则,Dependence Inversion Principle)要针对接口编程,不要针对实现变成
LOD(迪米特法则,Low of Demeter):只与你直接的朋友通信,避免和陌生人通信
简单工厂(违背开闭原则,但是实际使用最多)
/**
* 简单工厂
*/
public class Factory01 {
public static Car createCar(String type){
Car c=null;
if("比亚迪".equals(type)){
return new BYD();
}else if("奔驰".equals(type)){
return new Bench();
}else{
return null;
}
}
}
/**
* 调用类
*/
public class Client01 {
public static void main(String[] args) {
Car c1=Factory01.createCar("比亚迪");
Car c2=Factory01.createCar("奔驰");
c1.run();
c2.run();
}
}
工厂方法模式(不修改类的前提下,通过增加新的工厂类实现扩展)
public interface Factory {
Car createCar();
}
public class BenchFactory implements Factory{
@Override
public Car createCar() {
return new Bench();
}
}
public class BYDFactory implements Factory{
@Override
public Car createCar() {
return new BYD();
}
}
public class Client {
public static void main(String[] args) {
Car c1=new BenchFactory().createCar();
Car c2=new BYDFactory().createCar();
c1.run();
c2.run();
}
}
根据设计理论建议:工厂方法模式,实际上一般都用简单工厂模式
抽象工厂模式(不可以增加产品,可以增加产品族)
public interface Factory {
Engine createEngine();
Seat crateSeat();
Tyre crateTyre();
}
public class LuxuryFactory implements Factory {
@Override
public Engine createEngine() {
return new LuxuryEngine();
}
@Override
public Seat crateSeat() {
return new LuxurySeat();
}
@Override
public Tyre crateTyre() {
return new LuxuryTyre();
}
}
public class LowFactory implements Factory {
@Override
public Engine createEngine() {
return new LowEngine();
}
@Override
public Seat crateSeat() {
return new LowSeat();
}
@Override
public Tyre crateTyre() {
return new LowTyre();
}
}
public interface Engine {
void run();
}
class LuxuryEngine implements Engine {
@Override
public void run() {
System.out.println("跑的快");
}
}
class LowEngine implements Engine{
@Override
public void run() {
System.out.println("跑得慢");
}
}
public interface Seat {
void comfort();
}
class LuxurySeat implements Seat{
@Override
public void comfort() {
System.out.println("舒适");
}
}
class LowSeat implements Seat{
@Override
public void comfort() {
System.out.println("硬的一批");
}
}
public interface Tyre {
void quality();
}
class LuxuryTyre implements Tyre{
@Override
public void quality() {
System.out.println("经久耐用");
}
}
class LowTyre implements Tyre{
@Override
public void quality() {
System.out.println("不耐用");
}
}
public class Client {
public static void main(String[] args) {
Factory factory=new LuxuryFactory();
Engine engine=factory.createEngine();
engine.run();
}
}
建造者模式
public class Car {
private Engine engine;
private Tyre tyre;
private Frame frame;
public void lunch(){
System.out.println("启动");
}
public Engine getEngine() {
return engine;
}
public void setEngine(Engine engine) {
this.engine = engine;
}
public Tyre getTyre() {
return tyre;
}
public void setTyre(Tyre tyre) {
this.tyre = tyre;
}
public Frame getFrame() {
return frame;
}
public void setFrame(Frame frame) {
this.frame = frame;
}
}
class Engine{
private String name;
public Engine(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
class Tyre{
private String name;
public Tyre(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
class Frame{
private String name;
public Frame(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
两个接口
public interface CarBuilder {
Engine createEngine();
Tyre createTyre();
Frame createFrame();
}
public interface CarDirect {
Car assemble();
}
public class MyCarBuilder implements CarBuilder {
@Override
public Engine createEngine() {
System.out.println("张大爷牌发动机");
return new Engine("张大爷牌发动机");
}
@Override
public Tyre createTyre() {
System.out.println("跑得快轮子");
return new Tyre("跑得快轮子");
}
@Override
public Frame createFrame() {
System.out.println("汽车框架");
return new Frame("汽车框架");
}
}
public class MyCarDirect implements CarDirect {
private CarBuilder builder;
public MyCarDirect(CarBuilder builder) {
this.builder = builder;
}
@Override
public Car assemble() {
Engine engine=builder.createEngine();
Tyre tyre=builder.createTyre();
Frame frame=builder.createFrame();
//组装
Car car=new Car();
car.setEngine(engine);
car.setFrame(frame);
car.setTyre(tyre);
return car;
}
}
public class Client {
public static void main(String[] args) {
CarBuilder builder=new MyCarBuilder();
CarDirect direct=new MyCarDirect(builder);
Car car=direct.assemble();
System.out.println("组装完成");
car.lunch();
}
}
原型模式
import java.util.Date;
/**
* 浅克隆
*/
public class Mouse implements Cloneable{
private String name;
private Date birthday;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public Mouse(String name, Date birthday) {
this.name = name;
this.birthday = birthday;
}
@Override
protected Object clone() throws CloneNotSupportedException {
Object obj=super.clone();
return obj;
}
}
import java.util.Date;
public class Client {
public static void main(String[] args) throws CloneNotSupportedException {
Date date=new Date(13212132132132L);
Mouse mouse=new Mouse("小白", date);
Mouse mouse1=(Mouse)mouse.clone();
System.out.println(mouse1.getName()+"出生于"+mouse1.getBirthday());
System.out.println(mouse.getName()+"出生于"+mouse.getBirthday());
date.setTime(123456789L);//它们两指向相同的date对象
//原
System.out.println(mouse.getName()+"出生于"+mouse.getBirthday());
System.out.println(mouse1.getName()+"出生于"+mouse1.getBirthday());
}
}
import java.util.Date;
/**
* 深克隆
*/
public class Mouse2 implements Cloneable{
private String name;
private Date birthday;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public Mouse2(String name, Date birthday) {
this.name = name;
this.birthday = birthday;
}
@Override
protected Mouse2 clone() throws CloneNotSupportedException {
Object obj=super.clone();
//深克隆
Mouse2 mouse2=(Mouse2)obj;
mouse2.birthday=(Date)this.birthday.clone();
return mouse2;
}
}
使用序列化、反序列化实现深克隆
import java.io.*;
import java.util.Date;
/**
* 使用序列化及反序列化
*/
public class Client2 {
public static void main(String[] args) throws IOException, ClassNotFoundException {
Date date=new Date(13212132132132L);
Mouse mouse=new Mouse("小白", date);//Mouse必须实现Serializable 接口
ByteArrayOutputStream bos=new ByteArrayOutputStream();
ObjectOutputStream oos=new ObjectOutputStream(bos);
oos.writeObject(mouse);
byte[] bytes=bos.toByteArray();
ByteArrayInputStream bis=new ByteArrayInputStream(bytes);
ObjectInputStream ois=new ObjectInputStream(bis);
Mouse mouse2=(Mouse)ois.readObject();
System.out.println(mouse.getName()+"出生于"+mouse.getBirthday());
System.out.println(mouse2.getName()+"克隆出生于"+mouse2.getBirthday());
date.setTime(123456789L);//它们两指向相同的date对象
//原
System.out.println(mouse.getName()+"出生于"+mouse.getBirthday());
System.out.println(mouse2.getName()+"克隆出生于"+mouse2.getBirthday());
}
}
new方法和clone效率的比较
/**
* clone与new方法的比较
*/
public class Client3 {
public static void testNew(int size){
long start=System.currentTimeMillis();
for (int i=0;i<size;i++){
Laptop te=new Laptop();
}
long end=System.currentTimeMillis();
System.out.println("new耗时:"+(end-start));
}
public static void testClone(int size) throws CloneNotSupportedException {
Laptop temp=new Laptop();
long start=System.currentTimeMillis();
for (int i=0;i<size;i++){
Laptop te=(Laptop)temp.clone();
}
long end=System.currentTimeMillis();
System.out.println("Clone耗时:"+(end-start));
}
public static void main(String[] args) throws CloneNotSupportedException {
testNew(1000);
testClone(1000);
}
}
class Laptop implements Cloneable{
public Laptop() {
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@Override
protected Object clone() throws CloneNotSupportedException {
Object obj=super.clone();
return obj;
}
}