1.观察者模式,在一个事件触发后,同时触发其他一个或多个事件。为了解耦合,不把所有的代码写在一起,所以有了观察者模式,比如业务归业务,日志归日志,不写在一起。一般观察者模式配合责任链模式使用,多个observer循环调用观察方法实现观察。

package myDesignPattern.observer;import java.util.ArrayList;
import java.util.List;public class MyObserver {public static void main(String[] args) {MyEvent myEvent = new MyEvent();myEvent.add(new ObserverFirst());myEvent.add(new ObserverSecond());myEvent.add(new ObserverThird());myEvent.happen();}
}interface Observer{void doSomething();
}class MyEvent{private static List<Observer> observers= new ArrayList();public void happen(){System.out.println("it happened");this.notifyObservers();}public void add(Observer observer){observers.add(observer);}private void notifyObservers(){for (Observer observer : observers) {observer.doSomething();}}
}class ObserverFirst implements Observer{@Overridepublic void doSomething() {System.out.println("this is first");}
}class ObserverSecond implements Observer{@Overridepublic void doSomething() {System.out.println("this is second");}
}
class ObserverThird implements Observer{@Overridepublic void doSomething() {System.out.println("this is third");}
}

2.迭代器模式,一般用于自定义容器,不在乎迭代的过程,只在乎迭代的结果,迭代器只需要有hasnext和next方法即可。

