GOF设计模式
创建型模式:
- 单例模式
- 工厂模式
- 抽象工厂模式
- 建造者模式
- 原型模式
结构型模式:
- 适配器模式
- 桥接模式
- 装饰模式
- 组合模式
- 外观模式
- 享元模式
- 代理模式
行为型模式:
- 模板方法模式
- 命令模式
- 迭代器模式
- 观察者模式
- 中介者模式
- 备忘录模式
- 解释器模式
- 状态模式
- 策略模式
- 职责连模式
- 访问者模式
单例模式
保证一个类只有一个实例对象,并提供访问方法
构造器私有,私有一个static属性保存类的实例,提供一个public方法获取这个实例
读取配置文件的类一般是单例
优点:只产生一个实例,减少系统开销。当一个对象的产生需要消耗很多资源时,比如读取配置,产生其他依赖对象等,则可以在应用启动时只产生一个
单例对象,永驻内存来解决。
单例模式可以在系统设置全局的访问点,优化环景共享资源访问,例如可以设计一个单例类,负责所有数据表的映射处理。
实现方式:
- 饿汉式
- 懒汉式
- 双重检测锁式
- 静态内部类式
- 枚举单例
饿汉式:线程安全,调用效率高,不能延时加载
public class SingletonDemo1 {
private static SingletonDemo1 instance = new SingletonDemo1(); //类初始化时立即加载
private SingletonDemo1(){};
public static SingletonDemo1 getInstance(){
return instance;
}
}
懒汉式:线程安全,并发效率低,可以按需加载
public class SingletonDemo2 {
private static SingletonDemo2 instance; //类初始化时立即加载
private SingletonDemo2(){};
public static SingletonDemo2 getInstance(){
if (instance==null) {
instance = new SingletonDemo2();
}
return instance;
}
}
每次调用getInstance方法需同步,并发效率低。
工厂模式:
- 简单工厂模式(静态工厂模式)
class CarFactory{
public static Car createCar(String type) {
if (type.equals("audi")) {
return new Audi();
}
if (type.equals("benz")) {
return new Benz();
}
}
}
缺点是违背了开闭原则,即向扩展开放,向修改关闭的原则。在需要创造新的产品种类时必须修改工厂的内部代码,否则无法扩展功能。
2.工厂方法模式
工厂方法模式定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。
interface CarFactory{
createCar();
}
class AudiCarFactory implements CarFactory{
@Override
Car createCar(){
return new Audi();
}
}
抽象工厂模式:
抽象工厂模式(Abstract Factory)是围绕一个超级工厂创建其他工厂。该超级工厂又称为其他工厂的工厂。每个工厂生产一组品种不同的产品,如果每个工厂只生产一种产品,
那就成了简单工厂模式了。抽象工厂模式提供一个创建一系列相关或相互依赖对象的接口,而无需指定他们具体的类。说白了它就是创建工厂的工厂。
class Mouse {
sayHi();
}
class KeyBo {
sayHi();
}
interface ComputerFactory{
Mouse createMouse();
KeyBo createKeyBo();
}
class HPComputerFactory implements ComputerFactory {
Mouse createMouse() {return HPMouse;}
KeyBo createKeyBo() {return HPKeyBo;}
}
建造者模式
又称生成器模式:将一个复杂的构建与其表示相分离,使得同样的构建过程可以创建不同的表示。
三个角色:建造者、具体的建造者、监工、使用者(严格来说不算)
- 建造者角色:定义生成实例所需要的所有方法;
- 具体的建造者角色:实现生成实例所需要的所有方法,并且定义获取最终生成实例的方法;
- 监工角色:定义使用建造者角色中的方法来生成实例的方法;
- 使用者:使用建造者模式。
注意:定义中“将一个复杂的构建过程与其表示相分离”,表示并不是由建造者负责一切,而是由监工负责控制(定义)一个复杂的构建过程,
由各个不同的建造者分别负责实现构建过程中所用到的所有构建步骤。不然,就无法做到“使得同样的构建过程可以创建不同的表示”这一目标。
创建者角色:
public abstract class Builder{
public abstract void buildPart1();
public abstract void buildPart2();
public abstract void buildPart3();
}
监工角色:
public class Watcher{
private Builder builder;
public Watcher(Builder builder){
this.builder = builder;
}
public void setBuilder(Builder builder){
this.builder = builder;
}
public void construct() { // 控制(定义)一个复杂的构建过程
builder.buildPart1();
for (int i = 0; i < 5; i++) { // 提示:如果想在运行过程中替换构建算法,可以考虑结合策略模式。
builder.buildPart2();
}
builder.buildPart3();
}
}
具体建造者:
/**
* 此处实现了建造纯文本文档的具体建造者。
* 可以考虑再实现一个建造HTML文档、XML文档,或者其它什么文档的具体建造者。
* 这样,就可以使得同样的构建过程可以创建不同的表示
*/
public class ConcreteBuilder extends Builder {
private StringBuffer buffer = new StringBuffer();//假设 buffer.toString() 就是最终生成的产品
@Override
public void buildPart1() {//实现构建最终实例需要的所有方法
buffer.append("Builder1 : Part1\n");
}
@Override
public void buildPart2() {
buffer.append("Builder1 : Part2\n");
}
@Override
public void buildPart3() {
buffer.append("Builder1 : Part3\n");
}
public String getResult() {//定义获取最终生成实例的方法
return buffer.toString();
}
}
使用建造者模式:
public class Client{
public void testBuilderPattern(){
Builder builder = new ConcreteBuilder();
Watcher watcher = new Watcher(builder);
watcher.construct();
String result = builder.getResult();
}
}
原型模式
当new一个对象时需要非常繁琐的数据准备或访问权限时,可以考虑原型模式。利用已有的一个原型对象,快速地生成和原型对象一样的实例。这个原型对象必须实现
java.lang.Cloneable接口,重写clone()
方法。这里面涉及到了深浅拷贝的问题。
public class Sheep implements Cloneable{
private String name;
private Date birthday;
public void setBirthday(Date b){
birthday =b;
}
public Date getBirthday(){
return birthday;
}
public void setName(String name){
this.name = name;
}
public String getName(){
return name;
}
public Sheep(String name,int age,Date birthday){
this.birthday = birthday;
this.name = name;
this.age = age;
}
@Override
protected Object clone(){
// 浅克隆
// return super.clone();
//deep clone
Object obj = super.clone();
Sheep s = (Sheep) obj;
s.birthday = (Date) this.birthday.clone(); //将引用属性也复制
return s;
}
}
class Test{
public void test(){
Sheep sheep1 = new Sheep("a",new Date(20180907));
Sheep sheep2 = sheep1.clone();
}
}
用序列化和反序列化实现深拷贝:
class User1 implements Serializable {
private String name;
private int age;
User1() throws IOException {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
public static void main(String[] args) throws IOException, ClassNotFoundException {
User1 a = new User1();
a.setAge(11);
a.setName("kelly");
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(a);
byte[] arr = bos.toByteArray();
ByteArrayInputStream bis = new ByteArrayInputStream(arr);
ObjectInputStream ois = new ObjectInputStream(bis);
User1 b = (User1) ois.readObject();
}
}
网友评论