java设计模式学习笔记

简介

设计模式可以分为五类

  1. 接口型 模式:适配器模式,外观模式,合成模式,桥接模式
  2. 职责型 模式:单例模式,观察者模式,调停者模式,代理模式,职责链模式,享元模式 
  3. 构造型 模式:构建者模式,工厂方法模式,抽象工厂模式,原型模式,备忘录模式
  4. 操作型 模式:模板方法模式,状态模式,策略模式,命令模式,解析器模式
  5. 扩展型 模式:装饰器模式,迭代器模式,访问者模式。

 

 接口类

适配器模式 通过一个接口来适配类的接口

接口的优点:限制了类之间的协作 , 即使实现类发生巨大变化, 接口的客户端也不受影响

 

不同场景下使用 的模式

  1. 适配类的接口,以匹配客户端期待的接口-->适配器模式
  2. 为一组类提供简单接口-->外观模式
  3. 为简单对象和复合对象提供统一接口-->合成模式
  4. 解除抽象与实现之间的耦合,使得二者独立演化-->桥接模式

1. 适配器模式

 类适配器

使用继承方式,是静态的继承方式

简述 :接口中的方法  分别在父类和子类中实现 

写一个demo

接口中有两个方法 

public interface Target {

    void firstMethod();

    void secondMethod();
}

adaptee只有一个方法

public class Adaptee {
    public void firstMethod(){
        System.out.println("this is first method.");
    }
}

adapter 继承 adaptee 并实现 secondMethod

public class Adapter extends Adaptee implements Target {
    @Override
    public void secondMethod() {
        System.out.println("this second method.");
    }
}

  

对象适配器  

采用委派的方式 

将  adaptee组合到 adpter2中

写个demo

public class Adapter2 implements Target{
    private Adaptee adaptee;

    public Adapter2(Adaptee adaptee) {
        this.adaptee = adaptee;
    }

    @Override
    public void firstMethod() {
         this.adaptee.firstMethod();
    }

    @Override
    public void secondMethod() {
        System.out.println("this second method.");                                                     
    }
}

优点:代码复用,扩展 ,灵活 ,强大

缺点:是系统零乱 不易把握   

 2.外观模式

外观模式的意图是为 子系统 提供提供一个接口, 方便使用

外观类可能全是静态方法

简单描述一下  为复杂的子系统 提供一个 简单的调用门面  

网上找了个易于理解的例子 http://www.aichengxu.com/java/681321.htm

一个人申请开公司 他需要分别 去 工商局,银行,公安局,质监局,税务部门 办理相关手续 特别麻烦

现在 有个绿色通道 ,actor只要 和它对接 既可以完成 上述操作  这个 绿色通道便可以看成是 一个 facade

这样看来  facade 模式 减少了客户端和 各个子系统之间交互,减少耦合。使接入变得简单

写一个简单的demo

工商系统

public class Indutry {
   void regist(){
       System.out.println("indutry registration.");
   }
}

公安系统

public class PoliceStation {
    void regist(){
        System.out.println("police station registration.");
    }
}

税务系统

public class RevenueDepartment {
    void regist(){
        System.out.println("revenue department registration.");
    }
}

facade

public class Facade {
    public void buildCompany() {
        Indutry indutry = new Indutry();
        PoliceStation policeStation = new PoliceStation();
        RevenueDepartment revenueDepartment = new RevenueDepartment();

        indutry.regist();
        policeStation.regist();
        revenueDepartment.regist();
    }
}

3.合成模式

composite :组合对象 ,单对象 。组对象和单对象有共同的行为

组合对象 可以包括其他组合对象,也可以包括单对象。

合成模式 作用:保证客户端调用 单对象与组合对象的一致性

安全合成模式

管理聚集的方法 只出现在树枝构建中

写一个demo

相同接口

public interface Component {
    void printStruct(String preStr);
}

组合

public class Composite implements Component {
    private List<Component> childComponens = new ArrayList<Component>();
    private String name;

    public void add(Component child) {
        childComponens.add(child);
    }

    public void remove(int index) {
        childComponens.remove(index);
    }

    public Composite(String name) {
        this.name = name;
    }

    public List<Component> getChildComponens() {
        return childComponens;
    }

    public void setChildComponens(List<Component> childComponens) {
        this.childComponens = childComponens;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public void printStruct(String preStr) {
        System.out.println(preStr + "-->" + name);
        if (childComponens != null) {
            preStr += "      ";
            for (Component child : childComponens) {
                //递归调用
                child.printStruct(preStr);
            }
        }

    }
}

叶子节点

public class Leaf implements Component {

    private String name;

    public Leaf(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
    @Override
    public void printStruct(String preStr) {
        System.out.println(preStr+"-->"+name);
    }
}

 测试

public void test(){
        Composite root=new Composite("knowledge");
        //java 节点
        Composite java=new Composite("java");

        Composite map=new Composite("Map");
        map.add(new Leaf("HashMap"));
        map.add(new Leaf("TreeMap"));

        java.add(new Leaf("JVM"));
        java.add(new Leaf("List"));
        java.add(map);

        //spring节点
        Composite spring=new Composite("spring");
        spring.add(new Leaf("AOP"));
        spring.add(new Leaf("IOC"));

        // root add
        root.add(java);
        root.add(spring);

        root.printStruct("");
    }

运行结果

 

  

4. 桥接模式

 

桥接模式 (bridge)关注抽象

 

桥接模式的意图  是  将 抽象与抽象方法的实现 相互分离出来, 实现 解耦合,以便二者可以相互独立

简单的说 就是 将对象 与方法分离

书上看到一个例子:现在有 2种设备 分别有  启动  关闭 2个抽象方法。

写个简单的 demo

抽象设备

public abstract class AbstractMachine {

   private MechineMethod mechineMethod;

    public void setMechineMethod(MechineMethod mechineMethod) {
        this.mechineMethod = mechineMethod;
    }

    public MechineMethod getMechineMethod() {
        return mechineMethod;
    }

    abstract void checkMethod();
}  

