一、设计模式分类
总体来说设计模式分为三大类:
创建型模式,五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式
结构型模式,七种:适配器模式、装饰器模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式
二、设计模式的六大原则
1、开闭原则(Open Close Principle)
对扩展开发,对修改关闭。对程序进行扩展时,不能修改原有代码,实现一个热拔插效果。
2、里氏替换原则(Liskov Substitution Principle)
任何基类出现的地方,子类一定可以出现。
3、依赖倒转原则(Dependence Inversion Principle)
面向接口编程,依赖于抽象,不依赖于具体实现。
好处:减少类间耦合,提高系统稳定性,降低并发风险,提高代码可读性和可维护性。
4、接口隔离原则(Interface Segregation Principle)
使用多个隔离的接口,比使用单个接口要好。主要目的还是为了降低耦合。
5、迪米特法则(最少知道原则)(Demeter Principle)
一个实体应当尽量少的与其他实体发生相互作用,使系统功能模块相对独立。
6、单一职责原则(Single responsibility principle)
有且仅有一个原因引起类的变更。
三、16种设计模式
1、工厂方法模式
使一个类的实例化延迟到其子类。
适用性:
当一个类不知道它所必须创建的对象的类的时候。
当一个类希望由它的子类决定它所创建的对象的时候。
1.1 普通工厂
public interface Sender {
public void send();
}
public class MailSender implements Sender {
@Override
public void send() {
System.out.println("this is mailsender!");
}
}
public class SmsSender implements Sender {
@Override
public void send() {
System.out.println("this is smssender!");
}
}
// 工厂
public class SendFactory {
public Sender produce(String type) {
if ("mail".equals(type)) {
return new MailSender();
} else if ("sms".equals(type)) {
return new SmsSender();
} else {
System.out.println("请输入正确的类型");
return null;
}
}
}
public class Test {
public static void main(String[] args) {
SendFactory sf = new SendFactory();
Sender sender = sf.produce("sms");
sender.send();
}
}
输出:this is smssender!
1.2 多工厂方法模式
public class SenderFactory {
public Sender produceMail() {
return MailSender();
}
public Sender produceSms() {
return SmsSender();
}
}
public class Test {
public static void main(String[] args) {
SenderFactory sf = new SendFactory();
Sender sender = sf.produceMail();
sender.send();
}
}
1.3 静态工厂模式
public class SendFactory {
public static Sender produceMail() {
return new MailSender();
}
public static Sender produceSms() {
return new SmsSender();
}
}
public class Test {
public static void main(String[] args) {
Sender sender = SenderFactory.produceMail();
sender.send();
}
}
2、单例模式
保证在JVM中,该对象只有一个实例存在
好处:1、类创建比较频繁,对于一些大的类,系统开销大
2、省去了new,降低了系统内存的使用频率,减轻GC压力
3、只能创建一个对象的类(一个军队只能有一个司令)
适用范围:1、读取配置文件,读取一次全局使用 2、日志文件 3、线程池等
饿汉模式:加载时比较慢,运行时获取对象速度快,线程安全。
饱汉模式:加载时比较快,运行时获取对象速度慢,线程不安全。
// 饿汉模式
public class SingleTest1 {
private static SingleTest1 st1 = new SingleTest1();
public static SingleTest1 getInstance() {
return st1;
}
}
// 饱汉模式
public class SingleTest2 {
private static SingleTest2 st2 = null;
public static SingleTest2 getInstance() {
if (st2 == null) {
synchronized(st2) {
st2 = new SingleTest2();
}
}
return st2;
}
}
单例模式与静态类的区别:
1、静态类不能实现接口
2、单例模式可以延迟实例化,静态类只能立即实例化
3、单例类可以被继承,方法可以被覆盖,静态类都是静态方法,无法被覆盖
4、单例类比较灵活
3、建造者模式
将很多功能集成到一个类里。与工厂模式的区别:工厂模式关注创建单个产品,建造者模式关注创建符合对象多个部分;工厂模式侧重把一个类实例化延迟到子类,建造者模式侧重保持一个对象创建过程的稳定性。
public class Builder {
private List<Sender> list = new ArrayList<Sender>();
public void produceMailSender(int count) {
for(int i =0; i < count; i ++) {
list.add(new MailSender());
}
}
public void produceSmsSender(int count) {
for(int i =0; i < count; i ++) {
list.add(new SmsSender());
}
}
}
4、原型模式
将一个对象进行复制、克隆,产生一个与与原对象类似的对象。(浅复制)
public class ProtoTest implements Cloneable{
public Object clone() throws CloneNotSupportedException {
ProtoTest pt = super.clone();
return pt;
}
}
5、适配器模式
当想要使用一个已经存在的类,但是该类的接口不符合现有的需求时,需要将类的接口转换成客户期望的另一个接口,可使用适配器模式。
分为类适配器、对象适配器、接口适配器
6、装饰模式
将一个对象进行小的调整,同时希望经过调整的行为能和原有行为混合。给一个对象动态添加一些新的功能
public interface Source {
public void method();
}
public SourceImpl implements Source {
public void method() {
System.out.println("method");
}
}
public Decorator implements Source {
public SourceImpl source;
public Decorator(SourceImpl source) {
this.source = source;
}
public void method() {
System.out.println("before");
source.method();
System.out.println("after");
}
}
public class Test {
public static void main(String[] args) {
Source source = new SourceImpl();
Source source = new Decorator(source);
source.method();
}
}
7、外观模式
解决类与类之间的依赖关系,将类与类之间的关系放到配置文件中,降低类与类之间的耦合。
如:启动一台电脑,它会依次启动CPU、Memory、DISK等,对用户来说是启动了一台电脑。
8、桥接模式
将事物与其具体实现分开,将抽象化与实现化解耦,使得两者可以独立变化。
如:JDBC连不同类型数据库。
9、享元模式
目的是实现对象的共享,如共享池
public class ConnectionPool {
private Vector<Connection> pool;
private String url = "jdbc:mysql://localhost:3306/test";
private String username = "root";
private String passwd = "root";
private String driverClassName = "com.mysql.jdbc.Driver";
private int poolSize = 100;
private static ConnectionPool connectionPool = null;
Connection conn = null;
private ConnectionPool() {
pool = new Vector<Connection>();
try {
for(int i = 0; i < poolSize; i ++) {
Class.forname(driverClassName);
conn = DriverManager.getConnection(url, username, passwd);
pool.add(conn);
}
} catch(Exception e) {
e.printStackTrace();
}
}
}
public synchronized void release() {
pool.add(conn);
}
public synchronized Connection getConnection() {
if (pool.size() > 0) {
Connection conn = pool.get(0);
pool.remove(conn);
return conn;
}else {
return null;
}
}
10、观察者模式
当一个对象变化时,其他依赖该对象的对象会收到通知,并且随着变化。
public interface Observer {
public void update();
}
public class Observer1 implements Observer {
@Override
public void update() {
System.out.println("observer1 has received!");
}
}
public class Observer2 implements Observer {
@Override
public void update() {
System.out.println("observer2 has received!");
}
}
public interface Subject {
// 增加观察者
public void add(Observer observer);
// 删除观察者
public void del(Observer observer);
// 通知所有观察者
public void notifyObservers();
public void operation();
}
public abstract class AbstractSubject implements Subject {
private Vector<Observer> vector = new Vector<Observer>();
@Override
public void add(Observer observer) {
vector.add(observer);
}
@Override
public void del(Observer observer) {
vector.remove(observer);
}
@Override
public void notifyObservers() {
Enumeration<Observer> enumo = vector.elements();
while(enumo.hasMoreElements()) {
enumo.nextElement().update();
}
}
}
public class MySubject extends AbstractSubject {
@Override
public void operation() {
System.out.println("update self!");
notifyObservers();
}
}
public class Test {
public static void main(String[] args) {
Subject subject = new MySubject();
subject.add(new Observer1());
subject.add(new Observer2());
subject.operation();
}
}
11、责任链模式
有多个对象,每个对象持有对下一个对象的引用,形成一条链,请求在链上传递,直到某一个对象决定处理该请求。但发出者并不知道谁处理了该请求,可在隐瞒客户端情况下,对系统进行动态调整。
12、命令模式
司令员发布命令,口令经过传递,传到士兵耳朵里,士兵去执行。三者相互解耦。实现请求和执行分开
13、备忘录模式
保存一个对象的某个状态,以便在适当的时候恢复正常
14、状态模式
对象的状态改变时,同时改变其行为(如:权限控制)
15、访问者模式
把数据结构和作用于结构上的操作解耦,使得操作集合可相对自由地演化。通过这种分离,可达到为一个被访问者对象动态添加新的操作而无需做其他修改的效果。
16、中介者模式
用来降低类与类之间的耦合,两个类有关联,需要两者互相持有对方的引用,耦合度高。引入一新类,提供统一的接口实现解耦。