理解设计模式

简单工厂、工厂方法、抽象工厂

简单工厂

经过定义多个factory.produceXXX()方法,或者经过向factory.produce(type)传递type参数来生成产品。
添加新产品须要添加produeXXX()方法或个性produce(type)来支持生成新的产品。html

工厂方法

一个Factory接口,接口中有一个produce()方法用于生成产品,具体的XXXFactory实现Factory接口并实现本身的produce()方法。
添加新产品时新增一个XXXFactory类,实现Factory接口并实现produce()方法。java

抽象工厂

一个Factory接口,接口中有多个produce()方法(produceA, produceB)每一个方法对应生成一个类产品。
XXXFactory实现Factory接口,并实现其中的produce*()方法。
抽象工厂与工厂方法的区别,能够理解为抽象工厂用于生产多个产品类,工厂方法只生产一个产品类。python

单例模式

保证一个类仅有一个实例,并提供一个静态的getInstance()方法获取这个实例。编程

懒汉式,不加锁,线程不安全

public class Singleton {  
    private static Singleton instance;  
    private Singleton (){}  
  
    public static Singleton getInstance() {  
        if (instance == null) {  
            instance = new Singleton();  
        }  
        return instance;  
    }  
}

懒汉式,加锁,线程安全

public class Singleton {  
    private static Singleton instance;  
    private Singleton (){}  
  
    public static synchronized Singleton getInstance() {  
        if (instance == null) {  
            instance = new Singleton();  
        }  
        return instance;  
    }  
}

饿汉式,线程安全

public class Singleton {设计模式

private static Singleton instance = new Singleton();  
private Singleton (){}  
public static Singleton getInstance() {  
    return instance;  
}

}数组

懒汉式,双重检查,线程安全

public class Singleton {  
    private volatile static Singleton singleton;  
    private Singleton (){}  
    public static Singleton getSingleton() {  
        if (singleton == null) {  
            synchronized (Singleton.class) {  
                if (singleton == null) {  
                    singleton = new Singleton();  
                }  
            }  
        }  
        return singleton;  
    }  
}

懒汉式,静态内部类

public class Singleton {  
    private static class SingletonHolder {  
        private static final Singleton INSTANCE = new Singleton();  
    }  
    private Singleton (){}  
    public static final Singleton getInstance() {  
        return SingletonHolder.INSTANCE;  
    }  
}

经过枚举来实现单例

public enum Singleton {  
    INSTANCE;  
    public void whateverMethod() {  
    }  
}

自由序列化,线程安全,保证单例。安全

建造者模式

独立的Builder类,经过build方法来生成实例。在build以前用add、set等一系列方法为将要生成的类设置属性值。能够参考protobuf的对象建立方法。数据结构

原型模式

复制现有实例生成新的实例。复制方式有深克隆与浅克隆之分,具体看clone()方法的实现。架构

适配器模式

将一个类的接口转换成客户但愿的另一个接口。适配器模式使得本来因为接口不兼容而不能一块儿工做的那些类能够一块儿工做。
例:AudioPlayer.play()能能播放MP3,如今要它能播放其余格式(例如aac),另外一个AACPlayer能够播放aac格式。实现方法:
1,建立一个MediaAdapter类,其中实例化一个AACPlayer用来播放aac格式
2,MediaAdapter实现play方法来调用AACPlayer的play方法,以此来实现适配
3,当用AudioPlayer播放aac格式时,调用MediaAdapter.play来间接调用AACPlayer的play方法
4,要用AudioPlayer播放全部其余格式,都在MediaAdapter中作适配。ide

桥模式

将抽象和实现放在两个不一样的类层次中,使它们能够独立地变化。——《Head First 设计模式》
如何理解:

Bridge.java

public interface Bridge {
   public void func(int radius, int x, int y);
}

TheAbastractClass.java

public abstract class TheAbstractClass {
   protected Bridge bridge;
   protected TheAbstractClass(Bridge bridge){
      this.bridge = bridge;
   }
   public abstract void func();
}

BridgeOne.java

public class BridgeOne  implements Bridge {
   @Override
   public void func() {
      System.out.println("BridgeOne.func called!");
   }
}

BridgeTwo.java

public class BridgeTwo  implements Bridge {
   @Override
   public void func() {
      System.out.println("BridgeTwo.func called!");
   }
}

TheSpecificClass.java

public class TheSpecificClass extends TheAbastractClass{
    TheSpecificClass(Bridge bridge){
        super(bridge);
    }
    @override
    public void func(){
        this.bridge.func();
    }
}

通常来讲,直接继承TheAbstractClass来实现func方法。在桥模式下,继承TheAbstractClass以后,func方法的具体实现则在经过this.bridge实现的。
桥模式和适配器模式的区别能够看这篇文章