 设备A

public class MachineA extends AbstractMachine {
    @Override
    void checkMethod() {
        System.out.println("check machine A ......");
    }
}

 

设备B

public class MachineB extends AbstractMachine {
    @Override
    void checkMethod() {
        System.out.println("check machine B ......");
    }
}

 

要检测的功能 的抽象类 (这里对方法的处理 将常规的 竖 转 横,方法平铺 )

public abstract class MechineMethod {
    abstract void methodRun();
}

  

start功能

public class StartMethod extends MechineMethod {
    @Override
    void methodRun() {
        System.out.println("start method running.");
    }
}

  

close功能

public class CloseMethod extends MechineMethod {
    @Override
    void methodRun() {
        System.out.println("close method running.");
    }
}

  

 

测试 检测 A设备的Start功能

//检测A设备的 start功能
 public void test() {
        //检测A设备的 start功能
        AbstractMachine machine = new MachineA();
        MechineMethod mechineMethod = new StartMethod();
        machine.setMechineMethod(mechineMethod);
        machine.checkMethod();
        machine.getMechineMethod().methodRun();
    }

 

输出结果

 

 职责类 

 

 我们常见的职责模式 如

根据可见性控制职责 :java代码中的 public,private,protected

 

 

职责设计模式

  1. 将职责集中到某个类的单个实例中-->单例模式
  2. 将对象从依赖它的对象中解耦-->观察者模式
  3. 将职责集中在某个类,该类可以监督其他对象的交互-->调停者模式
  4. 让一个对象扮演其他对象的行为--代理模式
  5. 允许将职责链的请求传递给其他对象,直到这个请求被某个对象处理-->职责链模式
  6. 将共享的 细粒度的职责 进行集中管理-->享元模式

 

 

 

 1. 单例模式

单例模式 : 是确保一个类的 有且仅有一个实例,并为它提供一个全局访问点

单例模式中 往往使用 static关键字

static 修饰的变量为 静态变量,静态变量只在类第一次调用的时候加载 ,在内存中只有一个副本。

 

1.饿汉模式

public class EagerSingleton {
    private static EagerSingleton eagerSingleton=new EagerSingleton();

    private EagerSingleton() {
    }

    public EagerSingleton getSingleton(){
        return eagerSingleton;
    }
}

2.懒加载模式

public class LazzySingleton {
    private static LazzySingleton lazzySingleton;

    private LazzySingleton() {
    }

    //同步方法
    public static synchronized LazzySingleton getSingleton() {
        if (lazzySingleton == null) {
            lazzySingleton = new LazzySingleton();
        }
        return lazzySingleton;
    }
}

3.  支持多线程

public class Singleton {
    private static Singleton singleton;

    private Singleton() {
    }

    public static Singleton getSingleton() {
        //先条件  后程序
        if (singleton == null) {
            //锁 住整个对象
            synchronized (Singleton.class) {
                singleton = new Singleton();
            }
        }
        return singleton;
    }
}

  

2. 观察者模式

Observer  [əbˈzɜ:rvə(r)] 

观察者模式:在多个对象之间定义一对多依赖关系,当一个对象的状态发生改变时,通知你依赖于它的对象,并根据新状态做出相应反应。

写一个demo

如 写一个 微博更新自动推送给客户

 抽象 WeiBo 父类

public abstract class WeiBo {
    //保存 Observer 
    private List<Observer> list = new ArrayList<Observer>();

    public void addObserver(Observer observer) {
        list.add(observer);
    }

    public void delObserver(Observer observer) {
        list.remove(observer);
    }

    //通知所有观察者
    public void notifyObservers(String operation) {
        for (Observer observer : list) {
            observer.update(operation);
        }
    }
}

具体的Video类

public class Video extends WeiBo {
    private String operation;

    public String getOperation() {
        return operation;
    }

    public void change(String operation) {
        this.operation = operation;
        notifyObservers(operation);
    }
}

观察者接口

public interface Observer {
    public void update(String operation);
}

监听文件大小的观察者

public class ObserverSize implements Observer {
    private String operation;

    @Override
    public void update(String operation) {
        this.operation = operation;
        System.out.println("Observer Size : " + operation);
    }
}

写一个测试的demo

 public void test() {
        Video video = new Video();
        Observer observer = new ObserverSize();
        video.addObserver(observer);
        video.change("compress video");//压缩视频
    }

运行结果

 

推模式 

主题发生改变时自动推送给观察者 ,不管观察者是否需要,主题推送的通常是主题对象的全部数据 或部分数据

拉模式

主题发生改变时 只传递少了信息给观察者  ,观察者根据需再向主题拉取数据。

java 提供的观察者支持类  

Observable

Observable [əbˈzərvəbəl] 可观察

被观察的类只要继承该类即可。

 

  

public class Observable {
    private boolean changed = false;
    private Vector<Observer> obs;

    /** Construct an Observable with zero Observers. */

    public Observable() {
        obs = new Vector<>();
    }

    /**
     * Adds an observer to the set of observers for this object, provided
     * that it is not the same as some observer already in the set.
     * The order in which notifications will be delivered to multiple
     * observers is not specified. See the class comment.
     *
     * @param   o   an observer to be added.
     * @throws NullPointerException   if the parameter o is null.
     */
    public synchronized void addObserver(Observer o) {
        if (o == null)
            throw new NullPointerException();
        if (!obs.contains(o)) {
            obs.addElement(o);
        }
    }

    /**
     * Deletes an observer from the set of observers of this object.
     * Passing <CODE>null</CODE> to this method will have no effect.
     * @param   o   the observer to be deleted.
     */
    public synchronized void deleteObserver(Observer o) {
        obs.removeElement(o);
    }

    /**
     * If this object has changed, as indicated by the
     * <code>hasChanged</code> method, then notify all of its observers
     * and then call the <code>clearChanged</code> method to
     * indicate that this object has no longer changed.
     * <p>
     * Each observer has its <code>update</code> method called with two
     * arguments: this observable object and <code>null</code>. In other
     * words, this method is equivalent to:
     * <blockquote><tt>
     * notifyObservers(null)</tt></blockquote>
     *
     * @see     java.util.Observable#clearChanged()
     * @see     java.util.Observable#hasChanged()
     * @see     java.util.Observer#update(java.util.Observable, java.lang.Object)
     */
    public void notifyObservers() {
        notifyObservers(null);
    }