package iterator;public class Iterator {public static void main(String[] args) {MyCollection myList = new MyList();myList.add("wocao");myList.add(123);myList.add(new StringBuffer("waeaw").append("123"));MyIterator iterator = myList.iterator();while (iterator.hasNext()){System.out.println(iterator.next());}}
}interface MyCollection{boolean add(Object obj);Integer getSize();MyIterator iterator();
}class MyList implements MyCollection{private Object[] arr = new Object[10];private int index = 0;@Overridepublic boolean add(Object obj) {if (index == arr.length-1){Object[] arrNew = new Object[arr.length*2];//数组1,起始位置,数组2,起始位置,一共copy多少个元素System.arraycopy(arr,0,arrNew,0,arr.length);arr=arrNew;}this.arr[index++] = obj;return true;}@Overridepublic Integer getSize() {return arr.length;}@Overridepublic MyIterator iterator() {return new MyIterator(arr);}}
class MyIterator{private Object[] objs;private int index = 0;public MyIterator(Object[] objs){this.objs = objs;}boolean hasNext(){return objs[index]!=null;}Object next(){return objs[index++];}
}
  1. 单例模式,虽说有十种,但是可用的却没那么多,单例模式类似于云存档,新new的对象保留原来的数据。

    1. 恶汉,开始就直接new,安全可用,但初始化占了略微多一点内存
    public class Singleton {private final static Singleton INSTANCE = new Singleton();private Singleton(){}public static Singleton getInstance(){return INSTANCE;}
    }
    1. 恶汉的静态代码块类型,也可用
    public class Singleton {private static Singleton instance;static {instance = new Singleton();}private Singleton() {}public static Singleton getInstance() {return instance;}
    }
    
    1. 懒汉,单线程安全,多线程不安全,同时进入if后将产生多个实例,不可用
    public class Singleton {private static Singleton singleton;private Singleton() {}public static Singleton getInstance() {if (singleton == null) {singleton = new Singleton();}return singleton;}
    }
    
    1. 懒汉 方法加synchronize,线程安全,可用,但是效率很低,没意义
    public class Singleton {private static Singleton singleton;private Singleton() {}public static synchronized Singleton getInstance() {if (singleton == null) {singleton = new Singleton();}return singleton;}
    }
    
    1. 懒汉 方法内加synchronize块,不安全,不可用,多个线程同时进入if后,会得到多个实例
    public class Singleton {private static Singleton singleton;private Singleton() {}public static Singleton getInstance() {if (singleton == null) {synchronized (Singleton.class) {singleton = new Singleton();}}return singleton;}
    }
    
    1. Double Check 双检查,一般的解法,正招,可用且推荐。volatile需要加上,防止指令重排序拿到还未执行构造方法但已经赋过默认值的实例对象。
    public class Singleton {private static volatile Singleton singleton;private Singleton() {}public static Singleton getInstance() {if (singleton == null) {synchronized (Singleton.class) {if (singleton == null) {singleton = new Singleton();}}}return singleton;}
    }
    

    7.静态内部类,原理和恶汉类似,但是相较于恶汉有延迟加载的优势,由于静态内部类和非静态内部类一样,在外部类加载时并不会马上加载,当要用到时才会加载,也就是调用getInstance时,可用效率也高。

    public class Singleton {private Singleton() {}private static class SingletonInstance {private static final Singleton INSTANCE = new Singleton();}public static Singleton getInstance() {return SingletonInstance.INSTANCE;}
    }
    
    1. 枚举,很牛批的样子。

      直接通过Singleton.INSTANCE.doSomething()的方式调用即可。方便、简洁又安全。

      枚举在JDK5后才出现,只会加载一次,所以很容易实现单例。

    public enum Singleton {INSTANCE;public void doSomething() {System.out.println("doSomething");}}
    //调用方法:public class Main {public static void main(String[] args) {Singleton.INSTANCE.doSomething();}
    }
    
    1. 利用JDK8的新特性 CAS 就是各种atomic类保证线程安全。称作CAS实现单例。

    不断循环,直到实例不为null,compareAndSet,如果INSTANCE为null,指向instance指向的对象

    public class Singleton {private static final AtomicReference<Singleton> INSTANCE= new AtomicReference<Singleton> ();private Singleton() {}public static Singleton getInstance() {for(;;) {Singleton instance = INSTANCE.get();if(instance != null) {return instance;}instance = new Singleton();if(INSTANCE.compareAndSet(null, instance)) {return instance;}}}
    }
    
    1. 关于第十种,网上有两种说法,LOCK和容器,其实一般网上6种或者8种就结束了,后面这些我个人觉得倒是有些强行为之了。

    LOCK,其实就是DoubleCheck的lock锁版

    public class Singleton {private static Singleton instance = null;private static Lock lock = new ReentrantLock();private Singleton() {}public static Singleton getInstance() {if(instance == null) {lock.lock(); // 显式调用,手动加锁if(instance == null) {instance = new Singleton();}lock.unlock(); // 显式调用,手动解锁}return instance;}
    }
    

    容器,自定义Key作为键,实例放入map,很迷,不知道在干嘛,register调用的时机未说明,

    不过话说hashmap不是线程不安全的吗,难道不该用hashtable

    public class SingletonManager { private static Map<String, Object> objMap = new HashMap<String,Object>();private Singleton() { }public static void registerService(String key, Object instance) {if (!objMap.containsKey(key) ) {objMap.put(key, instance) ;}}public static ObjectgetService(String key) {return objMap.get(key) ;}
    }
    

4.策略模式,其实就是多态的使用,类似于很多种类用很多if判断的更优解。统一实现things接口,不关心做什么事,只是想做这些事。所以doMyThings方法的参数永远都是Things,不用改来改去的。这模式同样适合各种排序方式,各种模式(如事务传播方式,使用哪个工厂,使用哪种加载方式),各种配置等等

package myDesignPartten.strategy;public class Strategy {public static void main(String[] args) {Strategy strategy = new Strategy();Eat eat = new Eat();Sleep sleep = new Sleep();Run run = new Run();strategy.doMyThings(eat);strategy.doMyThings(sleep);strategy.doMyThings(run);}// I dont really care what is the thing,I just want to do itpublic void doMyThings(Things things){things.doSomeThing();}
}interface Things{void doSomeThing();
}class Eat implements Things{@Overridepublic void doSomeThing() {System.out.println("I am using");}
}
class Sleep implements Things{@Overridepublic void doSomeThing() {System.out.println("I am sleeping");}
}
class Run implements Things{@Overridepublic void doSomeThing() {System.out.println("I am running");}
}
  1. 工厂模式,不关心对象如何产生制造的,只想拿到用而已,即叫个名字就来的意思。

以下是简单工厂,如果变为工厂方法模式的话就是BeanFactory中加各种Bean的get方法,不传name,name体现在方法名里。

package myDesignPartten.factory;public class Factory {public static void main(String[] args) {BeanFactory beanFactory = new BeanFactory();Bean myDao = beanFactory.getBean("myDao");Bean myService = beanFactory.getBean("myService");Bean myController = beanFactory.getBean("myController");System.out.println(myDao);System.out.println(myService);System.out.println(myController);Bean mmmmmmymagic = beanFactory.getBean("mmmmmmymagic");System.out.println(mmmmmmymagic);}
}interface Bean{}class MyController implements Bean{}class MyService implements Bean{}class MyDao implements Bean{}class BeanFactory{public Bean getBean(String beanName){if ("myDao".equals(beanName)){return new MyDao();}if ("myService".equals(beanName)){return new MyService();}if ("myController".equals(beanName)){return new MyController();}else{throw new RuntimeException("NoSuchBeanException");}}
}
  1. 门面模式 ,各种复杂东西,全部由一个门面代理,也就是一键操作,用户只需很简单的操作,不需要去走很复杂的内部流程。
package myDesignPartten.facade;public class Facade {public static void main(String[] args) {MyFacade.startMyBusiness();}
}class MyFacade{public static void startMyBusiness(){new GuaHao().guaHao();new JiaoFei().jiaoFei();new MenZhen().menZhen();}
}class GuaHao{public void guaHao(){System.out.println("患者已挂号...");}
}class JiaoFei{public void jiaoFei(){System.out.println("患者已缴费...");}
}class MenZhen{public void menZhen(){System.out.println("患者已门诊...");}
}
  1. 调停者模式,和门面模式差不多,异曲同工。
  2. 装饰器模式,实际上就是把原对象扔进去,出来后对象还是那个对象的感觉,但是其方法已经被改变,被加工过了,因为实际上对象地址已不是原来那个了。类似于stringbuilder的append。只是他们都有共同的父类。
package myDesignPattern.decorator;public class Decorator {public static void main(String[] args) {HaveDinner haveDinner = new HaveDinner();//前置修饰MyDecoratorBefore myDecoratorBefore = new MyDecoratorBefore(haveDinner);//后置修饰MyDecoratorAfter myDecoratorAfter = new MyDecoratorAfter(myDecoratorBefore);myDecoratorAfter.eat();}
}interface MyObject{void eat();
}class HaveDinner implements MyObject{@Overridepublic void eat(){System.out.println("吃主食了。");}
}abstract class  MyDecorator implements MyObject{protected MyObject object;public MyDecorator(MyObject object){this.object=object;}@Overridepublic abstract void eat();
}class MyDecoratorBefore extends MyDecorator{public MyDecoratorBefore(MyObject object) {super(object);}@Overridepublic void eat(){System.out.println("吃开胃菜了。");object.eat();}
}class MyDecoratorAfter extends MyDecorator{public MyDecoratorAfter(MyObject object) {super(object);}@Overridepublic void eat(){object.eat();System.out.println("吃饭后甜点了。");}
}
  1. 责任链模式,各种工具类对一个对象进行加工,最后输出成品。多用于filter,多个filter层层过滤,由一条链管理,但filter们和链类都实现于同一个接口,类型相同,代码简便耦合低,非常容易维护与升级。
package myDesignPattern.chain;import java.util.ArrayList;
import java.util.List;public class Chain {private static MyMainChain myMainChain=new MyMainChain();static {HttpFilter httpFilter = new HttpFilter();CharFilter charFilter = new CharFilter();SensitiveFilter sensitiveFilter = new SensitiveFilter();myMainChain.add(httpFilter);myMainChain.add(charFilter);myMainChain.add(sensitiveFilter);}public static void main(String[] args) {MyMessage myMessage = new MyMessage("我日马化腾,详情请到http://www.baidu.com观看,<script>function mytest(){alert(111);}</script>");System.out.println(myMessage.getMessage());myMainChain.doFilter(myMessage);System.out.println(myMessage.getMessage());}
}class MyMessage{private String message;public MyMessage(String message){this.message = message;}public void setMessage(String message){this.message=message;}public String getMessage(){return this.message;}
}interface MyChain{void doFilter(MyMessage message);
}class MyMainChain implements MyChain{private List<MyChain> list = new ArrayList<>();public void add(MyChain myChain){list.add(myChain);}@Overridepublic void doFilter(MyMessage message) {for (MyChain myChain : list) {myChain.doFilter(message);}}
}class CharFilter implements MyChain{@Overridepublic void doFilter(MyMessage message) {String msg = message.getMessage();String newMsg = msg.replaceAll(">", "]").replaceAll("<", "[");message.setMessage(newMsg);}
}
class SensitiveFilter implements MyChain{@Overridepublic void doFilter(MyMessage message) {String msg = message.getMessage();String newMsg = msg.replaceAll("我日", "***").replaceAll("马化腾", "麻花藤");message.setMessage(newMsg);}
}
class HttpFilter implements MyChain{@Overridepublic void doFilter(MyMessage message) {String msg = message.getMessage();String newMsg = msg.replaceAll("http://", "[链接]").replaceAll("https://", "[链接]");message.setMessage(newMsg);}
}
  1. 享元模式,当一个对象会被反复使用到的时候,没有必要再去新分配内存地址,直接把对象放入池中,要就去取,实际上也是池化的思想。JDK的String类就是用了这个设计模式,多个String xx=“123” 引用变量的地址实际上是一样的,==都是为true的,当string new了以后,当前地址是不一样了,但是也就是多了个中间环节的指向,最终地址还是指向常量池,详见intern方法。其实有点类似单例的模式,没有就new,有就直接返回。
package myDesignPattern.flyWeight;public class FlyWeight {public static void main(String[] args) {String s1 = "abc";String s2 = "abc";String s3 = new String("abc");String s4 = new String("abc");System.out.println(s1 == s2);//trueSystem.out.println(s2 == s3);//falseSystem.out.println(s3 == s4);//falseSystem.out.println(s3.intern() == s2);//trueSystem.out.println(s3.intern() == s2.intern());//true}
}
  1. 组合模式,只用于树状结构的设计,Node类的成员变量的类型也是Node,或者容器类泛型为Node,以此成为树结构。
/*** 求二叉树深度*/public class ErChaShu {static class TreeNode{int val;TreeNode left;TreeNode right;TreeNode(int x,TreeNode left,TreeNode right){this.left=left;this.right=right;this.val=x;}TreeNode(int x){this.val=x;}}public static void main(String[] args) {ErChaShu erChaShu = new ErChaShu();TreeNode treeNode =new TreeNode(1,new TreeNode(2,new TreeNode(4,new TreeNode(6),new TreeNode(7)),new TreeNode(5)),new TreeNode(3));int depth = erChaShu.getDepth(treeNode);System.out.println(depth);}public int getDepth(TreeNode root){return root==null?0:Math.max(getDepth(root.left),getDepth(root.right))+1;}
}
  1. 访问者模式,对象结构中对象对应的类很少改变,但经常需要在此对象结构上定义新的操作。需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而需要避免让这些操作"污染"这些对象的类,也不希望在增加新操作时修改这些类。简而言之,就是在不改动具体实体类的属性与方法的情况下,新建一个访问类,在里面进行业务操作的改动,重载方法去使各种有共同的实现接口的不同类有不同的操作。
package myDesignPattern.visitor;public class Visitor {public static void main(String[] args) {ComputerPart computer = new Computer();computer.accept(new ComputerPartDisplayVisitor());}
}interface ComputerPart {public void accept(ComputerPartVisitor computerPartVisitor);
}class Keyboard  implements ComputerPart {@Overridepublic void accept(ComputerPartVisitor computerPartVisitor) {computerPartVisitor.visit(this);}
}class Monitor  implements ComputerPart {@Overridepublic void accept(ComputerPartVisitor computerPartVisitor) {computerPartVisitor.visit(this);}
}class Mouse  implements ComputerPart {@Overridepublic void accept(ComputerPartVisitor computerPartVisitor) {computerPartVisitor.visit(this);}
}class Computer implements ComputerPart {ComputerPart[] parts;public Computer(){parts = new ComputerPart[] {new Mouse(), new Keyboard(), new Monitor()};}@Overridepublic void accept(ComputerPartVisitor computerPartVisitor) {for (int i = 0; i < parts.length; i++) {parts[i].accept(computerPartVisitor);}computerPartVisitor.visit(this);}
}interface ComputerPartVisitor {public void visit(Computer computer);public void visit(Mouse mouse);public void visit(Keyboard keyboard);public void visit(Monitor monitor);
}class ComputerPartDisplayVisitor implements ComputerPartVisitor {@Overridepublic void visit(Computer computer) {System.out.println("Displaying Computer.");}@Overridepublic void visit(Mouse mouse) {System.out.println("Displaying Mouse.");}@Overridepublic void visit(Keyboard keyboard) {System.out.println("Displaying Keyboard.");}@Overridepublic void visit(Monitor monitor) {System.out.println("Displaying Monitor.");}
}
  1. 代理模式,代理模式分为静态代理和动态代理。其思想均为利用代理类对原方法进行增加操作(增强),可以是事务,日志等。静态代理是新增代理类,与被代理类实现同一接口,在代理类中有与被代理类同名方法,由成员变量存储被代理类对象,可以调用原方法,但是可以有更多操作。

    1. 静态代理
package myDesignPattern.proxy.staticProxy;public class StaticProxy {public static void main(String[] args) {MyInterface myThing = new MyThing();myThing.doMyThing();System.out.println();myThing = new MyProxyThing(myThing);myThing.doMyThing();}
}interface MyInterface{void doMyThing();
}class MyThing implements MyInterface{@Overridepublic void doMyThing() {System.out.println("this is my house");}
}class MyProxyThing implements MyInterface{private MyInterface myInterface;public MyProxyThing(MyInterface myInterface){this.myInterface = myInterface;}@Overridepublic void doMyThing() {System.out.println("this is before");myInterface.doMyThing();System.out.println("this is after");}
}
//输出结果
//this is my house//this is before
//this is my house
//this is after
  1. 动态代理,JDK方式

    代理handler,作Proxy.newInstacnce的第三参数用,继承自JDK的InvocationHandler,实现invoke方法,第一参数proxy基本没用,第二参数method为代理的方法的Method对象,第三参数为代理方法的参数数组,返回值为原方法的返回值,类似链路传输,原方法把结果传给代理方法,代理方法再传给Main方法,即使是原方法返回值是void,这代码也是可以适配的。

package myDesignPattern.proxy.dynamicProxy;import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;public class DynamicProxyHandler implements InvocationHandler {private Object object;public DynamicProxyHandler(final Object object) {this.object = object;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("before");Object result = method.invoke(object, args);System.out.println("after");return result;}
}

​ 主方法类,实际上,在第三个参数Handler传参数时,可以传各种各样的Handler以达到适配各种代理功能,如日志,运行时间,这也是策略模式的一种使用。

package myDesignPattern.proxy.dynamicProxy;import java.lang.reflect.Proxy;public class DynamicProxy {public static void main(String[] args) {MyInterface myClass = new MyClass();myClass.doMyThing();MyInterface myClassProxy = (MyInterface)Proxy.newProxyInstance(MyInterface.class.getClassLoader(), new Class[]{MyInterface.class}, new DynamicProxyHandler(myClass));myClassProxy.doMyThing();}
}
interface MyInterface{void doMyThing();
}
class MyClass implements MyInterface{public void doMyThing(){System.out.println("kiss my ass");}
}
  1. 动态代理,CGLib 方式
package myDesignPattern.proxy.dynamicProxyCGLib;import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;import java.lang.reflect.Method;public class DynamicProxyCGLib {public static void main(String[] args) {Enhancer enhancer = new Enhancer();enhancer.setSuperclass(MyClass.class);enhancer.setCallback(new MyIntercept());MyClass myClass = (MyClass)enhancer.create();myClass.doFirst();myClass.doSecond();//输出//I can do it now at ten of the time//this is the first//the light is my strength//I can do it now at ten of the time//this is the second//the light is my strength}
}class MyClass{void doFirst(){System.out.println("this is the first");}void doSecond(){System.out.println("this is the second");}
}class MyIntercept implements MethodInterceptor{@Overridepublic Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {System.out.println("I can do it now at ten of the time");Object result = methodProxy.invokeSuper(o, objects);System.out.println("the light is my strength");return result;}
}
  1. 建造者模式,通过一个Builder类去构建一个业务类的各个成员变量,因为直接赋值过于硬核死板(耦合),所以采用 原材料自由组合的 方法,类似于service任意注入dao的思想。测试代码使用游戏思想,分为菜鸟模式和老兵模式,展现两种不同Builder针对于相同的原材料(难度,BGM,人物)的组合利用。建造的方法返回自己(this)以便实现链式编程,但个人觉得分步完成可以实现进度条效果更佳。
package myDesignPattern.builder;public class Builder {public static void main(String[] args) throws InterruptedException {MyGame myGame = new MyGame();CaiNiaoModelBuilder cnBuilder = new CaiNiaoModelBuilder(myGame);System.out.println("正在生成难度。。。");Thread.sleep(1000);cnBuilder.buildDifficulty();System.out.println("正在生成背景音乐。。。");Thread.sleep(1000);cnBuilder.buildBackGroundMusic();System.out.println("正在生成人物。。。");Thread.sleep(1000);cnBuilder.buildHost();System.out.println("生成完成。。。");System.out.println(myGame);System.out.println("改换老兵模式。。。");Thread.sleep(1000);LaoBinModelBuilder lbBudiler = new LaoBinModelBuilder(myGame);lbBudiler.buildDifficulty().buildBackGroundMusic().buildHost();System.out.println(myGame);}
}interface Difficulty{}
class SimpleDifficulty implements Difficulty{@Overridepublic String toString() {return "简单";}
}
class HardDifficulty implements Difficulty{@Overridepublic String toString() {return "困难";}
}interface BackGroundMusic{}
class BackGroundMusicOne implements BackGroundMusic{@Overridepublic String toString() {return "BGM1";}
}
class BackGroundMusicTwo implements BackGroundMusic{@Overridepublic String toString() {return "BGM2";}
}interface Host{}
class GuYueXuan implements Host{@Overridepublic String toString() {return "谷月轩";}
}
class JinJi implements Host{@Overridepublic String toString() {return "荆棘";}
}
//实体类,getter/setter/toString
class MyGame{private Difficulty myDifficulty;private BackGroundMusic myBackGroundMusic;private Host myHost;public Difficulty getMyDifficulty() {return myDifficulty;}public void setMyDifficulty(Difficulty myDifficulty) {this.myDifficulty = myDifficulty;}public BackGroundMusic getMyBackGroundMusic() {return myBackGroundMusic;}public void setMyBackGroundMusic(BackGroundMusic myBackGroundMusic) {this.myBackGroundMusic = myBackGroundMusic;}public Host getMyHost() {return myHost;}public void setMyHost(Host myHost) {this.myHost = myHost;}@Overridepublic String toString() {return "MyGame{" +"游戏难度为:" + myDifficulty +", 游戏BGM为:" + myBackGroundMusic +", 游戏主角名字:" + myHost +'}';}
}class CaiNiaoModelBuilder{private MyGame myGame;public CaiNiaoModelBuilder(MyGame myGame){this.myGame=myGame;}public CaiNiaoModelBuilder buildDifficulty(){myGame.setMyDifficulty(new SimpleDifficulty());return this;}public CaiNiaoModelBuilder buildBackGroundMusic(){myGame.setMyBackGroundMusic(new BackGroundMusicOne());return this;}public CaiNiaoModelBuilder buildHost(){myGame.setMyHost(new GuYueXuan());return this;}
}
class LaoBinModelBuilder{private MyGame myGame;public LaoBinModelBuilder(MyGame myGame){this.myGame=myGame;}public LaoBinModelBuilder buildDifficulty(){myGame.setMyDifficulty(new HardDifficulty());return this;}public LaoBinModelBuilder buildBackGroundMusic(){myGame.setMyBackGroundMusic(new BackGroundMusicTwo());return this;}public LaoBinModelBuilder buildHost(){myGame.setMyHost(new JinJi());return this;}
}
  1. 适配器模式,适配器类似于数据线转换器,为了让两个接口标准不一样的接口连上而采取的类似中介的类。由于在接收类中有标准的规定所限,传入类的数据不能匹配导致不行,此时使用适配器进行转换,使其符合标准。
package myDesignPattern.adapter;public class Adapter {public static void main(String[] args) {MyLock myLock = new MyLock();Key key = new Key();//自己的Key是不行的myLock.unlock(key);//我们传入我们的适配器进去myLock.unlock(new MyAdapter());}
}class Password{public String word = "the light is my strength";
}class Key{private Password password = new Password();public String getPassword(){return password.word;}
}class MyLock{public void unlock(Key key){String password = key.getPassword();if ("I am the darkness".equals(password)){System.out.println("锁解开了!");}else{System.out.println("口令不对啊,咋肥事?");}}
}class MyAdapter extends Key{public String getPassword(){String password = super.getPassword();if ("the light is my strength".equals(password)){return "I am the darkness";}else{System.out.println("不用适配。");return null;}}
}
  1. 抽象工厂模式,思想和工厂模式一致,但是在一项产品有很多样式的时候,该产品就变成了抽象的,如武器就是抽象的,它可以是M4,也可以是莫洛托夫。此时,我们需要一个抽象工厂来生产抽象的物品,也可以理解为抽象各种工厂成为一个抽象父类,工厂们继承抽象工厂,并生产各自的具体物品。主要用于结构清晰有关联,相当于定制一套标准。
package myDesignPattern.abstactFactory;public class AbstactFactory {public static void main(String[] args) {FirstFactory firstFactory = new FirstFactory();System.out.println(firstFactory.createFood());System.out.println(firstFactory.createVehicle());System.out.println(firstFactory.createWeapon());SecondFactory secondFactory = new SecondFactory();System.out.println(secondFactory.createFood());System.out.println(secondFactory.createVehicle());System.out.println(secondFactory.createWeapon());}
}abstract class MyAbstactFactory{abstract Food createFood();abstract Weapon createWeapon();abstract Vehicle createVehicle();
}class FirstFactory extends MyAbstactFactory{@OverrideFood createFood() {return new Bread();}@OverrideWeapon createWeapon() {return new M4A1();}@OverrideVehicle createVehicle() {return new Subway();}
}class SecondFactory extends MyAbstactFactory{@OverrideFood createFood() {return new Rice();}@OverrideWeapon createWeapon() {return new EMP();}@OverrideVehicle createVehicle() {return new Bus();}
}interface Food{}
class Bread implements Food{}
class Rice implements Food{}
interface Weapon{}
class M4A1 implements Weapon{}
class EMP implements Weapon{}
interface Vehicle{}
class Bus implements Vehicle{}
class Subway implements Vehicle{}
  1. 桥接模式,bridge,用于由于形容词过多或者种类过多导致类数量繁多的情况。如操作系统有很多,如Windows,linux,MAC,然后每个都有分辨率模式,然后每个都有自己的时区,甚至是鼠标速度,如果要直接创造一个类来代表这些模式的话,应该叫WindowsPower1920x1080CNTimeFastMouse类,如果全部列出,这样一来类的数量就多起来了,倘若还有更多的设定呢?这种排列组合的模式将让类多到爆炸。此时使用桥接模式,变为new Windows(new Power1920x1080(new CNTime(new FastMouse())));把原子类创建,然后自由组合,分级各个阶段的类,让低级的类成为高级类的成员变量,减少类的繁多。
package myDesignPattern.bridge;public class Bridge {public static void main(String[] args) {System windows = new Windows(new Power1920x1080(new CNTime(new FastMouse())));System windows2 = new Windows(new Power1280x720(new EUTime(new FastMouse())));System linux = new Linux(new Power1280x720(new EUTime(new SlowMouse())));System linux2 = new Linux(new Power1280x720(new CNTime(new FastMouse())));}
}interface System{}
interface ResolvingPower{}
interface TimeArea{}
interface MouseSpeed{}class Windows implements System{private ResolvingPower resolvingPower;public Windows(ResolvingPower resolvingPower){this.resolvingPower=resolvingPower;}
}class Linux implements System{private ResolvingPower resolvingPower;public Linux(ResolvingPower resolvingPower){this.resolvingPower=resolvingPower;}
}class Power1920x1080 implements ResolvingPower{private TimeArea timeArea;public Power1920x1080(TimeArea timeArea){this.timeArea=timeArea;}
}class Power1280x720 implements ResolvingPower{private TimeArea timeArea;public Power1280x720(TimeArea timeArea){this.timeArea=timeArea;}
}class CNTime implements TimeArea{private MouseSpeed mouseSpeed;public CNTime(MouseSpeed mouseSpeed){this.mouseSpeed=mouseSpeed;}
}class EUTime implements TimeArea{private MouseSpeed mouseSpeed;public EUTime(MouseSpeed mouseSpeed){this.mouseSpeed=mouseSpeed;}
}class FastMouse implements MouseSpeed{}
class SlowMouse implements MouseSpeed{}l
  1. 命令模式,Command,其思想十分简单,就是要做事务,能有回退功能。要做的就是把要执行的方法就封装成一个个指令,指令也是方法,统一命名,然后用一个List记录起来,成为有记忆的事务。
package myDesignPattern.command;import java.util.ArrayList;
import java.util.List;public class Command {public static void main(String[] args) {//初始值设为0Calculator calculator = new Calculator(0);calculator.excute(new Add(1));calculator.excute(new Minus(2));calculator.excute(new Multiply(6));calculator.excute(new Divide(3));//backSystem.out.println("**********开始回滚**********");calculator.back();calculator.back();calculator.back();calculator.back();/*0 + 1当前结果为 11 - 2当前结果为 -1-1 * 6当前结果为 -6-6 / 3当前结果为 -2**********开始回滚**********-2 * 3当前结果为 -6-6 / 6当前结果为 -1-1 + 2当前结果为 11 - 1当前结果为 0*/}
}class Calculator{List<MyCommand> list = new ArrayList<>();private int result;public Calculator(int initValue){this.result = initValue;}public void excute(MyCommand myCommand){list.add(myCommand);int newResult = myCommand.execute(this.result);this.result=newResult;System.out.println("当前结果为 "+this.result);}public void back(){MyCommand lastCommand = this.list.remove(list.size() - 1);int value = lastCommand.getValue();if (lastCommand instanceof Add){this.executeBack(new Minus(value));}else if (lastCommand instanceof Minus){this.executeBack(new Add(value));}else if (lastCommand instanceof Multiply){this.executeBack(new Divide(value));}else{this.executeBack(new Multiply(value));}}private void executeBack(MyCommand command){int newResult = command.execute(this.result);this.result = newResult;System.out.println("当前结果为 "+this.result);}
}interface MyCommand{int execute(int oldResult);int getValue();
}class Add implements MyCommand{private int value;public Add(int value){this.value=value;}public int getValue(){return this.value;}@Overridepublic int execute(int oldResult) {System.out.println(oldResult+" + "+this.value);return oldResult+this.value;}
}class Divide implements MyCommand{private int value;public Divide(int value){this.value=value;}public int getValue(){return this.value;}@Overridepublic int execute(int oldResult) {System.out.println(oldResult+" / "+this.value);return oldResult/this.value;}
}class Minus implements MyCommand{private int value;public Minus(int value){this.value=value;}public int getValue(){return this.value;}@Overridepublic int execute(int oldResult) {System.out.println(oldResult+" - "+this.value);return oldResult-this.value;}
}class Multiply implements MyCommand{private int value;public Multiply(int value){this.value=value;}public int getValue(){return this.value;}@Overridepublic int execute(int oldResult) {System.out.println(oldResult+" * "+this.value);return oldResult*this.value;}
}

19.原型模式,与其叫原型模式,不如叫克隆模式,模式核心思想就是要搞清楚深拷贝和浅拷贝的区别。深拷贝,浅拷贝。浅拷贝是对象直接调用JDK自带的clone方法,创造出一个内容相同地址与本对象不同的对象,原对象需要实现cloneable接口,但是浅拷贝有问题,如果拷贝的对象有引用数据类型的成员变量,那么copy前和copy后的对象的成员变量指向同一个地址,当其中一个改变值时,另一个也会改变。深拷贝是实现cloneable接口后,重写clone方法,让其引用数据类型的成员变量也调用clone方法,从而实现两个对象完全不相关,但数据一模一样,此为深拷贝。String 类型的不需要做深拷贝操作,String类是不改变的,一旦改变其指向的地址也会改变。

package myDesignPattern.prototype;import java.util.HashMap;public class Prototype {public static void main(String[] args) throws CloneNotSupportedException {MyObject myObject = new MyObject();myObject.setS("kissMyAss");HashMap map = new HashMap<String,Object>();map.put("myData","myMMM");myObject.setMap(map);myObject.setI(1);MyObject clone = (MyObject)myObject.clone();System.out.println(myObject);System.out.println(clone);HashMap cloneMap = clone.getMap();cloneMap.put("myData","911sss");clone.setS("123");System.out.println(myObject);System.out.println(clone);//MyObject{s='kissMyAss', map={myData=myMMM}, i=1}//MyObject{s='kissMyAss', map={myData=myMMM}, i=1}//MyObject{s='kissMyAss', map={myData=myMMM}, i=1}//MyObject{s='123', map={myData=911sss}, i=1}}
}class MyObject implements Cloneable{private String s;private HashMap<String,Object> map;private int i;@Overridepublic Object clone() throws CloneNotSupportedException {MyObject clone = (MyObject)super.clone();HashMap<String, Object> map = clone.getMap();HashMap newMap = (HashMap)map.clone();clone.setMap(newMap);return clone;}public String getS() {return s;}public void setS(String s) {this.s = s;}public HashMap<String, Object> getMap() {return map;}public void setMap(HashMap<String, Object> map) {this.map = map;}public int getI() {return i;}public void setI(int i) {this.i = i;}@Overridepublic String toString() {return "MyObject{" +"s='" + s + '\'' +", map=" + map +", i=" + i +'}';}
}
  1. 备忘录模式,memento,为了一个功能,SL大法。核心思想为记录状态,以便撤销,CTRL+Z的思想。一般用List记录以前的状态,通过一个save方法记录。测试代码使用了序列化来做存储,序列化流为Object Out/In putStream,load时,先write的先read。要存储的类及其引用类型成员变量须实现serializable接口。但是一般不使用JDK自带的序列化工具ObjectOutputStream,而使用Google的protoBuffer,因为JDK自带的序列化工具会有很多冗余的东西在里面。transient关键字是不序列化该关键字修饰的变量,当然在反序列化时也将没有数据。Serilizable接口和Cloneable接口一样,只是用于标记功能,本身并无实际作用,称作声明式接口。
package myDesignPattern.memento;import java.io.*;public class Memento {public static void main(String[] args) throws IOException, ClassNotFoundException {MyObject myObject = new MyObject();myObject.setI(1);myObject.setMyVariable(new MyVariable(123));myObject.setNoS("MyAss");myObject.setS("FUXK");File file = new File("E:/developer/myData.data");FileOutputStream fis = new FileOutputStream(file);ObjectOutputStream oos = new ObjectOutputStream(fis);oos.writeObject(myObject);oos.writeObject("WWWW");oos.close();fis.close();ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file));MyObject o = (MyObject)ois.readObject();String s = (String)ois.readObject();System.out.println(myObject);System.out.println(o);System.out.println(s);ois.close();}
}class MyObject implements Serializable {private MyVariable myVariable;private int i;private String s;private transient String noS;public MyVariable getMyVariable() {return myVariable;}public void setMyVariable(MyVariable myVariable) {this.myVariable = myVariable;}public int getI() {return i;}public void setI(int i) {this.i = i;}public String getS() {return s;}public void setS(String s) {this.s = s;}public String getNoS() {return noS;}public void setNoS(String noS) {this.noS = noS;}@Overridepublic String toString() {return "MyObject{" +"myVariable=" + myVariable.xx +", i=" + i +", s='" + s + '\'' +", noS='" + noS + '\'' +'}';}
}class MyVariable implements Serializable{public int xx;public MyVariable(int xx){this.xx= xx;}
}
  1. 模板模式,为了使多个方法必须按一定顺序执行,新写一个方法暴露给外界,写死按顺序依次调用各个方法,类似钩子函数,多个钩子函数被一个初始化方法加载。但写法上一般先写一个抽象父类。
package myDesignPattern.template;public class Template {public static void main(String[] args) {MyTemplate myTemplate = new MyTemplateImpl();myTemplate.initMyProject();}
}abstract class MyTemplate{void initMyProject(){doFirst();doSecond();doThird();doForth();}abstract void doFirst();abstract void doSecond();abstract void doThird();abstract void doForth();
}class MyTemplateImpl extends MyTemplate{@Overridevoid doFirst() {System.out.println("this is the first");}@Overridevoid doSecond() {System.out.println("this is the second");}@Overridevoid doThird() {System.out.println("this is the third");}@Overridevoid doForth() {System.out.println("this is the forth");}
}
  1. 状态模式,在相同的方法下,不同的状态下会做出不同的回应,方法复用。
package myDesignPattern.state;public class State {public static void main(String[] args) {MyLife myLife = new MyLife(new RichState());myLife.PC();myLife.marry();myLife = new MyLife(new PoorState());myLife.PC();myLife.marry();}
}interface MyState{void PC();void marry();
}class RichState implements MyState{@Overridepublic void PC() {System.out.println("2000 WaiWei");}@Overridepublic void marry() {System.out.println("White Rich Beautiful");}
}class PoorState implements MyState{@Overridepublic void PC() {System.out.println("200 DaMa");}@Overridepublic void marry() {System.out.println("Deep Dark Fantasy");}
}class MyLife{private MyState state;public MyLife(MyState state){this.state=state;}public void PC(){state.PC();}public void marry(){state.marry();}
}
  1. 解释器模式,类似于自定义语法,利用JAVA语言写出自己定义的语言,就像JAVA是用汇编和C写出来的一样。以下测试代码为自制MMMySQL语言,查询关键字and使用BinQie代替,插入关键字为addMyNumber,数字用逗号隔开。
package myDesignPattern.interpreter;import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;public class Interpreter {private static List<Integer> myList=new ArrayList<>();public static void main(String[] args) {//添加数据AddInterpreter addInterpreter = new AddInterpreter("addMyNumber 2,5,6,31,2");Boolean execute = addInterpreter.execute();System.out.println(execute);//查询数据SearchInterpreter searchInterpreter = new SearchInterpreter("> 1 BinQie < 7 BinQie < 8");List<Integer> result = searchInterpreter.execute();System.out.println(result);}static class SearchInterpreter implements MMMySql{//> 1 BinQie < 3private String expression;private Integer[] reList = new Integer[myList.size()];public SearchInterpreter(String expression){this.expression=expression;}@Overridepublic List<Integer> execute() {String[] words = this.expression.split(" BinQie ");for (String word : words) {String[] myChar = word.split(" ");for (int i = 0; i < myList.size(); i++) {if (">".equals(myChar[0])) {if (myList.get(i).intValue() > Integer.parseInt(myChar[1])) {reList[i] = (myList.get(i));}else{reList[i] = null;}} else if ("<".equals(myChar[0])) {if (myList.get(i).intValue() < Integer.parseInt(myChar[1])) {reList[i] = (myList.get(i));}else{reList[i] = null;}} else if ("=".equals(myChar[0])) {if (myList.get(i).intValue() == Integer.parseInt(myChar[1])) {reList[i] = (myList.get(i));}else{reList[i] = null;}} else {throw new RuntimeException("无效的比较符");}}}List<Integer> list = Arrays.asList(reList);List<Integer> reList = new ArrayList<>();for (Integer integer : list) {if (integer!=null){reList.add(integer);}}return reList;}}static class AddInterpreter implements MMMySql{//addMyNumber 1,2,3,4,5private String expression;public AddInterpreter(String expression){this.expression=expression;}@Overridepublic Boolean execute() {boolean isRight = expression.startsWith("addMyNumber ");if (!isRight){throw new RuntimeException("请按照规范填写关键字");}String[] numbers = expression.replaceAll("addMyNumber ", "").split(",");Arrays.stream(numbers).forEach(number->{myList.add(Integer.parseInt(number));});return true;}}interface MMMySql{Object execute();}
}

解读全部二十三种设计模式(附测试代码)相关推荐

  1. 第二部分:二十三种设计模式解读——什么是工厂方法模式

    二十三种设计模式解读--什么是工厂方法模式 author:陈镇坤27 日期:2022年2月10日 修改日期:2022年6月23日 文章目录 二十三种设计模式解读--什么是工厂方法模式 一.工厂方法模式 ...

  2. Java二十三种设计模式 之代理(proxy)

    Java二十三种设计模式 之代理(proxy) 今天我们学习一下静态代理和动态代理 我们来看代码(写一个坦克运行了多少时间): 第一种方法: public calss Tank implements ...

  3. 深入理解常见的二十三种设计模式

    深入理解常见的二十三种设计模式 文章目录 深入理解常见的二十三种设计模式 一.设计模式的分类 1.1 创建型(五种) 1.2 结构型(七种) 1.3 行为型(十一种) 二.创建型 2.1 单例模式 2 ...

  4. Java实现二十三种设计模式(五)—— 十一种行为型模式 (中)——解释器模式、迭代器模式、中介者模式、备忘录模式

    Java实现二十三种设计模式(五)-- 十一种行为型模式 (中)--解释器模式.迭代器模式.中介者模式.备忘录模式 一.解释器模式 我国 IT 界历来有一个汉语编程梦,虽然各方对于汉语编程争论不休,甚 ...

  5. 二十三种设计模式-六大原则

    二十三种设计模式 一.创建型: 单例模式.工厂模式.抽象工厂模式.原型模式.建造者模式: 二.结构型: 代理模式,装饰器模式.适配器模式.外观模式.组合模式.享元模式.桥梁模式: 三.行为型: 策略模 ...

  6. 二十三种设计模式(第十二种)-----代理模式(Proxy)

    二十三种设计模式(第十二种)-----代理模式(Proxy) 尚硅谷视频连接https://www.bilibili.com/video/BV1G4411c7N4?from=search&se ...

  7. 二十三种设计模式之原型模式

    今天继续探讨GOF二十三种设计模式的原型模式,原型模式也是属于创建型模式的一种 原型模式通俗的讲就是对象复制的过程,即通过一个原型对象,我可以得到一个该对象的克隆. 下面来看下原型模式的第一种写法-- ...

  8. Java 二十三种设计模式

    一.单例模式 定义 Ensure a class has only one instance, and provide a global point of access to it.(确保某一个类只有 ...

  9. Java代码设计模式讲解二十三种设计模式

    设计模式 文章目录 设计模式 一.创造型设计模式 1.1 单例模式 1.1.1 饿汉式单例模式 1.1.2 懒汉式单例模式 (1)线程不安全的情况 (2)线程安全的情况 1. 实例化的方法上加sync ...

  10. java二十三种设计模式——工厂设计模式

    java设计模式的分类 在java中,设计模式有三十三种之多,分为三大类: 创建性模式,共五种:工厂方法模式.抽象工厂模式.单例模式.建造者模式.原型模式. 结构性模式,共七种:适配器模式.装饰器模式 ...

最新文章

  1. ORA-00942:表或视图不存在(低级错误)
  2. amoeba for mysql配置_Amoeba for mysql 读写分离
  3. 计算机网络学习笔记-01-概念,组成,功能,分类
  4. 删除a标签下面的横线
  5. Java的Stack类
  6. Flink State
  7. 银行工作的你压力大吗?待遇还好吗?
  8. leetcode python3 简单题1.Two Sum
  9. 三星1万亿元重金下注,推动AI、5G、半导体等项目的研究
  10. 【Excel】数据透视表—标签合并居中
  11. 迎亚运 广州推出全国首个地铁导向地图
  12. “天生BUFF”华硕主板冷傲ROG
  13. 【Jenkins】在Pipeline和Ant中使用环境变量
  14. Spring获取外网IP
  15. 如何用PPT编制方案 — 1. PPT的总体规划
  16. 电脑硬盘分区删了格式化了文件如何恢复
  17. 压缩包文件设置了加密怎么解密
  18. Linux操作系统的基本使用(ubuntu)
  19. Python培训脱产班和周末班
  20. 1211: 8102 开关

热门文章

  1. linux网页打开慢的解决方法,解决Ubuntu浏览网页速度慢的问题
  2. 三菱PLC特殊软元件
  3. 从Linux服务器下载文件夹到本地
  4. 信息安全-网络安全审计技术原理与应用
  5. 第114课:SparkStreaming+Kafka+Spark SQL+TopN+Mysql+KafkaOffsetMonitor电商广告点击综合案例实战(详细内幕版本)
  6. TextView rotation 旋转
  7. 经典推荐:盛大架构师周爱民回顾职业历程,分享十项建议
  8. Matlab信道容量的迭代计算实验
  9. MYSQL函数group_concat的使用
  10. 上海亚商投顾:沪指缩量跌0.43%