过滤器模式

相似函数式编程中的filter

组合模式

对象中包含对象,用实现树型结构,对单个对象和组合对象的使用具备一致性。

装饰模式

用于动态地给一个对象添加一些额外的职责。
例:
Origin.java

public interface Origin{
   void func();
}

OriginImpl.java

public class OriginImpl implements Origin{
    public void func() {
        //do something
    }
}

AbstactDecorator.java

public abstract class AbstractDecorator implements Origin{
    protect Origin origin;
    public AbstractDecorator(Origin origin){
        this.origin = origin;
    }
    
    public void func(){
        this.origin.func();
    }
}

SpecificDecorator.java

public class SpecificeDecorator extends AbstractDecorator{
    public SpecificDecorator(Origin origin){
        super(origin);
    }    
    
    @Override
    public void func(){
        this.origin.func();
        //do something else
    }
}

main

public static int main(){
    Origin origin = new SpecificeDecorator(new OriginImpl());
    origin.func();    
}

经过装饰器SpecificDecorator,能够在原来的OriginImpl.func()的基础上do something else

外观模式

用于隐藏系统的复杂性,提供一致的操做界面。
例如:
1,ClassA, ClassB, ClassC三个类分别有methodA, methodB, methodC三个方法
2,建立Facade类,关联ClassA, ClassB, ClassC,提供methodA, methodB, mehtodC
3,经过Facade就能够调用mehtodA, methodB, methodC了

享元模式

就是共享对象,将原来建立的对象保存起来,下次须要使用的时候优先使用已经建立过的相同对象。

代理模式

为其余对象提供一种代理以控制对这个对象的访问。

Origin.java

public interface Origin{
   void func();
}

OriginImpl.java

public class OriginImpl implements Origin{
    public void func() {
        //do something
    }
}

Proxy.java

public class Proxy implements Origin{
    private Origin origin;
    
    public void func(){
        if(origin == null){
            origin = new OriginImpl();
        }        
        this.origin.func();
    }    
}

Proxy为代理类,经过Proxy来间接的调用OriginImpl.func()

责任链模式

将请求的发送者和请求的处理者解耦。
当有多种类型(type)的Request,每一个Request有一个指定的handler,经过把全部的handler链接起来造成一条链handlerLink。请求能够不用发送到指定的handler,直接发送到handlerLink,链中的每一个handler判断type是否是本身的要处理的,若是不是则传递到下一个handler

命令模式

对命令请求者(Invoker)和命令实现者(Receiver)的解耦,方便对命令进行各类控制。

ICommand: 命令接口,有execute方法
Command: 命令实现类
Invoker: 请求发送者
Receiver: 请求接收者,负责执行实际的业务逻辑

不用命令模式:
想要调用Receiver的doSomething()方法

Receiver r = new Receiver();
r.doSomething()

命令模式:

Command.java

public Interface ICommand{
    void execute();
}

public class Command implements ICommand{
    private Receiver receiver;
    
    public Command(Receiver receiver){
        this.receiver = receiver;
    }
    
    public void execute(){
        receiver.doSomething();
    }
}

Invoker.java

public class Invoker{
    ICommand cmd;
    
    
    public void setCommand(ICommand cmd){
        this.cmd = cmd;
    }
    
    public void submit(){
        this.cmd.execute();
    }
}

main

Invoker invoker = new Invoker();
Receiver receiver = new Receiver();
ICommand cmd = new Command(receiver);
invoker.setCommand(cmd);
invoder.submit();

命令模式实现Invoker与Receiver的隔离,Command与Receiver耦合。发送者只接收命令。当要扩展新的功能的时候,建立新的ICommand的实现类交给Invoker便可。

解释器模式

我的理解就是,解释器的做用就是把人能看明白的东西解释一下,让机器也看明白。好比,python代码是给人看的,python解释器就是把代码解释成机器能执行的指令;计算表达式(1+2+3*4/7)是人能看懂的,计算器的做用就是把计算表达式解释成能执行的一系列的简单运算。

代码和计算表达式这样的问题有几个重要的特征:

  • 用什么元素来书写,在计算表达式中就是数字(0-9)和运算符(+-*/),在代码中就是字母、数字和符号
  • 怎么书写(文法),在计算表达式中运算符和数字必须交替出现,在代码中就是各类语言和各自的语法规则。

因此,有规则可循的问题均可以用解释器模式来解决。可是将问题的规则提炼出来是很麻烦的,并且规则很复杂的时候更加难以提炼,成本很高。所以,只有当一类问题发生的频率足够高的状况下才适合用解释器模式。

迭代器模式

为不一样的数据结构提供统一的顺序遍历的操做。

中介者模式

假设有ABCD四个对象,若是两两交互的话每一个对象要维护三条链路。
加入中介,每一个对象维护一条链路。

