设计模式简介
设计模式共有23种
- 关于构建类的 5种
- 工厂设计模式
Factory
- 抽象工厂设计模式
Abstract Factory
- 单例模式
Singleton
- 构建者模式
Builder
- 原型模式
Prototype
- 工厂设计模式
- 关于类结构的 7种
- 适配器模式
Adaptor
- 装饰器模式
Decorator
- 代理模式
Proxy
- 外观模式
Facade
- 桥接模式
Bridge
- 组合模式
Composite
- 享元模式
Cache
- 适配器模式
- 关于类行为的 11种
- 策略模式
Strategy
- 模板方法模式
Template
- 观察者模式
Observer
- 迭代子模式
Iterator
- 责任链模式
Chain
- 命令模式
Command
- 备忘录模式
Memo
- 状态模式
State
- 访问者模式
Visitor
- 中介者模式
Mediator
- 解释器模式
Interpreter
- 策略模式
设计模式的六大原则
- 开闭原则
对扩展开放,对修改关闭
- 里氏替换原则
所有使用父类的地方,一定可以用子类替换
- 依赖倒转原则
要依赖接口和抽象编程,而不是依赖具体类
- 接口隔离原则
尽量使用不同的接口,不要在一个接口中定义过多功能
- 迪米特原则或者最少知道原则
一个类要尽可能少的与其他类发生联系
- 合成复用原则
尽量使用聚合,避免使用继承
设计模式代码示例
下面是构造类型的5个设计模式
1.工厂设计模式
适用于批量生产拥有共同功能的不同规格的产品。
public class FactoryDesignPattern {
public static interface MessageSender{
void send(String message);
}
public static class MailMessageSender implements MessageSender{
public void send(String message) {
System.out.println(" sending mail . content: "+message);
}
}
public static class SmsMessageSender implements MessageSender{
public void send(String message) {
System.out.println(" sending mobile message . content: "+message);
}
}
public static class MessageSenderFactory{
public static MessageSender createMailMessageSender(){
return new MailMessageSender();
}
public static MessageSender createSmsMessageSender(){
return new SmsMessageSender();
}
}
public static void main(String[] args) {
MessageSender mailSender = MessageSenderFactory.createMailMessageSender();
mailSender.send("mail");
mailSender=MessageSenderFactory.createSmsMessageSender();
mailSender.send("sms");
}
}
2.抽象工厂模式
对于工厂模式,随着功能的迭代,需要不停的修改工厂类,甚至会出现需要不同版本的工厂类。此时对工厂类加一层抽象,来满足依赖倒转原则,便演化出了抽象工厂模式。
public class AbstractFactoryDesignPattern {
public static interface MessageSender{
void send(String message);
}
public static class MailMessageSender implements MessageSender {
private String version;
public MailMessageSender(String version) {
this.version = version;
}
public void send(String message) {
System.out.println((version==null?"":version)+" sending mail . content: "+message);
}
}
public static class SmsMessageSender implements MessageSender {
private String version;
public SmsMessageSender(String version) {
this.version = version;
}
public void send(String message) {
System.out.println((version==null?"":version)+" sending mobile message . content: "+message);
}
}
public static abstract class MessageSenderFactory{
public abstract MessageSender createMailMessageSender();
public abstract MessageSender createSmsMessageSender();
}
public static class MessageSenderFactoryV1 extends MessageSenderFactory{
public MessageSender createMailMessageSender() {
return new MailMessageSender("V1");
}
public MessageSender createSmsMessageSender() {
return new SmsMessageSender("V1");
}
}
public static class MessageSenderFactoryV2 extends MessageSenderFactory{
public MessageSender createMailMessageSender() {
return new MailMessageSender("V2");
}
public MessageSender createSmsMessageSender() {
return new SmsMessageSender("V2");
}
}
public static void main(String[] args) {
MessageSenderFactory messageSenderFactory=new MessageSenderFactoryV1();
MessageSender messageSender=messageSenderFactory.createMailMessageSender();
messageSender.send("mail");
messageSender=messageSenderFactory.createSmsMessageSender();
messageSender.send("sms");
}
}
3.单例模式
有些核心类,在web容器种只能创建一次,此时需要单例模式。单例模式的实现有很多种,主流的是double check加锁 和 static属性实现。
public class SingletonDesignPattern {
public static class SingletonBeanA{
//禁止外部创建
private SingletonBeanA(){}
private static SingletonBeanA singletonBeanA;
public static SingletonBeanA getInstance(){
if(singletonBeanA==null){
synchronized (SingletonBeanA.class){
if(singletonBeanA==null){
SingletonBeanA tmp=new SingletonBeanA();
//创建后的bean 一定不要直接赋值给 singletonBeanA
// necessary check , make sure bean is ok
singletonBeanA=tmp;
}
}
}
return singletonBeanA;
}
//序列化时保证单例
public Object readResolve(){
return getInstance();
}
}
public static class SingletonBeanB{
private SingletonBeanB(){};
//jvm 保证只初始化一次
private static SingletonBeanB singletonBeanB=new SingletonBeanB();
public static SingletonBeanB getInstance(){
return singletonBeanB;
}
//序列化时保证单例
public Object readResolve(){
return getInstance();
}
}
//通过enum 保证单例机制
public static enum SingletonBeanC{
instance;
SingletonBeanC() {
}
}
}
4.建造者模式
工厂模式关注的是批量生产对象,而建造者关注的是构建一个复杂的聚合对象。
public class BuilderDesignPattern {
// 一个复杂的难以理解的类
public static class ComplexBean{
String name;
Long concurrent;
int sleep;
ThreadHolder threadHolder;
public static class ThreadHolder{
Thread thread;
int tid;
}
}
//一个容易使用的 提供简易配置方法的构造者
public static class ComplexBeanBuilder{
private String name;
private Long concurrent;
public ComplexBeanBuilder name(String name){
this.name=name;
return this;
}
public ComplexBeanBuilder concurrent(Long concurrent){
this.concurrent=concurrent;
return this;
}
//复杂的构建逻辑
public ComplexBean build(){
ComplexBean complexBean=new ComplexBean();
complexBean.name=name;
complexBean.concurrent=concurrent;
complexBean.sleep=10;
ComplexBean.ThreadHolder threadHolder=new ComplexBean.ThreadHolder();
threadHolder.thread= Thread.currentThread();
complexBean.threadHolder=threadHolder;
return complexBean;
}
}
public static void main(String[] args) {
ComplexBean complexBean=new ComplexBeanBuilder().
name("name").concurrent(10L).build();
System.out.println(complexBean.name);
}
}
5.原型模式
原型模式在生产环境用的比较少,说白了就是将已有的对象作为原型复制一个新对象,实现方法有浅复制和深复制两种,分别可以通过clone和反序列化实现。
public class PrototypeDesignPattern {
public static class Holder implements Serializable{
private static final long serialVersionUID = 1L;
String name="holder";
}
public static class PrototypeBean implements Cloneable,Serializable{
private static final long serialVersionUID = 1L;
String name;
Holder holder;
//浅复制
public PrototypeBean copy() throws CloneNotSupportedException {
return (PrototypeBean)super.clone();
}
//深复制
public PrototypeBean deepCopy() throws IOException, ClassNotFoundException {
ByteArrayOutputStream byteArrayOutputStream=new ByteArrayOutputStream();
ObjectOutputStream objectOutputStream=new ObjectOutputStream(byteArrayOutputStream);
objectOutputStream.writeObject(this);
ByteArrayInputStream byteArrayInputStream=new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
ObjectInputStream objectInputStream=new ObjectInputStream(byteArrayInputStream);
return (PrototypeBean)objectInputStream.readObject();
}
}
public static void main(String[] args) throws Exception {
PrototypeBean prototypeBean=new PrototypeBean();
prototypeBean.name="good name";
Holder holder=new Holder();
prototypeBean.holder=holder;
PrototypeBean copy=prototypeBean.copy();
PrototypeBean deepCopy=prototypeBean.deepCopy();
assert copy.holder==holder;
assert deepCopy.holder!=null && deepCopy.holder!=holder;
}
}
下面是7种结构类型设计模式
6.适配器模式
顾名思义,适配器模式是用来将已有的类或者接口中的方法 组合转化成更加方便使用的方法, 适配器也可以提供默认实现方便子类继承使用。说白了,就是现实生活中的转换头。
public class AdaptorDesignPattern {
public static interface Phone{
boolean sendMessage(String message);
boolean call(String phoneNumber);
// represent the phone function that we don't even care
void functionA();
void functionB();
void functionC();
}
public static abstract class PhoneAdaptor implements Phone{
public void functionA() {
//default implement
}
public void functionB() {
//default implement
}
public void functionC() {
//default implement
}
}
public static void main(String[] args) {
Phone phone=new PhoneAdaptor() {
public boolean sendMessage(String message) {
System.out.println("sending message : "+message);
return true;
}
public boolean call(String phoneNumber) {
return true;
}
};
phone.sendMessage("hello world.");
}
}
7.装饰器模式
主要用于动态的在原有类的基础上添加功能,如添加缓存、增加日志等等。Decorator实现原有类相同的接口,对使用原有类的地方是透明的。
public class DecoratorDesignPattern {
public static interface IPhone{
boolean sendMessage(String message);
}
public static class Phone implements IPhone{
public boolean sendMessage(String message){
System.out.println("sending message : "+message);
return true;
}
}
public static class PhoneDecorator implements IPhone{
private DecoratorDesignPattern.Phone phone=new Phone();
public boolean sendMessage(String message) {
System.out.println("before send message.");
phone.sendMessage(message);
System.out.println("after send message.");
return true;
}
}
public static void main(String[] args) {
IPhone phone=new PhoneDecorator();
phone.sendMessage("message.");
}
}
8.代理模式
有一些业务操作十分复杂,客户并不关心内部的具体实现,客户可以通过托管给代理来实现对应的功能。代理还可以根据需要,对相应的功能做增强和扩展。
与装饰器的区别:装饰器对客户使用是透明的,主要在原有功能基础上额外添加客户无感知的功能;代理模式下用户必须感知代理,并且依赖代理的实现。
public class ProxyDesignPattern {
public static class Sing{
public void sing(){
System.out.println("i am singing...");
}
}
public static class SingProxy{
private Sing sing = new Sing();
public void sing(){
System.out.println("using proxy ... ");
sing.sing();
}
}
public static void main(String[] args) {
//用户感知代理的存在,并依赖代理的实现
SingProxy singProxy = new SingProxy();
singProxy.sing();
}
}
9.外观模式
为了降低业务之间的耦合关系,避免复杂的网状依赖关系,设计一个集中管理的Facade类。
类比于天朝的民主集中制,一切向Facade看齐,变将网状依赖变为更加清晰的星状依赖。
public class FacadeDesignPattern {
public static class BeanA{}
public static class BeanB{}
public static class BeanC{}
public static class Facade{
private static BeanA beanA=new BeanA();
private static BeanB beanB=new BeanB();
private static BeanC beanC=new BeanC();
public static BeanA getBeanA() {
return beanA;
}
public static BeanB getBeanB() {
return beanB;
}
public static BeanC getBeanC() {
return beanC;
}
}
public static void main(String[] args) {
BeanA beanA=Facade.getBeanA();
//do some thing with beanA
}
}
10.桥接模式
将抽象与实现分离,从而使二者可以独立变化。换句话,就是在抽象与具体实现之间添加一个中间类。通常在适配驱动的场景下,使用桥接模式。
public class BridgeDesignPattern {
public static interface Driver{
String run(String key);
}
public static class DriverA implements Driver{
public String run(String key){
return "driver A : "+key;
}
}
public static class DriverB implements Driver{
public String run(String key) {
return "driver B : "+key;
}
}
public static interface DataManager{
String read(String key);
//不依赖Driver是否实现 而新增功能
boolean write(String key,String value);
}
public static class DataManagerBridge implements DataManager{
Driver driver;
public String read(String key) {
if(driver!=null) return driver.run(key);
return null;
}
// 虽然driver 暂时不支持写入,可以在桥接器中提供默认实现
public boolean write(String key, String value) {
return false;
}
}
public static void main(String[] args) {
DataManagerBridge dataManagerBridge=new DataManagerBridge();
//桥接器注入 具体driver实现
dataManagerBridge.driver=new DriverA();
System.out.println(dataManagerBridge.read("key"));
System.out.println(dataManagerBridge.write("key","value"));
}
}
11.组合模式
主要用来构建一些稍复杂的数据结构,如二叉树、B+树等。
代码示例略,请参考二叉树实现。
12.享元模式
主要用来缓存对象示例,减少新建对象的开销。最典型的应用是数据库连接池、线程池等。
代码示例略,请参考数据库连接池实现。
行为设计模式 11种
13.策略模式
封装一系列的算法,每个算法为一个实现类,实现共同的接口。由外部用户的输入,动态的决定使用哪个算法。
常见用于决策算法,以及个性化或场景化推荐系统。
public class StrategyDesignPattern {
public static interface Recommend{
String recommendProduct();
}
public static class ManRecommend implements Recommend{
public String recommendProduct() {
return "Cars";
}
}
public static class WomanRecommend implements Recommend{
public String recommendProduct() {
return "Flowers";
}
}
public static class RecommendManager{
public String recommend(Map<String,String> params){
Recommend recommend=null;
if(params.containsKey("man")) recommend=new ManRecommend();
else recommend=new WomanRecommend();
return recommend.recommendProduct();
}
}
public static void main(String[] args) {
Map<String,String> map=new HashMap<String, String>();
System.out.println(new RecommendManager().recommend(map));
}
}
14.模板模式
由抽象类定义一些列的抽象方法或实现方法,子类只需实现必要的抽象方法。多用于业务流程的抽象,极大提高代码复用性。
代码示例略。
15.观察者模式
类似于发布订阅的Server主动推送模型。观察者将自己注册到发布者中,当有观察者关心的时间发生时,发布者会回调观察者。
代码示例略。
16.迭代子模式
提供集合遍历的统一接口,参考jdk中集合类的实现。
17.责任链模式
将一系列的处理实体类串联起来,按顺序依次调用,直到有实体类决定终止向后调用并处理请求。典型的例子是web应用的FilterChain。
18.命令模式
主要目的是将调用者和实现者解耦,调用者只需关注发号Command,实现者实现具体逻辑,Command中需要注入实现者。
19.备忘录模式
将对象某时刻的状态整个保存下来,在适当的时候可以恢复。
20.状态模式
当对象的状态改变时,对外表现出明显不同的行为。类比qq状态改变,qq好友就可能无法发出振动。
21.访问者模式
适合数据结构很稳定,但算法经常改变的情况。客户可以定义多个Visitor, Subject被访问者只需要accept访问者,并提供通用的数据访问。
22.中介者模式
目的是解耦类之间的调用,通过统一的Mediator来协调调用。典型的生活例子是租房,租房者和房东都去找中介者,中介来协调合同签订。
每个相关的类只需要持有中介者的引用,中介者持有所有相关类的引用。
23.解释器模式
主要用于解释器的实现。