    /**
     * If this object has changed, as indicated by the
     * <code>hasChanged</code> method, then notify all of its observers
     * and then call the <code>clearChanged</code> method to indicate
     * that this object has no longer changed.
     * <p>
     * Each observer has its <code>update</code> method called with two
     * arguments: this observable object and the <code>arg</code> argument.
     *
     * @param   arg   any object.
     * @see     java.util.Observable#clearChanged()
     * @see     java.util.Observable#hasChanged()
     * @see     java.util.Observer#update(java.util.Observable, java.lang.Object)
     */
    public void notifyObservers(Object arg) {
        /*
         * a temporary array buffer, used as a snapshot of the state of
         * current Observers.
         */
        Object[] arrLocal;

        synchronized (this) {
            /* We don't want the Observer doing callbacks into
             * arbitrary code while holding its own Monitor.
             * The code where we extract each Observable from
             * the Vector and store the state of the Observer
             * needs synchronization, but notifying observers
             * does not (should not).  The worst result of any
             * potential race-condition here is that:
             * 1) a newly-added Observer will miss a
             *   notification in progress
             * 2) a recently unregistered Observer will be
             *   wrongly notified when it doesn't care
             */
            if (!changed)
                return;
            arrLocal = obs.toArray();
            clearChanged();
        }

        for (int i = arrLocal.length-1; i>=0; i--)
            ((Observer)arrLocal[i]).update(this, arg);
    }

    /**
     * Clears the observer list so that this object no longer has any observers.
     */
    public synchronized void deleteObservers() {
        obs.removeAllElements();
    }

    /**
     * Marks this <tt>Observable</tt> object as having been changed; the
     * <tt>hasChanged</tt> method will now return <tt>true</tt>.
     */
    protected synchronized void setChanged() {
        changed = true;
    }

    /**
     * Indicates that this object has no longer changed, or that it has
     * already notified all of its observers of its most recent change,
     * so that the <tt>hasChanged</tt> method will now return <tt>false</tt>.
     * This method is called automatically by the
     * <code>notifyObservers</code> methods.
     *
     * @see     java.util.Observable#notifyObservers()
     * @see     java.util.Observable#notifyObservers(java.lang.Object)
     */
    protected synchronized void clearChanged() {
        changed = false;
    }

    /**
     * Tests if this object has changed.
     *
     * @return  <code>true</code> if and only if the <code>setChanged</code>
     *          method has been called more recently than the
     *          <code>clearChanged</code> method on this object;
     *          <code>false</code> otherwise.
     * @see     java.util.Observable#clearChanged()
     * @see     java.util.Observable#setChanged()
     */
    public synchronized boolean hasChanged() {
        return changed;
    }

    /**
     * Returns the number of observers of this <tt>Observable</tt> object.
     *
     * @return  the number of observers of this object.
     */
    public synchronized int countObservers() {
        return obs.size();
    }
}

Observer  

观察者只要实现该类即可。

3. 调停者模式 Mediator

  

mediator [ˈmēdēˌātər] :中间人

调停者模式:定义一个对象,封装一组对象的交互,从而降低对象间的耦合度,避免了对象之间的显示引用,并且可以独立的改变对象间的行为。

 

复杂的调用关系

 

 引入 mediator

 

写个demo

Mediator 接口 

public interface Mediator {

    void changed(Component component);
}

将A,B,C...等组件 抽象出一个父类

/**
 * A,B,C,D...抽象出一个父类 叫 Colleague
 * 因为 调停者 要和 A,B,C,D..组件关联 所以将它注入到各组件中(抽象到父类里)
 */
public abstract class Component {
    private Mediator mediator;


    public Component(Mediator mediator) {
        this.mediator = mediator;
    }

    public Mediator getMediator() {
        return mediator;
    }

}

  

组件A

public class ComponetA extends Component {

    public ComponetA(Mediator mediator) {
        super(mediator);
    }
    public void start(){
        getMediator().changed(this);//通过Mediator 调停者 通知 其他组件
    }
}

  

组件B

public class ComponetB extends Component {
    public ComponetB(Mediator mediator) {
        super(mediator);
    }
    public void start(){
        getMediator().changed(this);//通过Mediator 调停者 通知 其他组件
    }
}

  

实现 Mediator 类

public class MediatorConcrete implements Mediator {
    //调停者 要交互 其他组件 所以 其他组件 要注入调停者里面
    private ComponetA colleagueA;
    private ComponetB colleagueB;

    public void setColleague(ComponetA colleagueA, ComponetB colleagueB) {
        this.colleagueA = colleagueA;
        this.colleagueB = colleagueB;
    }

    @Override
    public void changed(Component colleague) {
        //通知给其他组件
        if (colleague instanceof ComponetA) {
            System.out.println("hi B,ComponetA start");
        } else if (colleague instanceof ComponetB) {
            System.out.println("hi A,ComponetB start");
        }
    }
}

  

测试  

public void test(){
        //实例化一个调停者
        MediatorConcrete mediator = new MediatorConcrete();
        //创建两个组件,放入调停者(要通过调停者传递消息)
        ComponetA a = new ComponetA(mediator);
        ComponetB b = new ComponetB(mediator);

        //交互的组件放入 (因为一个组件change,要通知其他组件)
        mediator.setColleague(a,b);
        a.start();//a组件启动

    }

 

运行结果 

 

4. 代理模式 Proxy

 

代理对象通常拥有一个几乎和实际对象相同的接口。它常常会控制访问,并将请求合理的转发给底层的真实对象。

 

Java 代理 

  1.  静态代理
  2.  动态代理

静态代理

 client-->subject-->proxy-->realSubject

 

 

realSubject : 委托类

proxy : 代理类

subject : 委托类和代理类的接口

 

静态代理中 一个委托类  realSubject 对应一个代理类 proxy 代理类在编译期间就已经确定

动态代理

 

Java 动态代理

 

动态代理的代理类 不是在Java代码中实现  是在运行期生成

1.定义接口 SubjectService

public interface SubjectService {
     void add();
}

2.定义委托类 RealSubjectServiceImpl

public class RealSubjectServiceImpl implements SubjectService {
    @Override
    public void add() {
        System.out.println("init real sub service.");
    }
}

3.定义 myInvocationHandler 实现java.lang.reflect.InvocationHandler接口

m.invoke(obj,args)  : 对目标对象的调用转发给 包装对象 

public class MyInvocationHandler implements InvocationHandler {
    private Object target;//目标对象