备忘录模式

保存历史状态,以即可以恢复到原先的状态。

观察者模式

使用场景:一个对象A的改变要通知到一个或多个其余对象。

加入观察者可让A没必要关心具体要通知改变的其余对象,由观察者来发通知。

状态模式

类的行为是基于它的状态改变的,容许对象在内部状态发生改变时改变它的行为,对象看起来好像修改了它的类。如何理解这句话?

类(TheClass), 状态(State), 行为(action)

代码:

public class TheClass{
    private State state;
    
    public void action(){
        //TODO depends on state
    }
}

TODO这块能够用switch case或者if else来实现,State通常是一个int

typedef int State;//状态通常是个整型

public class TheClass{
    private State state;
    
    public void setState(State state){
        this.state = state;
    }
    
    public void action(){
        switch (state) {
            case stateA:
                //do A;
            case stateB:
                //do B;
        }
    }
}

不符合开闭原则,由于若是要增长一种状态,则须要修改代码,添加case

用状态模式,State是一个interface, 拥有一个action方法

public interface State{
    void action();
}

public Class StateA implements State{
    public void action(){
        //do A
    }
}

public Class StateB implements State{
    public void action(){
        //do B
    }
}

public class TheClass{
    private State state;
    
    public void setState(State state){
        this.state = state;
    }
    
    public void action(){
        this.state.action()
    }
}

若是要添加一个C状态,只须要新建一个StateC实现State接口便可。

空对象模式

对象有方法,NULL什么都没有。空对象目的在于提供默认的方法。这样咱们空对象执行相关操做时也不会报错。

策略模式

从输入获取输出能够有多种策略,例如排序问题就有插入、冒泡、快速、归并等不一样和策略,均可以获得相同的结果。各类策略分别适用于特定的输入,例如,对于自己有序数组来讲,冒泡策略只须要遍历一遍就能够。

若是用if else来解决排序问题:

sort(List list, Strategy strategy){
    switch (strategy) {
        case insert:
            //do insert sort
        case bubble:
            //do bubble sort
        ...
    }
}

不符合开闭原则,添加策略须要修改代码

用策略模式:

sort(List list, Strategy strategy){
    strategy.sort(list)
}

将策略抽象成接口,不一样的策略实现该接口。

模板模式

一个操做operate,有多个step。咱们把operate定义为固定的模板,各个step则能够重写。

public abstract class Template{
    void step1();
    void step2();
    void step3();
    
    void final operate(){
    
        step1();
        
        step2();
        
        step3();
    }
}

public class TheClass extends Template{
    @override
    void step1(){
        //do step1
    }
    
    void step2(){
        //do step2        
    }
    
    void step3(){
        //do step3
    }
}

访问者模式

  • 被访问者接口(Acceptor): 有accept(visitor)方法,接收visitor的访问
  • 被访元素(AcceptorItem): 实现了Acceptor接口,一般不会直接暴露给Visitor。
  • 访问者(Visitor): 有visit(acceptor)方法,访问acceptor元素
  • 被访问对象(Containor): 直接暴露给Visitor出来的被访问对象,至关于一个Containor,以必定的结构组织了各个AcceptorItem。

Acceptor.java

public interface Acceptor{
    void acceptor(Visitor visitor);
}

Visitor.java

public interface Visitor{
    void visit(AcceptorOne acceptor);
    void visit(AcceptorTwo acceptor);
}

AcceptorOne.java

public class AcceptorOne extends{
    public void accept(Visitor visitor){
        visitor.visit(this);
    }
}

AcceptorTwo.java

public class AcceptorTwo extends{
    public void accept(Visitor visitor){
        visitor.visit(this);
    }
}

Containor.java

public class Containor implements Acceptor{
    
    private Collection<Acceptor> acceptors;
    
    public void accept(Visitor visitor){
        Iteratro it = acceptors.getIterator();
        while(it.hasNext()){
            visitor.visit(it.next());
        }
    }
}

访问者(Vistor)有多个visit方法,visit根据不一样的Accepctor执行不一样的逻辑。若是要扩展新的Acceptor,须要修改Visitor接口,这样不符合开闭原则;而扩展新的Visitor时,则只须要新增Visitor实现就能够了。所以,访问者模式适合对象结构稳定,而常常须要扩展对象操做的场景。

MVC模式

MVC模式是一种软件架构模式,应于交互式应用中。交互式应用就是界面+操做+数据后台。若是不使用MVC模式,界面的代码和对数据操做的代码杂在一块儿,不方便重用,也不容易维护。MVC模式分离了界面和数据,界面(View)经过控制器(Controller)提供的接口操做数据模型(Model),后台数据变动以后经过控制器通知到相关的界面。

相关文章
相关标签/搜索