23中设计模式介绍,主要分为三大类:
- 创建型(创建对象)
- 结构型(自身扩展)
- 行为型(对象间解耦)
创建类模式
Factory
public class SendFactory{
public static Sender produce(String name){
if("mail".equals(name))
return new MailSender();
else if("sms".equals(name))
return new SmsSender();
else
return null;
}
}
public interface Sender{
public void Send();
}
public class MailSender implements Sender{...}
public class SmsSender implements Sender{...}
// Test
Sender sender=SenderFactory.produce("mail");
sender.send();
Abstract Factory
拓展性比Factory Pattern好
public interface Provider{
public Sender provide();
}
public class MailFactory implements Provider{...} // new MailSender
public class SmsFactory implements Provider{...} // new SmsSender
// Test
Provider provider = new MailFactory();
Sender sender=provider.provide();
sender.send();
Builder
工厂模式关注创建单个产品 建造者模式关注创建多个产品
public class Builder {
private List<Sender> list = new ArrayList<Sender>();
public void produce(String name,int count){
if("mail".equals(name)){
for(int i=0; i<count; i++){
list.add(new MailSender());
}
}else{
for(int i=0; i<count; i++){
list.add(new SmsSender());
}
}
}
}
Builder builder = new Builder();
builder.produce("mail",10);
builder.produce("sms",10);
Singleton
public class Singleton{
// 可再加入volatile:禁止指令重排序优化 (Java 5 之后修复)
private static Singleton instance=null;
// 构造函数私有化,防止被外部实例化
private Singleton(){}
// 静态方法,创建实例
public static Singleton getInstance(){
if(instance==null)
syncInit()
return instance;
}
private static synchronized void syncInit() {
if (instance == null) {
instance = new Singleton(); // 注意:这并不是一个原子操作
}
}
...
}
优化1:使用私有静态内部类private static nested class
- 懒加载
- 线程安全
- 读取实例的时候不会进行同步,没有性能缺陷
- 不依赖 JDK 版本
public class Singleton {
private Singleton() { }
public static Singleton getInstance() {
return SingletonFactory.instance;
}
private static class SingletonFactory {
private static Singleton instance = new Singleton();
}
// 可采用"影子实例"的办法为单例对象的属性同步更新
private Vector properties = null;
public Vector getProperties() {
return properties;
}
public void updateProperties() {
Singleton shadow = new Singleton();
properties = shadow.getProperties();
}
}
//Test
Singleton singleton=Singleton.getInstance();
优化2:使用枚举enum
- 自由序列化
- 线程安全
- 保证只有一个实例(即使使用反射机制也无法多次实例化一个枚举量)
public enum Singleton{
INSTANCE;
private Singleton(){}
}
//Test
Singleton singleton=Singleton.INSTANCE;
注:参考《Effective Java》
Prototype
将一个对象作为原型,对其进行复制、克隆,产生一个和原对象类似的新对象
//实现Cloneable接口(空接口)
public class Prototype implements Cloneable, Serializable {
private String str;
private MyObject obj;
// 浅复制(基本数据类型)
// 需调用super.clone();
public Object clone() throws CloneNotSupportedException {
Prototype proto = (Prototype) super.clone();
return proto;
}
// 深复制(基本数据类型+引用类型)
// 需要采用流的形式读入当前对象,再写出
public Object deepClone() throws IOException, ClassNotFoundException {
// 写入当前对象的二进制流
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(this);
// 读出二进制流产生的新对象
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bis);
return ois.readObject();
}
//get/set
...
}
public class MyObject implements Serializable {
...
}
结构类模式
对象的适配器模式是各种模式的起源
Adapter
适配器模式
- 将某个类的接口转换成客户端期望的另一个接口表示
- 目的:消除由于接口不匹配所造成的类的兼容性问题
主要分为三类:
类的适配器模式:
- Adapter类继承Source类,实现Targetable接口
场景:希望将一个类转换成满足另一个新接口的类时
public class Source { public void method1() { ... } } public interface Targetable { public void method1(); // 扩展方法 public void method2(); }
public class Adapter extends Source implements Targetable { @Override public void method2() { ... } }
//Test Targetable target = new Adapter(); target.method1(); target.method2();
对象的适配器模式:
- Adapter类持有Source类的实例,调用Source实例的方法
- 场景:希望将一个对象转换成满足另一个新接口的对象
public class Adapter implements Targetable { private Source source; public Adapter(Source source){ super(); this.source = source; } @Override public void method1() { source.method1(); } @Override public void method2() { ... } }
//Test Targetable target = new Adapter(new Source()); target.method1(); target.method2();
接口的适配器模式:
- Adapter类继承一个抽象类(实现了Targetable接口),重写方法
- 场景:不希望实现一个接口中所有的方法时
public class AbstractTarget implements Targetable{ public void method1(){ ... } public void method2(){ ... } } public class Adapter extends AbstractTarget{ @Override public void method1(){ ... } }
//Test Targetable target=new Adapter(); target.method1(); target.method2();
Decorator
装饰模式
- 动态给一个对象增加一些新的功能
- 应用场景:
- 扩展一个类的功能
- 动态的为一个对象增加撤销功能(继承的功能是静态的,不能动态增删)
- 实现方式:
- Target:被装饰类
- Decorator:装饰类
- Target和Decorator实现同一个接口
- Decorator对象持有Target对象,为Target动态的添加取消功能
示例:
public interface Targetable { public void method(); }
public class Target implements Targetable { @Override public void method() { ... } } public class Decorator implements Targetable { private Targetable target; // 通过构造函数传入Target对象 public Decorator(Targetable target){ super(); this.target = target; } // 扩展Target方法 @Override public void method() { ... target.method(); ... } }
//Test Targetable obj=new Decorator(new Source()); obj.method();
- 缺点:产生过多相似的对象,不易排错
Proxy
代理模式:相较于Decorator,Proxy通过自己创建Target对象,来持有Targe对象 (将功能划分的更加清晰,有助于后期维护)
public class Proxy implements Targetable {
private Targetable target;
// 在构造函数中创建Target对象
public Proxy(){
super();
this.target = new Target();
}
// 扩展Target方法
@Override
public void method() {
...
target.method();
...
}
}
//Test
Targetable obj=new Proxy();
obj.method();
Facade
外观模式:为了解决类与类之家的依赖关系 (将依赖放在一个Facade类中,降低类与类之间的耦合度,类似Spring将通过配置文件维护各个bean的依赖关系)
public class A{...}
public class B{...}
public class Facade{
private A a;
private B b;
public Facade(){
a=new A();
b=new B();
}
public void method(){
a.xxx();
b.xxx();
...
}
}
//Test
Facade facade = new Facade();
facade.method();
Bridge
桥接模式:将抽象与实现解耦,使得二者可以独立变化
类似:DriverManager与JDBC桥接(统一接口),在各个数据库(提供各自实现)之间进行切换 用一个叫做数据库驱动的程序来桥接就行了。
// 统一接口
public interface Targetable {
public void method();
}
//各自实现
public class TargetSub1 implements Targetable {
@Override
public void method() {... }
}
public class TargetSub2 implements Targetable {
@Override
public void method() { ... }
}
// 桥接:抽象方法,通过set传入Target对象,自定义调用Target方法
public abstract class Bridge {
private Targetable target;
public void method(){
target.method();
}
//get/set
...
}
// 桥接扩展
public class MyBridge extends Bridge {
public void method(){
getTarget().method();
}
}
//Test
Bridge bridge = new MyBridge();
// 调用第一个对象
bridge.setTarget(new TargetSub1());
bridge.method();
// 调用第二个对象
bridge.setTarget(new TargetSub2());
bridge.method();
Combine
组合模式:部分-整体模式,将多个对象组合在一起进行操作(常用场景:树形结构)
public class Tree {
TreeNode root = null;
public Tree(String name) {
root = new TreeNode(name);
}
}
public class TreeNode {
private String name;
private TreeNode parent;
private Vector<TreeNode> children = new Vector<TreeNode>();
public TreeNode(String name){
this.name = name;
}
//get/set
...
//添加孩子节点
public void add(TreeNode node){
children.add(node);
}
//删除孩子节点
public void remove(TreeNode node){
children.remove(node);
}
}
// Test
Tree tree = new Tree("A");
TreeNode nodeB = new TreeNode("B");
TreeNode nodeC = new TreeNode("C");
tree.root.add(nodeB);
nodeB.add(nodeC);
Flyweight
享元模式:实现对象的共享,即共享池 (对象多的时候可以减少内存的开销,一般为单例,可参考数据库连接池的实现)
public class ConnectionPool {
private Vector<Connection> pool;
/*公有属性*/
private String url = "jdbc:mysql://localhost:3306/test";
private String username = "root";
private String password = "root";
private String driverClassName = "com.mysql.jdbc.Driver";
private int poolSize = 100;
Connection conn = null;
private static ConnectionPool instance = null;
private ConnectionPool() {
pool = new Vector<Connection>(poolSize);
for (int i = 0; i < poolSize; i++) {
try {
Class.forName(driverClassName);
conn = DriverManager.getConnection(url, username, password);
pool.add(conn);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
/* 返回连接到连接池 */
public synchronized void release() {
pool.add(conn);
}
/* 返回连接池中的一个数据库连接 */
public synchronized Connection getConnection() {
if (pool.size() > 0) {
conn = pool.get(0);
pool.remove(conn);
return conn;
} else {
return null;
}
}
}
行为类模式
Strategy
策略模式:定义了一系列算法,封装起来,可随意替换
场景:适用于当一个应用程序需要实现一种特定的服务或者功能,而且该程序有多种实现方式时使用(决定权在用户,系统本身提供不同的实现)
PS: 可参考java.util
中Collections
算法类的使用和实现
//统一接口
public interface IStrategy {
public void operate();
}
//各个策略实现类(具体对象)
public class Strategy1 implements IStrategy {
@Override
public void operate() {...}
}
public class Strategy2 implements IStrategy {
@Override
public void operate() { ... }
}
// 环境类(引用策略)
public class Context{
private IStrategy strategy;
public Context(IStrategy strategy){
this.strategy=strategy;
}
public operate(){
this.strategy.opreate();
}
}
// Test
Context ctx=new Context(new Strategy1());
ctx.operate();
Template
模板模式:在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中,使得子类可以在不改变算法结构的情冴下,重新定义算法中的某些步骤
抽象类和具体子类的之间的协作
- 抽象类:给出一个算法的骨架和搭建步骤
- 基本方法:搭建步骤(抽象方法,由子类具体实现)
- 模板方法:骨架(基本方法的汇总)
- 子类:提供这个算法搭建步骤的具体实现
PS:可参考HttpServlet
抽象类
(提供了一个service方法,这个方法调用七个do方法中的一个或几个,完成对客户端调用的响应,这些do方法需要由HttpServlet的具体子类提供,这是典型的模板模式)
public abstract class AbstractTemplate{
protected abstract void abstractMethod1();
protected abstract void abstractMethod2();
protected void hookMethod(){...}
public void templateMethod(){
abstractMethod1();
abstractMethod2();
hookMethod();
...
}
}
public ConcreteTemplate extends AbstractTemplate{
@Override
public void abstractMethod1(){...}
@Override
public void abstractMethod2(){...}
@Override
public void hookMethod(){...}
}
// Test
AbstractTemplate template=new ConcreteTemplate();
template.templateMethod();
Observer
订阅者模式:发布-订阅(Publish/Subscribe)模式
对象之间是一种一对多的关系: 让多个观察者对象同时监听某一个主题对象 这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己
- Subject:主题(接口/抽象类,可增加删除观察者对象)
- Observer:观察者(接口/抽象类,在得到Subject通知时更新自己)
- ConcreteSubject:具体主题
- ConcreteObserver:具体观察者
public interface Subject {
public void add(Observer observer);
public void del(Observer observer);
public void notifyObservers(); // 通知Observer
public void operation(); //自身的操作
}
public interface Observer {
public void update();
}
// Subject 实现类:
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 ConcreteSubject extends AbstractSubject {
@Override
public void operation() {
System.out.println("update self!");
notifyObservers();
}
}
// Observer 实现类:
public class ConcreteObserver1 implements Observer {
@Override
public void update() {
System.out.println("observer1 has received!");
}
}
public class ConcreteObserver2 implements Observer {
@Override
public void update() {
System.out.println("observer2 has received!");
}
}
// Test
Subject subject = new ConcreteSubject();
subject.add(new ConcreteObserver1());
subject.add(new ConcreteObserver2());
subject.operation();
Iterator
迭代器模式
- 又叫做游标(Cursor)模式
- 顺序访问容器(Container)中的各个对象,且不需暴露内部细节
- 常使用JDK提供的迭代接口
Iterator
进行collection
的遍历Iterator it = list.iterator(); while(it.hasNext()){ //using “it.next();”do some businesss logic }
实现:
- Iterator
- Container
- ConcreteIterator
- ConcreteContainer
一是需要遍历的对象,即聚集对象,二是迭代器对象,用于对聚集对象进行遍历访问
这个思路和我们常用的一模一样,MyCollection中定义了集合的一些操作,MyIterator中定义了一系列迭代操作,且持有Collection实例
两个接口
public interface Container {
public Iterator iterator();
public Object get(int i);
public int size();
}
public interface Iterator {
public Object previous();
public Object next();
public boolean hasNext();
}
public class ConcreteContainer implements Container {
public String string[] = {"A","B","C","D","E"};
@Override
public Iterator iterator() {
return new ConcreteIterator(this);
}
@Override
public Object get(int i) {
return string[i];
}
@Override
public int size() {
return string.length;
}
}
public class ConcreteIterator implements Iterator {
private Container container;
private int pos = -1;
public ConcreteIterator(Container Container){
this.container = container;
}
@Override
public Object previous() {
if(pos > 0){ pos--; }
return container.get(pos);
}
@Override
public Object next() {
if(pos<container.size()-1){pos++; }
return container.get(pos);
}
@Override
public boolean hasNext() {
return pos<container.size()-1?true:false;
}
}
// Test
Container container = new ConcreteContainer();
Iterator it = container.iterator();
while(it.hasNext()){
System.out.println(it.next());
}
Chain of Responsibility
责任链模式:
- 有多个对象,每个对象持有对下一个对象的引用,这样就会形成一条链
- 请求在这条链上传递,直到某一对象决定处理该请求。
- 发出者并不清楚到底最终那个对象会处理该请求
- 所以,责任链模式可以实现在隐瞒客户端的情况下,对系统进行动态的调整
实现:
- Handler:抽象处理者
- ConcreteHandler:具体处理者(持有下家的引用,可将请求处理掉,或将请求传给下家)
PS:
- 链接上的请求可以是一条链,可以是一个树,还可以是一个环,模式本身不约束这个;
- 在一个时刻,命令只允许由一个对象传给另一个对象,而不允许传给多个对象
public abstract class Handler {
// 持有handler
private Handler handler;
public Handler getHandler() {
return handler;
}
public void setHandler(Handler handler) {
this.handler = handler;
}
// 处理方法,抽象
public abstract void handlerRequest(String condition);
}
public class ConcreteHandler1 extends Handler {
@Override
public void handlerRequest(String condition) { ... }
}
public class ConcreteHandler2 extends Handler {
@Override
public void handlerRequest(String condition) { ... }
}
public class ConcreteHandler3 extends Handler {
@Override
public void handlerRequest(String condition) { ... }
}
//Test
ConcreteHandler1 handler1 = new ConcreteHandler1();
ConcreteHandler2 handler2 = new ConcreteHandler2();
ConcreteHandler3 handler3=new ConcreteHandler3();
handler1.setHandler(handler2);
handler2.setHandler(handler3);
// handler1 => handler2 => handler3
handler1.operator();
Command
命令模式:
- 将来自客户端的不同的请求(命令)传入一个对象(根据命令执行操作)
- 达到命令的发出者和执行者之间解耦,实现请求和执行分开
实现:
- Invoker:调用者(司令员)
- Receiver:被调用者(士兵)
- Command:命令
- ConcreteCommand:实现了Command接口,持有接收对象
// 调用者(包含命令)
public class Invoker {
private Command command;
public void setCommand(Command command){
this.command=command;
}
public void execute(){
this.command.execute();
}
}
// 命令接收者
public class Receiver {
public void action(){
// 真正执行命令操作的功能代码
System.out.println("command received!");
}
}
// 命令
public interface Command {
public void execute();
}
// 具体命令(包括命令接收者)
public class ConcreteCommand implements Command {
private Receiver receiver;
public ConcreteCommand(Receiver receiver) {
this.receiver = receiver;
}
@Override
public void execute() {
receiver.action();
}
}
// Test
Invoker invoker = new Invoker(); // 创建命令调用者
Command cmd = new ConcreteCommand(new Receiver()); // 构造具体命令
invoker.setCommand(cmd); // 装入命令
invoker.execute(); // 发送命令
Memento
备忘录模式:
- 快照模式(Snapshot Pattern)或Token模式
- 在不破坏封闭的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,以后可将该对象恢复到原先保存的状态
- 场景:适用于对象在执行某些操作为防止意外而在执行操作前将对象状态备份的场景(有点类似事务回滚的意思)
实现:
- Originator:发起人(包括内部状态和备忘录)
- Memento:备忘录(需保存的内容)
- Caretaker:管理备忘录
public class Originator {
private String value;
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public Memento createMemento(){
return new Memento(value);
}
public void restoreMemento(Memento memento){
this.value = memento.getValue();
}
}
public class Memento {
private String value;
public Memento(String value) {
this.value = value;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
public class Caretaker {
private Memento memento;
public Memento getMemento() {
return memento;
}
public void setMemento(Memento memento) {
this.memento = memento;
}
}
// Test
Originator origi=new Originator(); // 创建发起对象
Caretaker storage=new Caretaker(); // 创建管理者
origi.setValue("Test");
origi.setMemento(origi.createMemento()); // 暂存状态
origi.setValue("Test too");
origi.restoreMemento(storage.getMemento()); // 恢复状态
State
状态模式:当对象的状态改变时,同时改变其行为
- State
- ConcreteState
- Context
public interface State{
public void handler(Context context);
}
public class Context {
private State state;
public Context(State state){
this.state = state;
}
public State getState() {
return state;
}
public void setState(State state) {
this.state = state;
}
public void handler() {
this.state.handler(this);
}
}
public class ConcreteState1 extends State{
@Override
public void handler(Context context)(){
System.out.println("Current State 1");
// 设置下一状态为2
context.setState(new ConcreteState2());
}
}
public class ConcreteState2 extends State{
@Override
public void handler(Context context)(){
System.out.println("Current State 2");
// 设置下一状态为1
context.setState(new ConcreteState1());
}
}
// Test
Context context = new Context(new ConcreteState1());
context.handler();
context.handler();
Visitor
访问者模式:
- 一种分离对象数据结构与行为的方法
- 封装一些施加于某种数据结构元素之上的操作,一旦这些操作需要修改的话,接受这个操作的数据结构则可以保持不变
- 适用于数据结构相对稳定的系统,把数据结构和算法解耦
实现:
- Vistor
- Element
- ObjectStructure
- ConcreteVisitor
- ConcreteElement
PS: Vistor 和 Element的都可自行扩展,会不影响(相对独立,双重分派)
// 访问Element,可对Element提出某些操作
public interface Visitor {
public void visit(Element element);
}
// 接收访问者,提供处理方法
public interface Element {
public void accept(Visitor visitor);
public void doSomething();
}
public class ConcreteVisitor1 implements Visitor {
@Override
public void visit(Element element) {
//element.doSomething();
}
}
public class ConcreteVisitor2 implements Visitor {
@Override
public void visit(Element element) {
//element.doSomething();
}
}
public class ConcreteElement1 implements Element{
@Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
@Override
public void doSomething() { ... }
}
public class ConcreteElement2 implements Element{
@Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
@Override
public void doSomething() { ... }
}
public class ObjectStruture{
private List<Element> list = new ArrayList<Element>();
public void attach(Element element){
this.list.add(element);
}
public void accept(Vistor vistor){
for(Element element:list){
element.accept(vistor);
}
}
}
// Test
ObjectStruture objectStructor=new ObjectStructor();
objectStructor.attach(new ConcreteElement1());
objectStructor.attach(new ConcreteElement2());
objectStructor.accept(new ConcreteVisitor1();)
objectStructor.accept(new ConcreteVisitor2();)
Mediator
中介者模式: 用一个中介者对象封装一系列的对象交互,中介者使各对象不需要显示地相互作用,从而使耦合松散,而且可以独立地改变它们之间的交互
PS:只需关心和Mediator类的关系(由Mediator负责具体类类之间的关系及调度,有点像spring容器的作用)
实现:
- Mediator:维护Colleague之间的关系及调度
- Colleague:维护与Mediator的关系,自身的一些处理等
- ConcreteMediator
- ConcreteColleague
public interface Mediator{
void change(Colleague colleague);
}
public class ConcreteMediator implements Mediator {
private List<Colleague> list=new ArrayList<Colleague>();
public void addColleague(Colleague colleague){
this.list.add(colleague);
}
@Override
public void change(Colleague colleague) {
//各个Colleague交互协作
}
}
public abstract class Colleague{
private Mediator mediator;
public Colleague(Mediator mediator) {
this.mediator = mediator;
}
public Mediator getMediator(){
return mediator;
}
}
public class ConcreteColleague1 extends Colleague {
public ConcreteColleague1(Mediator mediator){
super(mediator);
}
public void doSomething(){
//...
}
}
public class ConcreteColleague2 extends Colleague {
public ConcreteColleague1(Mediator mediator){
super(mediator);
}
public void doSomething(){
//...
}
}
//Test
Mediator mediator = new ConcreteMediator();
Colleague colleague1=new ConcreteColleague1();
Colleague cooleague2=new ConcreteColleague2();
mediator.addColleague(colleague1);
mediator.addColleague(colleague1);
mediator.change(colleague1);
Interpreter
解释器模式
- 一种简单的语法解释器构架
- 给定一个语言之后,解释器模式可以定义出其文法的一种表示,并同时提供一个解释器
- 客户端可以使用这个解释器来解释这个语言中的句子
- 用来做各种各样的解释器,如正则表达式等的解释器等等
用的不多!