    public MyInvocationHandler(Object target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println(".....before......");
        Object result=method.invoke(target,args);
        System.out.println(".....after......");
        return result;
    }
    public Object getProxy(){
        return Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),target.getClass().getInterfaces(),this);
    }
}

4.测试

@Test
public void proxyTest(){
MyInvocationHandler handler=new MyInvocationHandler(new RealSubjectServiceImpl());
//proxy
SubjectService proxy= (SubjectService) handler.getProxy();
proxy.add();
}

 

运行结果

 

cglib动态代理  

cglib底层使用 ASM 重写 非 final 方法实现

  

1.创建 自己的方法拦截器  MyMethodInterceptor 实现  MethodInterceptor  

2.通过 net.sf.cglib.proxy.Enhancer 创建代理对象

public class MyMethodInterceptor implements MethodInterceptor {
private Object target;

public MyMethodInterceptor(Object target) {
this.target = target;
}

@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println(".....before......");
Object result=proxy.invokeSuper(obj,args);
System.out.println(".....before......");
return result;
}

public Object getProxy(){
Enhancer enhancer=new Enhancer();
enhancer.setCallback(this);
enhancer.setSuperclass(target.getClass());
return enhancer.create();
}
}

 

测试. 

  @Test
    public void cglibTest(){
        MyMethodInterceptor interceptor=new MyMethodInterceptor(new RealSubjectServiceImpl());
        SubjectService proxy= (SubjectService) interceptor.getProxy();
        proxy.add();
    }

 

 

 5. 职责链模式 chain of responsibility

 

 

 职责链模式 通过给予多个对象处理请求的机会,以解除请求的发送者与接收者之间的耦合。

简单的说 :请假3天假-->leader审批-->经理审批-->人事审批

                   或者

                  我只请半天假-->leader审批-->人事审批 

 

职责链的节点 可以自由组合 

 

 抽象一个Hander父类

public abstract class Handler {
    private Handler next;//后续责任对象

    public Handler getNext() {
        return next;
    }

    public void setNext(Handler next) {
        this.next = next;
    }

    public abstract void handleRequest();//处理请求
}

  

 A节点

public class HanderA  extends Handler{
    @Override
    public void handleRequest() {
        System.out.println("A done..");
        if(getNext()!=null){
            getNext().handleRequest();
        }else {
            System.out.println("finish..");
        }
    }
}

  

B节点

public class HanderB extends Handler{
    @Override
    public void handleRequest() {
        System.out.println("B done..");
        if(getNext()!=null){
            getNext().handleRequest();
        }else {
            System.out.println("finish..");
        }
    }
}

  

c节点

public class HanderC extends Handler{
    @Override
    public void handleRequest() {
        System.out.println("C done..");
        if(getNext()!=null){
            getNext().handleRequest();
        }else {
            System.out.println("finish..");
        }
    }
}

  

测试

 

public void test(){
        Handler a=new HanderA();
        Handler b=new HanderB();
        Handler c=new HanderC();
        a.setNext(b);
        b.setNext(c);

        a.handleRequest();
    }

 

执行结果

 

 6. 享元模式 flyweight

 

 

享元模式 在客户对象之间提供共享对象,并且为共享对象创建职责

共享对象发生改变 时  不需要通知其他客户端 

享元模式的目的是:通过共享来支持大量细粒度对象

 

1.享元模式 可以 使你共享的访问 大量出现的细粒度对象

 

2.享元对象必须是不可变的

 

3.不变的部分提取出来

 

4.为了确保享元对象共享 ,需要强制客户端通过享元工厂来访问

 

5.享元工厂 做好权限限制

 

 

 

不变性  

可以设置成枚举  

 java 中的String就是 享元模式  

  

 1.单纯享元模式

所有的享元对象都可以共享

 抽象一个接口

public interface Flyweight {
    void operation(String state);
}

实现一个享元对象

public class FlyweightA implements Flyweight {
    //共享对象状态
    private Character inState;

    public FlyweightA(Character inState) {
        this.inState = inState;
    }

    @Override
    public void operation(String state) {
        //state 改变方法的行为 单 不改变 共享对象的状态
        System.out.println("param :"+state);
        System.out.println("state:"+inState);
    }
}

享元工厂

public class FlyweightFactory {
    private Map<Character,Flyweight> files=new HashMap<Character, Flyweight>();
    public Flyweight factory(Character state){
        Flyweight flyweight=files.get(state);
        if(flyweight==null){
            flyweight=new FlyweightA(state);
            files.put(state,flyweight);
        }
        return flyweight;
    }
}

 

测试

public class FlyweightTest {

    @Test
    public void test() {
        FlyweightFactory factory = new FlyweightFactory();
        Flyweight flyweight = factory.factory(new Character('0'));
        flyweight.operation("test 1");
        flyweight = factory.factory(new Character('1'));
        flyweight.operation("test B");

    }
}

  

 运行结果

2.复合享元模式

复合享元模式  意思是 单个享元对象 组成一个集合,而这个集合本身不是共享的 

就是 将上述的例子 instate改成一个集合  

demo

 接口

public interface Flyweight {
    void operation(String state);
}

 

单个享元

public class FlyweightA implements Flyweight {
    //共享对象状态
    private Character inState;

    public FlyweightA(Character inState) {
        this.inState = inState;
    }

    @Override
    public void operation(String state) {
        //state 改变方法的行为 单 不改变 共享对象的状态
        System.out.println("param :"+state);
        System.out.println("state:"+inState);
    }
}

 

复合享元

public class FlyweightB implements Flyweight {
    //复合享元模式
    private Map<Character,Flyweight> files=new HashMap<Character, Flyweight>();
    @Override
    public void operation(String state) {
          for(Flyweight flyweight:files.values()){
              flyweight.operation(state);
          }
    }

    public void add(Character key,Flyweight value){
        files.put(key,value);
    }
}

  

享元工厂

public class FlyweightFactory {
    private Map<Character,Flyweight> files=new HashMap<Character, Flyweight>();
    //集合工厂
    public Flyweight factory(List<Character> states){
        FlyweightB b=new FlyweightB();
        for(Character c:states){
            //调用 单个构建
            b.add(c,factory(c));
        }
        return b;
    }

