设计模式分类
创建型模式:工厂模式、建造者模式、原型模式、单例模式
结构型模式:适配器模式、桥接模式、组合模式、装饰模式、外观模式、享元模式、代理模式
行为型模式:解释器模式、模板方法模式、责任链模式、命令模式、迭代器模式、中介者模式、备忘录模式、观察者模式、状态模式、策略模式、访问者模式
面向对象的设计原则
单一职责原则:一个对象应该只包含单一的指责,并且该指责被完整的封装在一个类中。
开闭原则:尽量在不修改原有代码的基础上进行拓展。
里氏代换原则:使用基类对对象进行定义,在运行时再确定其子类类型。
依赖倒转原则:针对抽象层编程,采用抽象的形式注入。
合成复用原则:优先使用对象组合(注入),而不是通过继承来达到复用目的。
创建型模式
工厂模式
简单工厂模式:
抽象工厂模式:
建造者模式
应用场景:构造的对象复杂,且过程繁琐。
Builder:给出一个抽象接口,以规范产品对象的各个组成成分的建造。
ConcreteBuilder:实现Builder接口,具体化复杂对象的各部分创建。
Director:调用具体建造者来创建复杂对象的各个部分,在指导者中不涉及具体产品的信息,只负责保证对象各部分完整创建或按某种顺序创建。
Product:复杂产品。
原型模式
根据原型对象复制创建多个相同或相似的对象,如clone()。
克隆必须实现Cloneable接口。浅克隆不会复制引用成员,深克隆会复制引用成员。
package com.sjp.design.create.prototype; import java.util.ArrayList; import java.util.List; //如果要克隆就必须实现Cloneable接口 public class Person implements Cloneable{ private String name; private String sex; private List<String> list; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public List<String> getList() { return list; } public void setList(List<String> list) { this.list = list; } //浅克隆 @Override protected Person clone() { try { Person person = (Person) super.clone(); return person; } catch (CloneNotSupportedException e) { e.printStackTrace(); return null; } } //深克隆 // @Override // protected Person clone() { // try { // Person person = (Person) super.clone(); // List<String> newList = new ArrayList(); // // for (String str : this.list) { // newList.add(str); // } // person.setList(newList); // return person; // } catch (CloneNotSupportedException e) { // e.printStackTrace(); // return null; // } // } public static void main(String[] args) { Person p1 = new Person(); List<String> list = new ArrayList<String>(); list.add("123"); list.add("abc"); p1.setList(list); Person p2 = p1.clone(); System.out.println(p1 == p2); System.out.println(p1.getList() == p2.getList()); } }
浅克隆:false,true
深克隆:false,false
单例模式
静态变量,静态块是在类被使用的时候初始化的。
public class Singleton { private static Singleton instance = new Singleton(); private Singleton (){} public static Singleton getInstance() { return instance; } }
结构型模式
适配器模式
适配器解决这么一类问题:要访问的方法不再合适的接口里。
类适配器:访问的接口A中没有想要的方法,接口B中有合适的方法,这是我们可以定义适配器P实现A,继承B。
对象适配器:同上,适配器P实现A,注入B。
接口适配器:当存在一个接口定义了N多方法,而我们只想实现其中一到几个,这时可以中间加一层抽象类。
桥接模式
桥接模式的用意:将抽象化与实现化解耦,使得二者可以独立的变化。解耦,将两个类继承关系改为聚合关系,就是将强关联改为弱关联。
优点:
1.分离抽象部分和实现部分,极大提供了系统的灵活性,有助于系统分层,从而产生更好的结构化系统。
2.抽象和实现可以独立的拓展,互不影响,大大提高了系统的可拓展性。
桥接模式的结构:
实际场景
1)实现发送消息,实现方式有短信和邮件。设计如下:
2)消息又分为加急消息和普通消息,设计如下:
3)实现特加急消息,设计如下:
现在出现问题的根本原因,就在于消息的抽象和实现是混杂在一起的,这就导致了一个纬度的变化会引起另一个纬度进行相应的变化,从而使得程序扩展起来非常困难。
利用桥接模式,如下:
桥接模式在java中的使用:JDBC驱动器
装饰器模式
装饰器模式是使用对象的关联关系代替继承关系,无需通过继承增加子类来扩展对象新功能,更加灵活,避免类型体系的快速膨胀。
demo:变形金刚在变形前是一辆汽车,它可以在陆地上移动。当它变成机器人之后除了能够在陆地上移动之外,还可以说话;如果需要,它还可以变成飞机,除了在陆地上移动还可以在天空中飞翔。
Component(抽象构件):Transform.java,声明一个move方法,无论变形金刚如何改变该方法始终都有,是具体构件和抽象装饰类共有的方法。
package com.sjp.design.create.decorate; /** * Created by Timor on 2019/2/9. */ public interface Transform { void move(); }
ConcreteComponent(具体构件):Car.java 提供了move方法的实现,运用构造函数初始化输出当前状态,它是一个可以被装饰的类。在这里Car被声明为final类型,说明不能通过继承来拓展其功能,需运用类之间的关联关系来拓展。即装饰器模式
package com.sjp.design.create.decorate; /** * Created by Timor on 2019/2/9. */ public final class Car implements Transform { @Override public void move() { System.out.println("我会走"); } }
Decorator(抽象装饰类):Changer.java 定义一个抽象构件类型的transform,通过构造函数或者setter方法来给该对象赋值,同时也通过调用transform对象来实现move方法,这样可以保证原方法不被丢失,而且可以在它的子类中增加新的方法,拓展原有功能。
package com.sjp.design.create.decorate; /** * Created by Timor on 2019/2/9. */ public abstract class Changer implements Transform{ private Transform transform; public Changer(Transform transform) { this.transform = transform; } @Override public void move() { transform.move(); } abstract void say(); }
ConcreteDecorator(具体装饰类)
package com.sjp.design.create.decorate; /** * Created by Timor on 2019/2/9. */ public class SayCar extends Changer { public SayCar(Transform transform) { super(transform); } @Override void say() { System.out.println("我会说"); } }
AirCar中的air()方法采用半透明,作为一个单独的方法提供给客户端使用,客户端不能使用抽象构件来定义具体装饰对象
package com.sjp.design.create.decorate; /** * Created by Timor on 2019/2/9. * 半透明装饰模式 */ public class AirCar extends Changer{ public AirCar(Transform transform) { super(transform); } @Override void say() { System.out.println("我会说"); } void fly(){ System.out.println("我会飞"); } }
测试:
package com.sjp.design.create.decorate; /** * Created by Timor on 2019/2/9. */ public class Test { public static void main(String[] args) { Transform car = new Car(); car.move(); Changer sayCar = new SayCar(car); sayCar.move(); sayCar.say(); AirCar airCar = new AirCar(car); airCar.move(); airCar.say(); airCar.fly(); } }
代理模式
代理模式使用场景:对原有方法进行改进,采用一个代理类调用原来的方法,且对产生的结果进行控制。