模式是在特定环境下人们解决某类重复出现问题的一套成功或有效的解决方案
在软件开发生命周期的每一个阶段都存在着一些被认同的模式
什么是设计模式
设计模式(Design Pattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结,使用设计模式是为了可重用代码、让代码更容易被他人理解并且保证代码可靠性。
设计模式一般包含模式名称、问题、目的、解决方案、效果等组成要素,其中关键要素是模式名称、问题、解决方案和效果
设计模式分为三类:5种创建型模式 、7种结构型模式 、11种行为型模式
23种设计模式
**创建型模式:**单例模式、抽象工厂模式、建造者模式、工厂模式、原型模式。
**结构型模式:**适配器模式、桥接模式、装饰模式、组合模式、外观模式、享元模式、代理模式。
**行为型模式:**模版方法模式、命令模式、迭代器模式、观察者模式、中介者模式、备忘录模式、解释器模式、状态模式、策略模式、职责链模式(责任链模式)、访问者模式。
复习的时候,发现了一个很有趣的开源代码:https://github.com/youlookwhat/DesignPattern
设计模式的六大原则
**1.开闭原则:**对扩展开放,对修改关闭;
**2.里氏替换原则:**任何基类可以出现的地方,子类一定可以出现
LSP是继承复用的基石,只有当衍生类可以替换掉基类,软件单位的功能不受到影响时,基类才能真正被复用,而衍生类也能够在基类的基础上增加新的行为
依赖倒转原则: 开闭原则的基础;针对接口变成,依赖于抽象而不依赖于具体;
**接口隔离原则:**使用多个隔离的接口,比使用单个接口要好
**最少知道原则:**一个实体应当尽量少的与其他实体之间发生相互作用,使得系统功能模块相对独立(高内聚低耦合)
**合成复用原则:**尽量使用合成/聚合的方式,而不是使用继承
创建型模式
单例模式
单例模式,保证JVM中只有一个单例对象并且该对象只有一个实例存在;
好处:
1、某些类创建比较频繁,对于一些大型的对象,这是一笔很大的系统开销
2、省去了new操作符,降低了系统内存的使用频率,减轻GC压力
3、有些类如交易所的核心交易引擎,控制着交易流程,如果该类可以创建多个的话,系统完全乱了。(比如一个军队出现了多个司令员同时指挥,肯定会乱成一团),所以只有使用单例模式,才能保证核心交易服务器独立控制整个流程。
**坏处:**之前看过内存溢出相关的文章,单例模式的滥用似乎很容易发生内存溢出;
eg:(栗子来自于:http://blog.csdn.net/zhangerqing/article/details/8194653 )
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 public class Singleton { private static Singleton instance = null ; private Singleton () {} public static Singleton getInstance () { synchronized (instance) { if (instance == null ) { instance = new Singleton(); } } return instance; } public Object readResolce () { return instance; } } private static class SingletonFactory { private static Singleton instance = new Singleton(); } public static Singleton getInstance () { return SingletonFactory.instance; } }
可以利用内部类来维护单例的实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 public class Singleton { private Singleton () { } private static class SingletonFactory { private static Singleton instance = new Singleton(); } public static Singleton getInstance () { return SingletonFactory.instance; } public Object readResolve () { return getInstance(); } }
工厂模式
工厂模式分为:普通工厂模式,多个工厂模式,静态工厂模式
普通工厂模式
建立一个工厂类,对实现了同一接口的一些类进行实例的创建
eg:来自:http://blog.csdn.net/zhangerqing/article/details/8194653
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 public interface Sender { public void Send () ; } public class MailSender implements Sender { @Override public void Send () { ... } } public class SmsSender implements Sender { @Override public void Send () { ... } } / ** / * Factory: ** / public class SendFactory { public Sender produce (String type) { if ("mail" .equals(type)){ return new MailSender(); }else if ("sms" .equals(type)){ retrun new SmsSender () ; }else { ... return null ; } } } public class FactoryTest { public static void main (String[] args) { SendFactory factory = new SendFactory(); Sender sender = factory.produce("sms" )'; sender.Send(); } }
多个工厂方法模式
对普通工厂方法模式的费劲,在普通工厂方法模式中,如果传递的字符串出错,则不能创建对象,而多个工厂方法模式是提供多个工厂方法,分别创建对象
eg:将Factory修改为:
1 2 3 4 5 6 7 8 9 10 public class SendFactory { public Sender produceMail () { return new MailSender(); } publc Sender produceSms () { return new SmsSender(); } }
静态工厂方法模式:
将工厂类中的方法设为静态,不需要创建实例;
抽象工厂模式
普通的工厂方法,类的创建以来于工厂类;扩展程序的时候,需要对工厂类进行修改;
抽象工厂模式,创建多个工厂类,在增加新的功能的时候没直接增加新的工厂类,不需要修改之前的代码;
eg:利用刚才的两个类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 public interface Provider { public Sender produce () ; } public class SendMailFactory implements Provider { @Override public Sender produce () { return new MailSender(); } } public class SendSmsFactory implements Provider { @Override public Sender produce () { return new SmsSender(); } } public class Test { public static void main (String[] args) { Provider provider = new SendMailFactory(); Sender sender = provider.produce(); sender.Send(); } }
建造者模式(Builder)
建造者模式则是将各种产品集中起来进行管理,用来创建复合对象,所谓复合对象就是指某个类具有不同的属性,其实建造者模式就是前面抽象工厂模式和最后的Test结合起来得到的
感觉安卓开发的过程中,好像很经常会用到Builder这个东西;比如说okhttp的FormBody的构造;
eg:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 public class Builder { private List<Sender> list = new ArrayList<Sender>(); public void produceMailSender (int count) { for (int i=0 ; i<count; i++){ list.add(new MailSender()); } } public void produceSmsSender (int count) { for (int i=0 ; i<count; i++){ list.add(new SmsSender()); } } } public class Test { public static void main (String[] args) { Builder builder = new Builder(); builder.produceMailSender(10 ); } }
还有另一种形式(在effective Java中看到的)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 public class NutritionFacts { private final int servingSize; private final int servings; private final int calories; private final int fat; private final int sodium; private final int carbohydrate; public static class Builder { private final int servingSize; private final int servings; private int calories = 0 ; private int fat = 0 ; private int carbohydrate = 0 ; private int sodium = 0 ; public Builder (int servingSize, int servings) { this .servingSize = servingSize; this .servings = servings; } public Builder calories (int val) { calories = val; return this ; } public Builder fat (int val) { fat = val; return this ; } public Builder carbohydrate (int val) { carbohydrate = val; return this ; } public Builder sodium (int val) { sodium = val; return this ; } public NutritionFacts build () { return new NutritionFacts(this ); } } private NutritionFacts (Builder builder) { servingSize = builder.servingSize; servings = builder.servings; calories = builder.calories; fat = builder.fat; sodium = builder.sodium; carbohydrate = builder.carbohydrate; } public static void main (String[] args) { NutritionFacts cocaCola = new NutritionFacts.Builder(240 , 8 ). calories(100 ).sodium(35 ).carbohydrate(27 ).build(); } }
在类的内部定义一个Builder内部类,通过Builder中的函数,设置对象的各种值,最后build为我们的类对象;
感觉这个跟平时开发中用到的东西比较像;
我觉得,利用Builder模式,就解决了多个构造函数的问题
原型模式
该模式的思想就是将一个对象作为原型,对其进行复制、克隆,产生一个和原对象类似的新对象
eg:栗子来自:http://blog.csdn.net/zhangerqing/article/details/8194653
1 2 3 4 5 6 7 8 9 10 11 12 / ** / * 原型类 / ** public class Prototype implements Cloneable { public Object clone () throws CloneNotSupportedException { Prototype proto = (Prototype) super .clone(); return proto; } }
一个原型类,只需要实现Cloneable接口,覆写clone方法,此处clone方法可以改成任意的名称(Cloneable接口是个空接口,你可以任意定义实现类的方法名)
Object类中,clone()是native的
浅复制:将一个对象复制后,基本数据类型的变量都会重新创建,而引用类型,指向的还是原对象所指向的。
深复制:将一个对象复制后,不论是基本数据类型还有引用类型,都是重新创建的。简单来说,就是深复制进行了完全彻底的复制,而浅复制不彻底。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 public class Prototype implements Cloneable , Serializable { private static final long serialVersionUID = 1L ; private String string; private SerializableObject obj; public Object clone () throws CloneNotSupportedException { Prototype proto = (Prototype) super .clone(); return proto; } public Object deepClone () throws IOException, ClassNotFoundException { ByteArrayOutputStream bos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(bos); oos.writeObject(this ); ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray()); ObjectInputStream ois = new ObjectInputStream(bis); return ois.readObject(); } public String getString () { return string; } public void setString (String string) { this .string = string; } public SerializableObject getObj () { return obj; } public void setObj (SerializableObject obj) { this .obj = obj; } } class SerializableObject implements Serializable { private static final long serialVersionUID = 1L ; }
结构型模式
适配器模式
将一个类的接口转换成客户期望的另一个接口,适配器让原本接口不兼容的类可以相互合作
eg:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 public class Mobile { public void inputPower (V5Power power) { int provideV5Power = power.provideV5Power(); System.out.println("手机(客户端):我需要5V电压充电,现在是-->" + provideV5Power + "V" ); } } public interface V5Power { public int provideV5Power () ; }
1 2 3 4 5 6 7 8 9 10 11 12 13 public class V220Power { public int provideV220Power () { System.out.println("我提供220V交流电压。" ); return 220 ; } }
适配器:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 public class V5PowerAdapter implements V5Power { private V220Power v220Power ; public V5PowerAdapter (V220Power v220Power) { this .v220Power = v220Power ; } @Override public int provideV5Power () { int power = v220Power.provideV220Power() ; System.out.println("适配器:我悄悄的适配了电压。" ); return 5 ; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 / ** / * Test / ** public class Test { public static void main (String[] args) { Mobile mobile = new Mobile(); V5Power v5Power = new V5PowerAdapter(new V220Power()) ; mobile.inputPower(v5Power); } }
桥接模式
将抽象部分与它的实现部分分离,使它们都可以独立地变化。它是一种对象结构型模式,又称为柄体(Handle and Body)模式或接口(Interface)模式。
主要特点是把抽象(abstraction)与行为实现(implementation)分离开来
Client Bridge模式的使用者
Abstraction 抽象类接口(接口或抽象类);维护对行为实现(Implementor)的引用
Refined Abstraction Abstraction子类
Implementor 行为实现类接口 (Abstraction接口定义了基于Implementor接口的更高层次的操作)
ConcreteImplementor Implementor子类
eg:栗子来自:http://blog.csdn.net/shaopeng5211/article/details/8827507
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 / ** / * implemeentor / * 行为实现类接口 (Abstraction接口定义了基于Implementor接口的更高层次的操作) / ** public interface Engine { public void installEngine () ; } / ** / * ConcreteImplemeentor / * Implementor子类 / ** public class Engine2000 implements Engine { @Override public void installEngine () { ... } } public class Engine2200 implements Engine { @Override public void installEngine () { ... } } / ** / * Abstraction / * 抽象类接口(接口或抽象类);维护对行为实现(Implementor)的引用 / ** public abstract class Car { private Engine engine; publc Car (Engine engine) { this .engine = engine; } public Engine getEngine () { return engine; } public void setEngine (Engine engine) { this .engine = engine; } public abstract void installEngine () ; } / ** / * Refined Abstraction / * Abstraction子类 / ** public class Bus extends Car { public Bus (Engine engine) { super (engine); } @Override public void installEngine () { ... this .getEngine().installEngine(); } } public class Jeep extends Car { public Jeep (Engine engine) { super (engine); } @Override public void installEngine () { System.out.print("Jeep:" ); this .getEngine().installEngine(); } } / ** / * Client / * Bridge模式的使用者 / ** public class MainClass { public static void main (String args[]) { Engine engine2000 = new Engine2000(); Engine engine2200 = new Engine2200(); Car bus = new Bus(engine2000); bus.installEngine(); Car jeep = new Jeep(engine2200); jeep.installEngine(); } }
感觉桥接模式,有点像……画画的时候,有各种笔,然后颜料也有各种颜色;然后不同的笔可以蘸不同的颜料;
装饰者模式
若要扩展功能,装饰者提供了比集成更有弹性的替代方案,动态地将责任附加到对象上
当我们设计好了一个类,我们需要给这个类添加一些辅助的功能,并且不希望改变这个类的代码,这时候就是装饰者模式大展雄威的时候了
体现了开闭原则
eg:栗子来自:http://blog.csdn.net/lmj623565791/article/details/24269409
这个博主用了游戏系统中装备加宝石,提升属性当做栗子,感觉很有意思;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 public interface IEquip { public int caculateAttack () ; public String description () ; } public class ArmEquip implements IEquip { @Override public int caculateAttack () { return 20 ; } @Override public String description () { return "屠龙刀" ; } } public class RingEquip implements IEquip { @Override public int caculateAttack () { return 5 ; } @Override public String description () { return "圣战戒指" ; } }
装饰器:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 public interface IEquipDecorator extends IEquip { } public class BlueGemDecorator implements IEquipDecorator { private IEquip equip; public BlueGemDecorator (IEquip equip) { this .equip = equip; } @Override public int caculateAttack () { return 5 + equip.caculateAttack(); } @Override public String description () { return equip.description() + "+ 蓝宝石" ; } } public class YellowGemDecorator implements IEquipDecorator { private IEquip equip; public YellowGemDecorator (IEquip equip) { this .equip = equip; } @Override public int caculateAttack () { return 10 + equip.caculateAttack(); } @Override public String description () { return equip.description() + "+ 黄宝石" ; } } public class RedGemDecorator implements IEquipDecorator { private IEquip equip; public RedGemDecorator (IEquip equip) { this .equip = equip; } @Override public int caculateAttack () { return 15 + equip.caculateAttack(); } @Override public String description () { return equip.description() + "+ 红宝石" ; } } package com.zhy.pattern.decorator; public class Test { public static void main (String[] args) { System.out.println(" 一个镶嵌1颗红宝石,1颗蓝宝石,1颗黄宝石的武器" ); equip = new RedGemDecorator(new BlueGemDecorator(new YellowGemDecorator(new ArmEquip()))); System.out.println("攻击力 : " + equip.caculateAttack()); System.out.println("描述 :" + equip.description()); System.out.println("-------" ); } }
组合模式
将对象组合成树形结构以表示“部分-整体”的层次结构。Composite使得用户对单个对象和组合对象的使用具有一致性。
外观模式
提供一个统一的接口,用来访问子系统中的一群接口,外观定义了一个高层的接口,让子系统更容易使用
eg:栗子来自:http://blog.csdn.net/lmj623565791/article/details/25837275
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 public class HomeTheaterFacade { private Computer computer; private Player player; private Light light; private Projector projector; private PopcornPopper popper; public HomeTheaterFacade (Computer computer, Player player, Light light, Projector projector, PopcornPopper popper) { this .computer = computer; this .player = player; this .light = light; this .projector = projector; this .popper = popper; } public void watchMovie () { popper.on(); popper.makePopcorn(); light.down(); projector.on(); projector.open(); computer.on(); player.on(); player.make3DListener(); } public void stopMovie () { popper.off(); popper.stopMakePopcorn(); light.up(); projector.close(); projector.off(); player.off(); computer.off(); } }
感觉像是,将要做一件事的所有步骤,整合到一块;
享元模式
享元模式采用一个共享来避免大量拥有相同内容对象的开销;享元模式以共享的方式高效地支持大量的细粒度对象
像String型,就是享元模式的;
代理模式
为其他对象提供一种代理以控制对这个对象的访问
在某些情况下,一个客户不想或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用
**抽象角色:**声明真实对象和代理对象的共同接口;
**代理角色:**代理对象角色内部含有对真实对象的引用,从而可以操作真实对象,同时代理对象提供与真实对象相同的接口以便在任何时刻都能代替真实对象。同时,代理对象可以在执行真实对象操作时,附加其他的操作,相当于对真实对象进行封装。
**真实角色:**代理角色所代表的真实对象,是我们最终要引用的对象。
静态代理
eg:栗子来自《Java与模式》
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 public abstract class Subject { public abstract void request () ; } public class RealSubject extends Subject { @Override public void request () { } } public class ProxySubject extends Subject { private RealSubject realSubject = null ; @Override public void request () { preRequest(); if (realSubject == null ){ realSubject = new RealSubject(); } realSubject.request(); postRequest(); } private void postRequest () { } private void preRequest () { } } public class Main { public static void main (String[] args) { Subject subject = new ProxySubject(); subject.request(); } }
动态代理
Java动态代理类位于Java.lang.reflect包下
ge:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 package dynamicproxy; public interface Subject { void request () ; } public class RealSubject implements Subject { @Override public void request () { } } import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; public class DynamicSubject implements InvocationHandler { private Object sub; public DynamicSubject (Object sub) { this .sub = sub; } @Override public Object invoke (Object proxy, Method method, Object[] args) throws Throwable { System.out.println("before calling " + method); method.invoke(sub,args); System.out.println("after calling " + method); return null ; } } import java.lang.reflect.Constructor; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Proxy; public class Main { public static void main (String[] args) throws Throwable { RealSubject rs = new RealSubject(); InvocationHandler handler = new DynamicSubject(rs); Class cls = rs.getClass(); Subject subject = (Subject)Proxy.newProxyInstance(cls.getClassLoader(),cls.getInterfaces(), handler); subject.request(); } }
行为型模式
模版方法模式
定义了一个算法的骨架,而将一些步骤延迟到子类中,模版方法使得子类可以在不改变算法结构的情况下,重新定义算法的步骤
模版方法定义了一个算法的步骤,并且允许子类为一个或多个步骤提供实现
eg:栗子来自:http://blog.csdn.net/lmj623565791/article/details/26276093
博主的WorkDay栗子;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 public abstract class Worker { protected String name; public Worker (String name) { this .name = name; } public final void workOneDay () { System.out.println("-----------------work start ---------------" ); enterCompany(); computerOn(); work(); computerOff(); exitCompany(); System.out.println("-----------------work end ---------------" ); } public abstract void work () ; private void computerOff () { System.out.println(name + "关闭电脑" ); } private void computerOn () { System.out.println(name + "打开电脑" ); } public void enterCompany () { System.out.println(name + "进入公司" ); } public void exitCompany () { System.out.println(name + "离开公司" ); } } / * * codeMokey / * public class ITWorker extends Worker { public ITWorker (String name) { super (name); } @Override public void work () { System.out.println(name + "写程序-测bug-fix bug" ); } } public class HRWorker extends Worker { public HRWorker (String name) { super (name); } @Override public void work () { System.out.println(name + "看简历-打电话-接电话" ); } } public class Test { public static void main (String[] args) { Worker it1 = new ITWorker("鸿洋" ); it1.workOneDay(); Worker it2 = new ITWorker("老张" ); it2.workOneDay(); Worker hr = new HRWorker("迪迪" ); hr.workOneDay(); Worker qa = new QAWorker("老李" ); qa.workOneDay(); Worker pm = new ManagerWorker("坑货" ); pm.workOneDay(); } }
命令模式
将“请求”封装成对象,以便使用不同的请求、队列或者日志来参数化其他对象
将请求封装成对象,将动作请求者和动作执行者解耦
eg:栗子来自:http://blog.csdn.net/lmj623565791/article/details/24602057
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 public class Door { public void open () { System.out.println("打开门" ); } public void close () { System.out.println("关闭门" ); } } public class Light { public void on () { System.out.println("打开电灯" ); } public void off () { System.out.println("关闭电灯" ); } } public class Computer { public void on () { System.out.println("打开电脑" ); } public void off () { System.out.println("关闭电脑" ); } } public interface Command { public void execute () ; } public class LightOffCommond implements Command { private Light light ; public LightOffCommond (Light light) { this .light = light; } @Override public void execute () { light.off(); } } public class LightOnCommond implements Command { private Light light ; public LightOnCommond (Light light) { this .light = light; } @Override public void execute () { light.on(); } } public class ComputerOnCommond implements Command { private Computer computer ; public ComputerOnCommond ( Computer computer) { this .computer = computer; } @Override public void execute () { computer.on(); } } public class ComputerOffCommond implements Command { private Computer computer ; public ComputerOffCommond ( Computer computer) { this .computer = computer; } @Override public void execute () { computer.off(); } } public class ControlPanel { private static final int CONTROL_SIZE = 9 ; private Command[] commands; public ControlPanel () { commands = new Command[CONTROL_SIZE]; for (int i = 0 ; i < CONTROL_SIZE; i++) { commands[i] = new NoCommand(); } } public void setCommand (int index, Command command) { commands[index] = command; } public void keyPressed (int index) { commands[index].execute(); } } public class NoCommand implements Command { @Override public void execute () { } } public class Test { public static void main (String[] args) { Light light = new Light(); Door door = new Door(); Computer computer = new Computer(); ControlPanel controlPanel = new ControlPanel(); controlPanel.setCommand(0 , new LightOnCommond(light)); controlPanel.setCommand(1 , new LightOffCommond(light)); controlPanel.setCommand(2 , new ComputerOnCommond(computer)); controlPanel.setCommand(3 , new ComputerOffCommond(computer)); controlPanel.setCommand(4 , new DoorOnCommond(door)); controlPanel.setCommand(5 , new DoorOffCommond(door)); controlPanel.keyPressed(0 ); controlPanel.keyPressed(2 ); controlPanel.keyPressed(3 ); controlPanel.keyPressed(4 ); controlPanel.keyPressed(5 ); controlPanel.keyPressed(8 ); } }
迭代器模式
提供一种方法访问一个容器对象中各个元素,而又不暴露该对象的内部细节
**抽象容器:**一般是一个接口,提供一个iterator()方法,例如java中的Collection接口,List接口,Set接口等。
**具体容器:**就是抽象容器的具体实现类,比如List接口的有序列表实现ArrayList,List接口的链表实现LinkList,Set接口的哈希列表的实现HashSet等。
**抽象迭代器:**定义遍历元素所需要的方法,一般来说会有这么三个方法:取得第一个元素的方法first(),取得下一个元素的方法next(),判断是否遍历结束的方法isDone()(或者叫hasNext()),移出当前对象的方法remove();
**迭代器实现:**实现迭代器接口中定义的方法,完成集合的迭代。
eg:栗子来自:http://blog.csdn.net/zhengzhb/article/details/7610745
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 interface Iterator { public Object next () ; public boolean hasNext () ; } class ConcreteIterator implements Iterator { private List list = new ArrayList(); private int cursor =0 ; public ConcreteIterator (List list) { this .list = list; } public boolean hasNext () { if (cursor==list.size()){ return false ; } return true ; } public Object next () { Object obj = null ; if (this .hasNext()){ obj = this .list.get(cursor++); } return obj; } } interface Aggregate { public void add (Object obj) ; public void remove (Object obj) ; public Iterator iterator () ; } class ConcreteAggregate implements Aggregate { private List list = new ArrayList(); public void add (Object obj) { list.add(obj); } public Iterator iterator () { return new ConcreteIterator(list); } public void remove (Object obj) { list.remove(obj); } } public class Client { public static void main (String[] args) { Aggregate ag = new ConcreteAggregate(); ag.add("小明" ); ag.add("小红" ); ag.add("小刚" ); Iterator it = ag.iterator(); while (it.hasNext()){ String str = (String)it.next(); System.out.println(str); } } }
观察者模式
定义了对象之间的一对多的依赖,这样一来,当一个对象改变时,它的所有的依赖者都会收到通知并自动更新
eg:栗子来自:http://blog.csdn.net/lmj623565791/article/details/24179699
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 public interface Subject { public void registerObserver (Observer observer) ; public void removeObserver (Observer observer) ; public void notifyObservers () ; } public interface Observer { public void update (String msg) ; } import java.util.ArrayList; import java.util.List; public class ObjectFor3D implements Subject { private List<Observer> observers = new ArrayList<Observer>(); private String msg; @Override public void registerObserver (Observer observer) { observers.add(observer); } @Override public void removeObserver (Observer observer) { int index = observers.indexOf(observer); if (index >= 0 ) { observers.remove(index); } } @Override public void notifyObservers () { for (Observer observer : observers) { observer.update(msg); } } public void setMsg (String msg) { this .msg = msg; notifyObservers(); } } public class Observer1 implements Observer { private Subject subject; public Observer1 (Subject subject) { this .subject = subject; subject.registerObserver(this ); } @Override public void update (String msg) { System.out.println("observer1 得到 3D 号码 -->" + msg + ", 我要记下来。" ); } } public class Test { public static void main (String[] args) { ObjectFor3D subjectFor3d = new ObjectFor3D(); Observer observer1 = new Observer1(subjectFor3d); Observer observer2 = new Observer2(subjectFor3d); subjectFor3d.setMsg("20140420的3D号码是:127" ); subjectFor3d.setMsg("20140421的3D号码是:333" ); } }
中介者模式
用一个中介者对象封装一系列的对象交互,中介者使各对象不需要显示地相互作用,从而使耦合松散,而且可以独立地改变它们之间的交互
**抽象中介者:**定义好同事类对象到中介者对象的接口,用于各个同事类之间的通信。一般包括一个或几个抽象的事件方法,并由子类去实现。
**中介者实现类:**从抽象中介者继承而来,实现抽象中介者中定义的事件方法。从一个同事类接收消息,然后通过消息影响其他同时类。
**同事类:**如果一个对象会影响其他的对象,同时也会被其他对象影响,那么这两个对象称为同事类。在类图中,同事类只有一个,这其实是现实的省略,在实际应用中,同事类一般由多个组成,他们之间相互影响,相互依赖。同事类越多,关系越复杂。并且,同事类也可以表现为继承了同一个抽象类的一组实现组成。在中介者模式中,同事类之间必须通过中介者才能进行消息传递。
一般来说,同事类之间的关系是比较复杂的,多个同事类之间互相关联时,他们之间的关系会呈现为复杂的网状结构,这是一种过度耦合的架构,即不利于类的复用,也不稳定。例如有六个同事类对象,假如对象1发生变化,会有4个对象受到影响。如果对象2发生变化,那么会有5个对象受到影响。也就是说,同事类之间直接关联的设计是不好的。
如果引入中介者模式,那么同事类之间的关系将变为星型结构,任何一个类的变动,只会影响的类本身,以及中介者,这样就减小了系统的耦合。一个好的设计,必定不会把所有的对象关系处理逻辑封装在本类中,而是使用一个专门的类来管理那些不属于自己的行为。
eg:栗子来自:http://blog.csdn.net/jason0539/article/details/45216585
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 bstract class AbstractColleague { protected int number; public int getNumber () { return number; } public void setNumber (int number) { this .number = number; } public abstract void setNumber (int number, AbstractColleague coll) ; } class ColleagueA extends AbstractColleague { public void setNumber (int number, AbstractColleague coll) { this .number = number; coll.setNumber(number*100 ); } } class ColleagueB extends AbstractColleague { public void setNumber (int number, AbstractColleague coll) { this .number = number; coll.setNumber(number/100 ); } } abstract class AbstractMediator { protected AbstractColleague A; protected AbstractColleague B; public AbstractMediator (AbstractColleague a, AbstractColleague b) { A = a; B = b; } public abstract void AaffectB () ; public abstract void BaffectA () ; } class Mediator extends AbstractMediator { public Mediator (AbstractColleague a, AbstractColleague b) { super (a, b); } public void AaffectB () { int number = A.getNumber(); B.setNumber(number*100 ); } public void BaffectA () { int number = B.getNumber(); A.setNumber(number/100 ); } } public class Client { public static void main (String[] args) { AbstractColleague collA = new ColleagueA(); AbstractColleague collB = new ColleagueB(); System.out.println("==========设置A影响B==========" ); collA.setNumber(1288 , collB); System.out.println("collA的number值:" +collA.getNumber()); System.out.println("collB的number值:" +collB.getNumber()); System.out.println("==========设置B影响A==========" ); collB.setNumber(87635 , collA); System.out.println("collB的number值:" +collB.getNumber()); System.out.println("collA的number值:" +collA.getNumber()); } }
中介模式能够避免类与类之间的过度耦合;
它将类与类之间的关系转换为星型结构;
备忘录模式
备忘录对象是一个用来存储另外一个对象内部状态的快照的对象。备忘录模式的用意是在不破坏封装的条件下,将一个对象的状态捕捉(Capture)住,并外部化,存储起来,从而可以在将来合适的时候把这个对象还原到存储起来的状态。备忘录模式常常与命令模式和迭代子模式一同使用。
http://www.cnblogs.com/java-my-life/archive/2012/06/06/2534942.html
解释器模式
给定一个语言之后,解释器模式可以定义出其文法的一种表示,并同时提供一个解释器。客户端可以使用这个解释器来解释这个语言中的句子。
http://www.cnblogs.com/java-my-life/archive/2012/06/19/2552617.html
状态模式
允许对象在内部状态改变时改变它的行为,对象看起来好像修改了它的类
当对象的内部状态改变时,它的行为跟随状态的改变而改变了,看起来好像重新初始化了一个类似的。
eg:栗子来自:http://blog.csdn.net/lmj623565791/article/details/26350617
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 public class VendingMachine { private final static int HAS_MONEY = 0 ; private final static int NO_MONEY = 1 ; private final static int SOLD = 2 ; private final static int SOLD_OUT = 3 ; private int currentStatus = NO_MONEY; private int count = 0 ; public VendingMachine (int count) { this .count = count; if (count > 0 ) { currentStatus = NO_MONEY; } } public void insertMoney () { switch (currentStatus) { case NO_MONEY: currentStatus = HAS_MONEY; System.out.println("成功投入硬币" ); break ; case HAS_MONEY: System.out.println("已经有硬币,无需投币" ); break ; case SOLD: System.out.println("请稍等..." ); break ; case SOLD_OUT: System.out.println("商品已经售罄,请勿投币" ); break ; } } public void backMoney () { switch (currentStatus) { case NO_MONEY: System.out.println("您未投入硬币" ); break ; case HAS_MONEY: currentStatus = NO_MONEY; System.out.println("退币成功" ); break ; case SOLD: System.out.println("您已经买了糖果..." ); break ; case SOLD_OUT: System.out.println("您未投币..." ); break ; } } public void turnCrank () { switch (currentStatus) { case NO_MONEY: System.out.println("请先投入硬币" ); break ; case HAS_MONEY: System.out.println("正在出商品...." ); currentStatus = SOLD; dispense(); break ; case SOLD: System.out.println("连续转动也没用..." ); break ; case SOLD_OUT: System.out.println("商品已经售罄" ); break ; } } private void dispense () { switch (currentStatus) { case NO_MONEY: case HAS_MONEY: case SOLD_OUT: throw new IllegalStateException("非法的状态..." ); case SOLD: count--; System.out.println("发出商品..." ); if (count == 0 ) { System.out.println("商品售罄" ); currentStatus = SOLD_OUT; } else { currentStatus = NO_MONEY; } break ; } } }
策略模式
定义了算法族,分别封装起来,让它们之间可相互替换,此模式让算法的变化独立于使用算法的客户
(代码好长啊……懒得贴了)
传送门:http://blog.csdn.net/lmj623565791/article/details/24116745
职责链模式(责任链模式)
责任链模式,我记得Android的事件分发机制就是责任链模式的;
之前在学习分发机制的时候有过一些记录:Android自定义View——事件分发机制学习笔记
责任链模式是一种对象的行为模式。在责任链模式里,很多对象由每一个对象对其下家的引用而连接起来形成一条链。请求在这个链上传递,直到链上的某一个对象决定处理此请求。发出这个请求的客户端并不知道链上的哪一个对象最终处理这个请求,这使得系统可以在不影响客户端的情况下动态地重新组织和分配责任。
有一种比较简单的解释大概是酱紫的:领导给小组长安排工作,然后小组长再把工作分配给组员;如果组员做的了就揽下来,否则反馈给组长;若组长做的了就揽下来;
**抽象处理者(Handler)角色:**定义出一个处理请求的接口。如果需要,接口可以定义 出一个方法以设定和返回对下家的引用。这个角色通常由一个Java抽象类或者Java接口实现。上图中Handler类的聚合关系给出了具体子类对下家的引用,抽象方法handleRequest()规范了子类处理请求的操作。
**具体处理者(ConcreteHandler)角色:**具体处理者接到请求后,可以选择将请求处理掉,或者将请求传给下家。由于具体处理者持有对下家的引用,因此,如果需要,具体处理者可以访问下家。
eg:栗子来自:http://www.cnblogs.com/java-my-life/archive/2012/05/28/2516865.html
《Java与模式》
1.抽象处理者:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 public abstract class Handler { protected Handler successor; public abstract void handleRequest () ; public Handler getSuccessor () { return successor; } public void setSuccessor (Handler successor) { this .successor = successor; } }
2.具体处理者
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 public class ConcreteHandler extends Handler { @Override public void handleRequest () { if (getSuccessor() != null ) { System.out.println("放过请求" ); getSuccessor().handleRequest(); }else { System.out.println("处理请求" ); } } }
3.Test:
1 2 3 4 5 6 7 8 9 10 11 12 public class Client { public static void main (String[] args) { Handler handler1 = new ConcreteHandler(); Handler handler2 = new ConcreteHandler(); handler1.setSuccessor(handler2); handler1.handleRequest(); } }
深入学习:http://www.cnblogs.com/java-my-life/archive/2012/05/28/2516865.html
访问者模式