    //单参构建
    public Flyweight factory(Character state){
        //先从缓存中查找对象
        Flyweight fly = files.get(state);
        if(fly == null){
            //如果对象不存在则创建一个新的Flyweight对象
            fly = new FlyweightA(state);
            //把这个新的Flyweight对象添加到缓存中
            files.put(state, fly);
        }
        return fly;
    }
}

  

测试

public void test(){
        //工厂构建数据
        FlyweightFactory flyweightFactory=new FlyweightFactory();
        List<Character> param= Arrays.asList('0','1','2');
        Flyweight flyweight=flyweightFactory.factory(param);

        //操作
        flyweight.operation("test..");
    }

  

运行结果

 

构造类

 

  1. 在请求 创建对象之前  ,逐渐收集创建对象的信息-->构建者模式
  2. 推迟实例化的类对象-->工厂方法模式
  3. 创建一组 有共同特征的对象-->抽象工厂
  4. 根据现有对象 创建一个对象-->原型模式
  5. 通过对象内部静态版本 重构对象-->备忘录模式

 

 

 

 1.构建者模式 Builder

构建者模式 :将类的实例化逻辑 转移到类的外部。

构建模式 :将构建与对象分离 。将复杂对象的构建逻辑从对象本身抽离,这样能够简化复杂对象 

网上找了个例子 http://www.blogjava.net/fancydeepin/archive/2012/08/05/384783.html

 

 

 

 

 我们现在需要生产一个产品 :电脑

简单的描述 就是  产品(电脑) 是一个类,构建(builder) 是一个类 

然后 将 产品 放入 builder中构建

看代码:

产品

public abstract class Product {
    protected List<String> parts = new ArrayList<String>();//存储产品的各个部件

    //add
    public void add(String part) {
        parts.add(part);
    }

    //show product
    public void show() {
        for (String s : parts) {
            System.out.println(s);
        }
    }
}

 

宏碁电脑

public class Acer extends Product {
}

 

戴尔电脑

public class Dell extends Product {
}

  

构建者接口

public interface Builder {
    //构建产品 的几个步骤
    void buildCPU();

    void buildMemory();

    void buildGraphicsCard();

    Product getResult();
}

  

实现 宏碁电脑构建

public class AcerBuilder implements Builder {
    //产品和构建分离
    //创建Acer产品 进行 构建
    private Product product=new Acer();
    @Override
    public void buildCPU() {
        product.add("cpu:i5");
    }

    @Override
    public void buildMemory() {
        product.add("memory:8G");
    }

    @Override
    public void buildGraphicsCard() {
        product.add("graphics card:HD");
    }

    @Override
    public Product getResult() {
        return product;
    }
}

  

实现戴尔电脑构建

public class DellBuilder implements Builder {
    //产品和构建分离
    //创建Dell产品 进行 构建
    private Product product = new Dell();

    @Override
    public void buildCPU() {
        product.add("cpu:i7");
    }

    @Override
    public void buildMemory() {
        product.add("memory:16G");
    }

    @Override
    public void buildGraphicsCard() {
        product.add("graphics card:HD");
    }

    @Override
    public Product getResult() {
        return product;
    }
}

  

指导构建过程

public class Director {
    private Builder builder;

    public Director(Builder builder) {
        this.builder = builder;
    }
     
    public void Construct() {
        //控制 构建逻辑顺序
        builder.buildCPU();
        builder.buildMemory();
        builder.buildGraphicsCard();
    }
}

  

测试

public void test() {
        System.out.println("acer");
        AcerBuilder acerBuilder = new AcerBuilder();
        Director director = new Director(acerBuilder);
        director.Construct();
        //Product show
        acerBuilder.getResult().show();

        System.out.println("..............");

        System.out.println("dell");
        DellBuilder dellBuilder = new DellBuilder();
        director = new Director(dellBuilder);
        director.Construct();
        //Product show
        dellBuilder.getResult().show();
    }

  

运行结果

 

 

 

 2.工厂方法 factory method

 

工厂方法:让服务提供者 确定实例化哪个类,而不是客户端代码

网上找了个 demo http://blog.csdn.net/jason0539/article/details/23020989

 

简单工厂模式

简单工厂模式 又称  静态工厂模式

 

客户需要一辆宝马车,客户不必自己亲自造一辆宝马车 。我们可以建立一个工厂 ,工厂负责宝马车的创建,降低 客户和宝马的耦合

首先我们抽象一个BMW类

public abstract class BMW {
}

  

有两种型号的 BMW

public class BMW320 extends BMW {
    public BMW320() {
        System.out.println("build bmw 320.");
    }
}

 

BMW523

public class BMW523 extends BMW {
    public BMW523() {
        System.out.println("build bmw 523.");
    }
}

  

工厂 根据传参 创建 相应产品

public class SimpleFactory {
    public BMW createBMW(int param) {
        switch (param) {
            case 320:
                return new BMW320();
            case 523:
                return new BMW523();
            default:
                break;
        }
        return null;
    }
}

  

测试

 public void test(){
        SimpleFactory factory=new SimpleFactory();
        factory.createBMW(320);
        factory.createBMW(523);
    }

  

运行结果

 

  

工厂方法模式

 

简单工厂中   当客户需要 一个新产品时, simpleFactory需修改 case代码  去创建新的代码 ,这样 simpleFactory的代码会频繁改动  很是被动。这也违背了 设计模式的开闭原则。

这时  我们可以把 case部分的 静态代码抽出来,分成不同的子工厂。

Factory接口 

public interface Factory {
    BMW createBMW();
}

  

320子工厂

public class FactoryBMW320 implements Factory {
    @Override
    public BMW createBMW() {
        return new BMW320();
    }
}

 

523子工厂

public class FactoryBMW523 implements Factory {
    @Override
    public BMW createBMW() {
        return new BMW523();
    }
}

  

测试

 public void test(){
        FactoryBMW320 factoryBMW320=new FactoryBMW320();
        factoryBMW320.createBMW();

        FactoryBMW523 factoryBMW523=new FactoryBMW523();
        factoryBMW523.createBMW();
    }

  

运行结果

 

 

  

 3.抽象工厂 abstract factory

 

 

抽象工厂  创建不同的产品簇

 

还按上面的例子说 客户不是简单要一个BMW, 每个客户有 不同的  发动机和变速箱需求。

先创建两个类  发动机,变速箱

 

发动机

public abstract class Engine {
}

  

4缸发动机

public class Engine4 extends Engine {
    public Engine4() {
        //生产 四缸发动机
        System.out.println("create N46.");
    }
}

  

12缸发动机

public class Engine12 extends Engine {
    public Engine12() {
        //生产 12缸发动机
        System.out.println("create M73.");
    }
}

  

变速箱

public abstract class Gearbox {

}

  

手动变速

public class ManualGearbox extends Gearbox {
    public ManualGearbox() {
        System.out.println("create manual transmission.");
    }
}

  

自动变速

public class AutomaticGearbox extends Gearbox {
    public AutomaticGearbox() {
        System.out.println("create automatic transmission.");
    }
}

  

抽象工厂

public interface AbstractFactory {
    Engine createEngine();

    Gearbox createGearbox();
}

  

产品12工厂:12缸发动机,自动变速箱

public class FactoryBMW12 implements AbstractFactory {
    @Override
    public Engine createEngine() {
        return new Engine12();
    }

    @Override
    public Gearbox createGearbox() {
       return new AutomaticGearbox();
    }
}

  

产品 46 工厂 :4缸发动机,手动变速

public class FactoryBMW46 implements AbstractFactory {
    @Override
    public Engine createEngine() {
        return new Engine4();
    }

    @Override
    public Gearbox createGearbox() {
       return new ManualGearbox();
    }
}

  

测试

public void test(){
        System.out.println("bmw 12 :");
        FactoryBMW12 factoryBMW12=new FactoryBMW12();
        factoryBMW12.createEngine();
        factoryBMW12.createGearbox();
        System.out.println("............");

        System.out.println("bmw 46 :");
        FactoryBMW46 factoryBMW46=new FactoryBMW46();
        factoryBMW46.createEngine();
        factoryBMW46.createGearbox();
    }

  

执行结果

 

 4.原型模式 prototype

 原型模式使用户复制对象样本来创建对象。而不是通过实例化的方式。

原型模式的核心是克隆方法,java 提供了 Cloneable接口 。

写个demo

public class Student implements Cloneable {
    private String code;
    List<String> courses;

    public List<String> getCourses() {
        return courses;
    }

    public void setCourses(List<String> courses) {
        courses = courses;
    }
    public void addCourse(String course) {
        if(courses==null) courses=new ArrayList<String>();
        courses.add(course);
    }
    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }

    @Override
    protected Student clone() {
        try {
            return (Student) super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    public String toString() {
        return this.code
                +",Courses : "+ Arrays.toString(courses.toArray());
    }
}

  

  

原型模式 内存二进制流copy,要比直接new性能好 。

new 的时候 也许受权限限制 ,使用原型模式可以访问一些私有对象

 

浅拷贝

 public void test(){
        Student student=new Student();
        student.setCode("001");
        student.addCourse("math");

        Student studentB=student.clone();
        studentB.setCode("001B");
        studentB.addCourse("java");
        studentB.addCourse("C#");
        System.out.println(student.toString());
        System.out.println(studentB.toString());

    }

 

输出

可以发现  studenB的  Courses变化 会影响到 原始Student

因为 Object提供的clone只Copy对象 对象中数组和引用对象都未copy,指向的还是元数据的 地址。 

 

 深拷贝

可以通过流式copy进行深copy

public class Teacher implements Serializable{
    private String code;
    List<String> courses;

    public List<String> getCourses() {
        return courses;
    }

    public void setCourses(List<String> courses) {
        courses = courses;
    }
    public void addCourse(String course) {
        if(courses==null) courses=new ArrayList<String>();
        courses.add(course);
    }
    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }


    @Override
    public String toString() {
        return this.code
                +",Courses : "+ Arrays.toString(courses.toArray());
    }
}

  

流 copy

 public void testDeep(){
        try {
            Teacher teacher=new Teacher();
            teacher.setCode("001");
            teacher.addCourse("tech math");

            //对象  写入缓存 bytes
            //申明缓存空间
            ByteOutputStream bytes=new ByteOutputStream();
            //申明 对象写入
            ObjectOutputStream out=new ObjectOutputStream(bytes);
            //对象写入
            out.writeObject(teacher);

             //bytes中读取对象
            ObjectInputStream inputStream=new ObjectInputStream(new ByteArrayInputStream(bytes.getBytes())) ;
            Teacher teacherB= (Teacher) inputStream.readObject();
            teacherB.setCode("001B");
            teacherB.addCourse("tech java");
            System.out.println(teacher.toString());
            System.out.println(teacherB.toString());
        } catch (Exception e) {
            e.printStackTrace();  
        }

    }

  

运行结果

 

 5.备忘录模式 Memento

 

备忘录模式的目的是 为对象状态 提供存储和恢复功能。

 

备忘录模式的结构

Originator [əˈrijəˌnātər]

Caretaker [Care taker] 管理人

 

  1. 发起人:记录当前时刻内部状态,负责定义哪些属于备份范围的状态,负责创建和恢复备忘数据。
  2. 备忘录:负责存储 发起人对象的内部状态,需要的时候提供 发起人需要的内部状态
  3. 管理角色:对备忘录进行管理,保存和提供备忘数据。

 

 发起人代码

public class Originator {
    private String state="";

    public String getState() {
        return state;
    }

    public void setState(String state) {
        this.state = state;
    }
    //创建备忘状态
    public Memento createMemento(){
        return new Memento(this.state);
    }
    //恢复备忘状态
    public void restoreMemento(Memento memento){
        this.setState(memento.getState());
    }
}

备忘录

public class Memento {
    private String state="";

    public Memento(String state) {
        this.state = state;
    }

    public String getState() {
        return state;
    }

    public void setState(String state) {
        this.state = state;
    }
}

 

管理者

public class Caretaker {
    private Memento memento;

    public Memento getMemento() {
        return memento;
    }

    public void setMemento(Memento memento) {
        this.memento = memento;
    }
}

  

测试

public void test(){
        Originator originator=new Originator();
        originator.setState("init");
        System.out.println(originator.getState());

        //管理员 保存 现有状态
        Caretaker caretaker=new Caretaker();
        caretaker.setMemento(originator.createMemento());

        //更新状态
        originator.setState("running");
        System.out.println(originator.getState());

        //恢复状态
        originator.restoreMemento(caretaker.getMemento());

        System.out.println(originator.getState());
    }

  

执行结果

多状态 备忘

将 对象的属性放在map里

 

操作类

 

不同类 实现同一操作时 采用不同的方式 。类似java的多态 ,多态的设计思路被多种设计模式使用。

  1. 在方法中实现算法,推迟对算法步骤的定义,使得子类能够重新实现-->模板方法模式
  2. 将操作分散,使得每个类都能够表示不同的状态-->状态模式
  3. 封装操作,使得实现都可以相互替换-->策略模式
  4. 用对象来封装方法调用-->命令模式
  5. 将操作分散,使得每个实现运用到不同类型的集合-->解析器模式

 

 1.模板方法模式 template mothed

  

 模板方法:抽象一些步骤或将它定义在接口中,以便其他类可以实现这一步骤。

 

比如 我们去乘车  大致分为  买票-->进站安检-->检票-->入座

我现在搞一个系统 乘坐汽车,乘坐火车,乘坐地铁 都用该系统  

写个demo

 先抽象一个公共父类 定义基本的逻辑框架

public abstract class Ride {
    //模板 方法 final类型 子类不可以修改
    public final void action(){
        buyTicket();
        securityCheck();
        checkIn();
        seated();
        doStarted();
    }
    //购票
    protected abstract void buyTicket();
    //进站安检
    protected abstract void securityCheck();
    //检票
    protected abstract void checkIn();
    //入座
    protected abstract void seated();
    //钩子方法 ,子类可以不必要实现,如果有需求可以写
    protected void doStarted(){
        System.out.println("车辆启动..");
    }
}

  

 汽车出行

public class Bus extends Ride {

    @Override
    protected void buyTicket() {
        System.out.println("buy a bus ticket.");
    }

    @Override
    protected void securityCheck() {

        System.out.println("bus station security check.");
    }

    @Override
    protected void checkIn() {
        System.out.println("bus station check in.");
    }

    @Override
    protected void seated() {
        //按票入座
        System.out.println("ticket seat.");
    }
}

  

地铁出行

public class Subway extends Ride {

    @Override
    protected void buyTicket() {
        System.out.println("buy a subway ticket.");
    }

    @Override
    protected void securityCheck() {

        System.out.println("subway station security check.");
    }

    @Override
    protected void checkIn() {
        System.out.println("subway station check in.");
    }

    @Override
    protected void seated() {
        //随便坐
        System.out.println("Sit casually.");
    }
}

  

测试

public void test(){
        Ride ride=new Bus();
        ride.action();
        System.out.println(".....");
        ride=new Subway();
        ride.action();

    }

运行结果

 2.状态模式

 

程序中 经常 因状态不同,执行的不同逻辑代码 。状态模式: 就是将 这些状态 分为不同的状态对象,

且 这些状态对象 有自己的状态 行为。解耦 

网上找了个例子

四种颜色 

Red,
White,
Blue,
Black

有 pull和  push两种操作 

Color类

public enum  Color {
    Red,
    White,
    Blue,
    Black
}

操作管理类

public class Context {
    private Color color;

    public Context(Color color) {
        this.color = color;
    }

    public void push(){
        //red->white->blue->black
        if(color==Color.Red) color=Color.White;
        else if(color==Color.White) color=Color.Blue;
        else if(color==Color.Blue) color=Color.Black;
    }
    public void pull(){
        //red<-white<-blue<-black
        if(color==Color.Black) color=Color.Blue;
        else if(color==Color.Blue) color=Color.White;
        else if(color==Color.White) color=Color.Red;


    }
}

测试

public void test(){
        Context context=new Context(Color.Red);
        context.push();
        System.out.println(context.getColor().name());
        context.pull();
        System.out.println(context.getColor().name());
    }

结果

 

改用状态模式

 

 

public abstract class State {
    protected abstract void push(Context2 context);
    protected abstract void pull(Context2 context);
    protected abstract Color getColor();

}

 

public class RedState extends State {
    @Override
    protected void push(Context2 context) {
        context.setState(new WhiteState());
    }

    @Override
    protected void pull(Context2 context) {
        context.setState(new RedState());
    }

    @Override
    protected Color getColor() {
        return Color.Red;
    }
}

 

public class WhiteState extends State {
    @Override
    protected void push(Context2 context) {
        context.setState(new BlueState());
    }

    @Override
    protected void pull(Context2 context) {
        context.setState(new RedState());
    }

    @Override
    protected Color getColor() {
        return Color.White;
    }
}

  

public class BlueState extends State {
    @Override
    protected void push(Context2 context) {
        context.setState(new BlackState());
    }

    @Override
    protected void pull(Context2 context) {
        context.setState(new WhiteState());
    }

    @Override
    protected Color getColor() {
        return Color.Blue;
    }
}

  

 

public class BlackState extends State {
    @Override
    protected void push(Context2 context) {
        context.setState(new BlackState());
    }

    @Override
    protected void pull(Context2 context) {
        context.setState(new BlueState());
    }

    @Override
    protected Color getColor() {
        return Color.Black;
    }
}

  

测试

 public void test2(){
        Context2 context2=new Context2(new RedState());
        context2.push();
        System.out.println(context2.getState().getColor());
        context2.pull();
        System.out.println(context2.getState().getColor());
    }

  

运行结果

3.策略模式 strategy

strategy [ˈstratəjē]

 策略模式 就是 将公共操作 ,在不同类中分别实现,也就是继承公共的接口或父类  。再用策略调用者调用自己需要的策略。

demo:

 

1.策略接口

public interface Strategy {
    void compress();
}

2.rar压缩算法实现

public class RarStrategy implements Strategy {
    @Override
    public void compress() {
        System.out.println("execute rar compression");
    }
}

3.zip压缩算法实现

public class ZipStrategy implements Strategy {
    @Override
    public void compress() {
        System.out.println("execute zip compression");
    }
}

4.调用者类

public class Context {
    private Strategy strategy;

    public Context(Strategy strategy) {
        this.strategy = strategy;
    }

    public void executeCompress(){
        strategy.compress();
    }
}

5.测试

public void test(){
        Context context=new Context(new RarStrategy());
        context.executeCompress();
        context=new Context(new ZipStrategy());
        context.executeCompress();
    }

  

执行结果

 

 4.命令模式

 

  

命令模式的目的是 将请求 封装到 类内部

命令模式可以将请求封装在一个对象中  允许你可以像管理对象一样去 管理方法 ,传递 并且在适合的机会调用它 

  

网上找了个例子 :http://blog.csdn.net/jason0539/article/details/45110355  

 开关电视机的请求

现在设置 请求命令接口

public interface Command {
    void execute();
}

然后 建立一个 TV对象 作为命令的接收者

public class TV {

    void turnOn(){
        System.out.println("The TV is turn on.");
    }
    void turnOff(){
        System.out.println("The TV is turn off.");
    }
}

  

开机命令

public class CommandOn implements Command {
    private TV tv;

    public CommandOn(TV tv) {
        this.tv = tv;
    }

    @Override
    public void execute() {
        tv.turnOn();
    }
}

  

关机命令

public class CommandOff implements Command {
    private TV tv;

    public CommandOff(TV tv) {
        this.tv = tv;
    }

    @Override
    public void execute() {
        tv.turnOff();
    }
}

  

控制 器   就像遥控器

 

public class Control {
    private CommandOn commandOn;
    private CommandOff commandOff;

    public Control(CommandOn commandOn, CommandOff commandOff) {
        this.commandOn = commandOn;
        this.commandOff = commandOff;
    }

    public void turnOn(){
        commandOn.execute();
    }

    public void turnOff(){
        commandOff.execute();
    }
}

 

测试

 public void test() {
        TV tv = new TV();
        CommandOn commandOn = new CommandOn(tv);
        CommandOff commandOff = new CommandOff(tv);
        Control control=new Control(commandOn,commandOff);
        control.turnOn();
        control.turnOff();
    }

 

执行结果

本demo将命令 开机和关机命令 封装 传递 ,并在需要的时候触发

  

5.解析器模式 Interpreter 

 

 

扩展型设计模式 

  1. 让开发者动态组合对象行为-->装饰器模式
  2. 提供一个方法 来顺序访问 集合中的元素-->迭代器模式
  3. 允许开发者定义新的操作 而无需改变 分层体系中的类-->访问者模式

1.装饰器模式 decorator

decorator [ˈdekəˌrātər]

经典的装饰器模式 就是java中的流处理

 

 public void test(){
        try {
            FileWriter file=new FileWriter(new File("E://test//test.txt"));
            BufferedWriter writer=new BufferedWriter(file);
            writer.write("this is test file.");
            writer.flush();
            writer.close();
        } catch (IOException e) {
            e.printStackTrace(); 
        }
    }

 

这段代码中 我们从 FileWriter 组合成BufferWriter 最后输入文本;

通过构造器传入参数 ,产生了新的对象行为。  

查看下  源码

2.迭代器模式 Iterator

为顺序访问集合提供一种方式

 

/*
 * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
 * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 *
 *
 */

package java.util;

import java.util.function.Consumer;

/**
 * An iterator over a collection.  {@code Iterator} takes the place of
 * {@link Enumeration} in the Java Collections Framework.  Iterators
 * differ from enumerations in two ways:
 *
 * <ul>
 *      <li> Iterators allow the caller to remove elements from the
 *           underlying collection during the iteration with well-defined
 *           semantics.
 *      <li> Method names have been improved.
 * </ul>
 *
 * <p>This interface is a member of the
 * <a href="{@docRoot}/../technotes/guides/collections/index.html">
 * Java Collections Framework</a>.
 *
 * @param <E> the type of elements returned by this iterator
 *
 * @author  Josh Bloch
 * @see Collection
 * @see ListIterator
 * @see Iterable
 * @since 1.2
 */
public interface Iterator<E> {
    /**
     * Returns {@code true} if the iteration has more elements.
     * (In other words, returns {@code true} if {@link #next} would
     * return an element rather than throwing an exception.)
     *
     * @return {@code true} if the iteration has more elements
     */
    boolean hasNext();

    /**
     * Returns the next element in the iteration.
     *
     * @return the next element in the iteration
     * @throws NoSuchElementException if the iteration has no more elements
     */
    E next();

    /**
     * Removes from the underlying collection the last element returned
     * by this iterator (optional operation).  This method can be called
     * only once per call to {@link #next}.  The behavior of an iterator
     * is unspecified if the underlying collection is modified while the
     * iteration is in progress in any way other than by calling this
     * method.
     *
     * @implSpec
     * The default implementation throws an instance of
     * {@link UnsupportedOperationException} and performs no other action.
     *
     * @throws UnsupportedOperationException if the {@code remove}
     *         operation is not supported by this iterator
     *
     * @throws IllegalStateException if the {@code next} method has not
     *         yet been called, or the {@code remove} method has already
     *         been called after the last call to the {@code next}
     *         method
     */
    default void remove() {
        throw new UnsupportedOperationException("remove");
    }

    /**
     * Performs the given action for each remaining element until all elements
     * have been processed or the action throws an exception.  Actions are
     * performed in the order of iteration, if that order is specified.
     * Exceptions thrown by the action are relayed to the caller.
     *
     * @implSpec
     * <p>The default implementation behaves as if:
     * <pre>{@code
     *     while (hasNext())
     *         action.accept(next());
     * }</pre>
     *
     * @param action The action to be performed for each element
     * @throws NullPointerException if the specified action is null
     * @since 1.8
     */
    default void forEachRemaining(Consumer<? super E> action) {
        Objects.requireNonNull(action);
        while (hasNext())
            action.accept(next());
    }
}

 

 如果一个类 支持 for循环 必须实现Iterable接口 ,并提供 Iterator方法

public interface Iterable <T>  {
    java.util.Iterator<T> iterator();

    default void forEach(java.util.function.Consumer<? super T> consumer) { /* compiled code */ }

    default java.util.Spliterator<T> spliterator() { /* compiled code */ }
}

  

比如我们经常使用的 ArrayList

 3.访问者 visitor模式

访问者模式的意图是 不改变类层次结构前提下,对该层次结构进行扩展。

 

 

 

 

  

  

  

 

 

 

 

  

 

 

 

 

 

 

 

 

  

  

 

  

  

posted on 2017-11-05 19:07  黑人霸霸  阅读(693)  评论(0编辑  收藏  举报