设计模式总结
1 设计原则
1 单一责任原则,一个类应该只有一个责任,如果有多个责任,责任就会耦合,如实现逻辑和界面的责任分开。
2 开闭原则:对扩展开发,对修改关闭。我们可以扩展模块的功能,但是不必改动原模块的代码 如使用接口和抽象类,关键是抽象化
3 里氏代换原则:任何基类出现的地方,子类一定可以出现,是对开闭原则的补充,开闭原则关键是抽象,而里氏代换的基类和子类就是抽象的具体化。
4 依赖倒转原则:依赖于抽象,不要依赖于具体,就是对抽象编程,可以降低模块间的耦合
5 接口隔离原则,客户端不应该依赖他不需要的接口。一个对的另一个类的依赖应该建立在最小接口上,使用多个专门接口比使用单一接口好,如用户使用订单查询,他就应该使用一个订单查询接口
6 合成复用原则,尽量使用组合和聚合关系,少用继承,新对象通过委派调用已有对象的方法达到复用的目的
7 最少知道法则:一个对象应该对其他对象尽可能少的了解。尽可能低的降低耦合,使得系统模块相互独立,如果必须联系可以通过中介。中介模式和门面模式就是最少知道法则的运用
2 对象的创建模式
对象的创建需要很多资源,把对象的创建和对象的使用分开,
1 工厂方法模式,设计4个角色,抽象产品,具体产品,抽象工厂,具体工厂,模式很好的符合开闭原则,如果有新产品的增加,只需要增加一个创建具体产品的具体工厂即可,把创建产品的行为推迟到了子类。
abstract class Dog{ public abstract void eat(); } class WhiteDog extends Dog{ @Override public void eat() { // TODO Auto-generated method stub System.out.println("whiteDog eat"); } } abstract class DogFactory{ public abstract Dog createDog(); } class WhiteDogFactory extends DogFactory { @Override public Dog createDog() { // TODO Auto-generated method stub return new WhiteDog(); } }
2 抽象工厂模式, 涉及4个角色, 抽象产品,具体产品,抽象工厂,具体工厂,和工厂方法模式不同的是,抽象工厂可以创建具有多个产品等级结构的的子系统,而这些子系统形成一个,一个的产品族,如果使用工厂方法模式,则需要多个产品等级结构的的抽象工厂。用在系统中,等级结构个数不变化中。
interface Gardener{ Fruit createFruit(); Vegetable createVegetable(); } class NorthernGardener implements Gardener{ @Override public Fruit createFruit() { // TODO Auto-generated method stub return new NorthernFruit(); } @Override public Vegetable createVegetable() { // TODO Auto-generated method stub return new NorthernVegetable(); } } class TropicalGardener implements Gardener{ @Override public Fruit createFruit() { // TODO Auto-generated method stub return new TropicalFruit(); } @Override public Vegetable createVegetable() { // TODO Auto-generated method stub return new TropicalVegetable(); } } interface Fruit{} interface Vegetable{} class NorthernFruit implements Fruit{} class TropicalFruit implements Fruit{} class NorthernVegetable implements Vegetable{} class TropicalVegetable implements Vegetable{}
3 单例模式 单例模式能确保一个类只有一个实例,并且自行实例化,向整个系统提供这个实例 其中Java runtime就是一个单例类
class Runtime { private static Runtime currentRuntime = new Runtime(); private Runtime(){} public static Runtime getRuntime() { return currentRuntime; } } class Runtime { private static Runtime currentRuntime = null; private Runtime(){} public static synchronized Runtime getRuntime() { if (currentRuntime == null) { currentRuntime = new Runtime(); } return currentRuntime; } }
4 建造者模式, 涉及4个角色, 抽象建造者(定义产品各个成分建造过程,和返回产品),具体建造者, 产品,和指导者,客户端和指导者通信,可以将一个产品表象和建造过程分开,适合创建比较复杂对象。如果一个零件依赖于另一个零件,也可以使用
class Person { private String head; private String body; private String foot; public String getHead() { return head; } public void setHead(String head) { this.head = head; } public String getBody() { return body; } public void setBody(String body) { this.body = body; } public String getFoot() { return foot; } public void setFoot(String foot) { this.foot = foot; } } class Man extends Person { public Man() { System.out.println("man build"); } } interface PersonBuilder { void buildhead(); void buildbody(); void buildfoot(); Person buildPerson(); } class Manbuilder implements PersonBuilder { private Person p; public Manbuilder() { super(); this.p = new Man(); } @Override public void buildhead() { // TODO Auto-generated method stub p.setHead("man head"); } @Override public void buildbody() { // TODO Auto-generated method stub p.setBody("man body"); } @Override public void buildfoot() { // TODO Auto-generated method stub p.setFoot("man foot"); } @Override public Person buildPerson() { // TODO Auto-generated method stub return p; } } class PersonDirect { public Person constructPerson(PersonBuilder p) { p.buildbody(); return p.buildPerson(); } }
5 原型模式,涉及3个角色, 客户端(提出创建对象请求),抽象原型角色(给出具体原型需要接口),具体原型角色,通过一个原型对象指明创建对象的类型,通过复制对象的方法创建对象。
interface My extends Cloneable { public Object clone(); } class CMy implements My{ public Object clone() { try { return super.clone(); } catch (Exception e) { // TODO: handle exception } return null; } } class Client{ My getMy(My m) { return (My) m.clone(); } }
3 结构型模式
处理类和对象的组合,描述如何组织类和对象来创建更大的结构,结构类模式采用继承,结构对象模式采用聚合和组合实现新功能
1 适配器模式 解决客户端接口和已有功能接口不兼容问题,将已有功能接口适配成客户端兼容接口,如手机充电器交流变直流,
类的适配器模式包括Target(目标角色),adaptee(源角色)adapter(适配器角色)
interface target{ void operation1(); void operation2(); } class adaptee { public void Peration1(){ } public void Peration2() { } } class Adapter extends adaptee implements target { @Override public void operation1() { // TODO Auto-generated method stub Peration1(); } @Override public void operation2() { // TODO Auto-generated method stub Peration2(); } }
与类的适配模式使用继承不同,对象的适配使用委派关系,角色和上面相同
interface target{ void operation1(); void operation2(); } class Adaptee { public void Peration1(){ } public void Peration2() { } } class Adapter implements target { private Adaptee adaptee; public Adapter(Adaptee a) { adaptee = a; } @Override public void operation1() { // TODO Auto-generated method stub adaptee.Peration1(); } @Override public void operation2() { // TODO Auto-generated method stub adaptee.Peration2(); } }
2 桥梁模式 作用是把抽象和具体实现分开,可以使两者独立的变化,继承是一种强耦合,他把抽象化角色和具体化角色绑定,两者之间相互牵制,无法独立变化。其中包括抽象和具体两个等级结构,包括Abastaction抽象化角色(保存一个实现化对象引用), refined abstraction修正抽象化(修正父类对抽象化定义),implementer实现化, concrete implementer具体实现化
abstract class Abstraction { protected Implementer implementer; public void operation() { implementer.operationImp(); } } class RefinedAbstracton extends Abstraction{ // 修正 public void operation() { } } abstract class Implementer { public abstract void operationImp(); } class ConcreteImplementer extends Implementer { @Override public void operationImp() { // TODO Auto-generated method stub System.out.println(" fdf "); } }
3 合成模式 又叫部分和整体模式,将对象组织到树结构中,可以使客户端将单纯元素和复合元素同等看待。包括Componenet(抽象构件)给出组合对象的公共接口,leaf(树叶), composite(树枝)。
interface Component { Composite getComposite(); void operation(); } class Composite implements Component { private Vector<Component> coms; @Override public Composite getComposite() { // TODO Auto-generated method stub return this; } @Override public void operation() { Enumeration<Component> e = enumeration(); while (e.hasMoreElements()) { e.nextElement().operation(); } } public void add(Component com) { coms.addElement(com); } public void remove(Component com) { coms.remove(com); } public Enumeration<Component> enumeration() { return coms.elements(); } } class Leaf implements Component { @Override public Composite getComposite() { // TODO Auto-generated method stub return null; } @Override public void operation() { // TODO Auto-generated method stub } }
4 装饰模式, 适配器模式主要适配两个不相兼容的接口,不一定要改变对象的性能,装饰模式要保持接口,从而增强所考虑对象的性能。
包括component(抽象构件,规范准备接收附加责任的对象),concrete componenet具体构件,decorator 装饰,持有一个构件对象实例,并定义一个与构件接口一致的接口 concrete decorator 具体装饰,给构件加附加责任。
abstract class Componenet { public abstract void operate(); } class ConcreteComponent extends Componenet { @Override public void operate() { // TODO Auto-generated method stub System.out.println("sdew"); } } class Decorator extends Componenet { protected Componenet com; public Decorator(Componenet com) { super(); this.com = com; } @Override public void operate() { // TODO Auto-generated method stub com.operate(); } } class ConcreteDecrator extends Decorator { public ConcreteDecrator(Componenet com) { super(com); // TODO Auto-generated constructor stub } @Override public void operate() { // TODO Auto-generated method stub super.operate(); System.out.println("add opper"); } }
5 门面模式 外部与一个子系统通信必须通过一个统一门面对象进行。包括两个角色,门面(客户端调用这个角色方法)和子系统
class Client { private Face face; public Client(Face face) { super(); this.face = face; } public void turnon() { face.turnon(); } } class Face { private Light light; private Door door; public Face(Light light, Door door) { super(); this.light = light; this.door = door; } public void turnon() { light.turnon(); door.turnon(); } public void turnoff() { light.turnoff(); door.turnoff(); } } class Light { public void turnon(){ System.out.println("light turn on"); } public void turnoff(){ System.out.println("light turn off"); } } class Door { public void turnon(){ System.out.println("door turn on"); } public void turnoff(){ System.out.println("door turn off"); } }
6 享元模式 享元对象分为内蕴状态(存储在享元对象内部,不随环境改变有所不同,内蕴状态可以共享),外蕴状态(随环境改变而改变,不可共享,用客户端保存,在需要的时候传入享元对象内部。)包括,抽象享元角色(规定出需要实现的接口,外蕴状态可以通过商业方法参数传入),具体享元(实现抽象享元角色接口,如果有内蕴状态,为内蕴状态分配空间),享元工厂(负责创建和共享享元角色)。客户端(维护一个对所有享元对象的引用,存储所有享元对象外蕴状态)
class Table{ private int num; public int getNum() { return num; } public void setNum(int num) { this.num = num; } } abstract class Order { public abstract void service(Table table); public abstract String getFlavor(); } class Flavor extends Order { private String flavor; public Flavor(String flavor) { super(); this.flavor = flavor; } @Override public void service(Table table) { // TODO Auto-generated method stub System.out.println(" server table " + table.getNum() + " with flvor "+ this.flavor);; } @Override public String getFlavor() { // TODO Auto-generated method stub return this.flavor; } } class FlavorFactory { private Order[] flavors = new Order[10]; private int ordreMade = 0; public Order gerFlavor(String f) { for (int i = 0; i < ordreMade; i++) { if (f.equals(flavors[i].getFlavor())) { return flavors[i]; } } flavors[ordreMade] = new Flavor(f); return flavors[ordreMade++]; } } class Client { private static Order[] flavors = new Order[1000]; private static FlavorFactory factory = new FlavorFactory(); private int num; public Order getOrder(String flavor) { flavors[num] = factory.gerFlavor(flavor); return flavors[num++]; } }
7 代理模式 装饰模式与所装饰的对象有相同接口,但是装饰模式应当为所装饰对象提供增强功能,而代理模式对对象的使用施加控制,并不增强对象本身功能。通过代理对象访问真实对象,包括抽象主题角色(真实主题和代理主题的共同接口,)代理角色 (有真实主题引用)真实主题
interface Getkd{ void getkd(); } class You implements Getkd{ String name; public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public void getkd() { // TODO Auto-generated method stub System.out.println(getName() + " getkd"); } } class Friend implements Getkd { Getkd you; public Friend(Getkd you) { this.you = you; } @Override public void getkd() { System.out.println("取快递前吃饭"); you.getkd(); System.out.println("取玩快递买西瓜"); } }
4 行为型模式 主要描述类或对象怎么交互和怎么分配职责的。
1 责任链模式 很多对象由每一个i对象对其下家的引用而连接起来形成连,请求在链上传递,直到链上的一个对象处理请求。客户端不知道哪个对象处理请求,系统在不影响客户端的情况下动态组织连和分配责任。包括handler抽象处理者(包含对下家的引用和处理请求方法),concreteHandler(具体处理)
abstract class Handler { protected Handler handler; public Handler getHandler() { return handler; } public void setHandler(Handler handler) { this.handler = handler; } public abstract void handleRequest(); } class ConcreteHanlder extends Handler { @Override public void handleRequest() { // TODO Auto-generated method stub if (getHandler() != null) { getHandler().handleRequest(); } else { System.out.println("handler request"); } } }
2 命令模式: 是对命令的封装,把发出命令的责任和执行命令的责任分开,允许请求的一方和接收请求的一方独立演化,包括客户端(client )命令角色(command具体命令的抽象接口),具体命令 (concrete command), 调用者(invoker,负责调用命令执行请求),接收者(receiver) 负责具体实施和执行请求。
interface Command{ void execute(); } class ConcreteCommand implements Command { @Override public void execute() { // TODO Auto-generated method stub System.out.println("Concrete Command"); } } class Invoker { private Command command; public Invoker(Command command) { super(); this.command = command; } public void action() { command.execute(); } }
3 解释器模式: 定义了一种文法,并定义一个解释器来解释复合文法的句子。包括抽象表达式(所有表达式都要实现的接口,interpret),终结符表达式(如组合模式中的叶节点),非终结符表达式(树枝节点),环境角色(各个解释器需要的数据和公共功能)。在解释器模式中可以通过一种称之为抽象语法树(Abstract Syntax Tree, AST)的图形方式来直观地表示语言的构成,每一棵抽象语法树对应一个语言实例
interface Node { int interpret(); } class ValueNode implements Node { protected int value; public ValueNode(int value) { super(); this.value = value; } @Override public int interpret() { // TODO Auto-generated method stub return value; } } abstract class SymbolNode implements Node { protected Node left; protected Node right; public SymbolNode(Node left, Node right) { super(); this.left = left; this.right = right; } } class MulNode extends SymbolNode { public MulNode(Node left, Node right) { super(left, right); // TODO Auto-generated constructor stub } @Override public int interpret() { // TODO Auto-generated method stub return left.interpret() * right.interpret(); } } class DivNode extends SymbolNode{ public DivNode(Node left,Node right){ super(left,right); } public int interpret(){ return super.left.interpret() / super.right.interpret(); } } class Calculator { private String state; private Node node; public void build(String statement) { Node left = null, right = null; Stack<Node> stack = new Stack<>(); String[] arr = statement.split(" "); for (int i = 0; i < arr.length; i++) { if (arr[i].equals("*")) { left = stack.pop(); right = new ValueNode(Integer.parseInt(arr[++i])); Node node = new MulNode(left, right); stack.push(node); } else if (arr[i].equals("/")) { left = stack.pop(); right = new ValueNode(Integer.parseInt(arr[++i])); Node node = new MulNode(left, right); stack.push(node); } else { Node node = new ValueNode(Integer.parseInt(arr[i])); stack.push(node); } } this.node = stack.pop(); } public int compute() { return node.interpret(); } }
4 迭代模式 :迭代模式可以顺序访问一个聚集中的元素而不必暴露聚集的内部表象, 包括抽象迭代子(Iterator),具体迭代子(concreteiterator如ArrayLIst的内部类Itr),聚集(里面有一个提供迭代子的接口),具体聚集
interface Iterator<E> { boolean hasNext(); E next(); void remove(); } interface Collection<E> extends Iterable<E> { } class List implements Collection{ @Override public java.util.Iterator iterator() { // TODO Auto-generated method stub return null; } }
5 中介者模式:使用一个中介者对象封装系统中各个对象的交互,使系统各个对象不必显示的相互引用,从而使其耦合松散,把系统的网状关系变为星型关系。包括mediator(抽象调停者,各个同事相互交互的接口,就是所谓的事件), concrete mediator(具体调停者,有同事的引用,他从同事接收消息,并向有关同事发送消息),colleague(抽象同事,一班有调停者引用), 具体同事
abstract class Mediator { public abstract void colleagueChange(Colleague c); } abstract class Colleague { protected Mediator mediator; public Colleague(Mediator mediator) { super(); this.mediator = mediator; } // mediator notify public abstract void action(); public void change() { mediator.colleagueChange(this); } } class Colleague1 extends Colleague { public Colleague1(Mediator mediator) { super(mediator); } @Override public void action() { // TODO Auto-generated method stub System.out.println(" i know"); } } class Colleague2 extends Colleague { public Colleague2(Mediator mediator) { super(mediator); } @Override public void action() { // TODO Auto-generated method stub System.out.println(" i know"); } } class ConcreteMediator extends Mediator { private Colleague1 c1; private Colleague2 c2; public void createConcreteC() { c1 = new Colleague1(this); c2 = new Colleague2(this); } @Override public void colleagueChange(Colleague c) { // TODO Auto-generated method stub c1.action(); c2.action(); } }
6 观察者模式: 观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听一个主题对象,当主题对象在状态上发生变化时,会通知所有观察者对象,使他们能够自行更新自己。包括抽象主题(subject所有观察者的聚集,可以添加,删除观察者),抽象观察者(observer, 当主题变化时有update方法),具体主题,具体观察者。Java有对观察者模式的直接支持
class Watched extends Observable { private String data = ""; public String getData() { return data; } public void changeData(String data) { if (!this.data.equals(data)) { this.data = data; setChanged(); } notifyObservers(); } } class Watcher implements Observer { public Watcher(Watched watched) { watched.addObserver(this); } @Override public void update(Observable o, Object arg) { // TODO Auto-generated method stub System.out.println("change" + ((Watched)o).getData()); } }
7 状态模式,允许一个对象在其内部状态改变的时候改变其行为,把所研究的行为包装在不同的状态对象里,每一个状态对象都属于一个状态类的子类,包括环境(context,保留一个具体状态类的实例,给出此环境的现有状态),抽象状态(state,接口封装对象一个特定状态所具有的行为)
interface TCPState { void open(); void close(); } class TCPEstablish implements TCPState { @Override public void open() { // TODO Auto-generated method stub } @Override public void close() { // TODO Auto-generated method stub } } class TCPClose implements TCPState { @Override public void open() { // TODO Auto-generated method stub } @Override public void close() { // TODO Auto-generated method stub } } class TCPConnection{ private TCPState state; public TCPState getState() { return state; } public void setState(TCPState state) { this.state = state; } public void open() { state.open(); } public void close() { state.close(); } }
8 备忘录模式: 备忘录是一个用来存储另一个对象内部状态的快照的对象,将一个对象 的状态捕捉住,并外部化存起来,将来可以把对象还原到存储起来的状态。包括memento备忘录角色(将发起人对象内部状态存储,提供一个窄接口给负责人,只允许传备忘录,宽接口给发起人,可以读备忘录),originator发起人,创建一个备忘录,从备忘录恢复, caretaker负责人,负责保存备忘录对象。
class Originator { private String state; public Originator() { super(); // TODO Auto-generated constructor stub } public String getState() { return state; } public void setState(String state) { this.state = state; } public MementoIF createMEmento() { return new Memento(this.state); } public void restoreMEmento(MementoIF if1) { Memento m = (Memento) if1; setState(m.getSaveState()); } public class Memento implements MementoIF { private String saveState; public Memento(String saveState) { super(); this.saveState = saveState; } public String getSaveState() { return saveState; } public void setSaveState(String saveState) { this.saveState = saveState; } } } interface MementoIF {} class CareTaker { private MementoIF mementoIF; public MementoIF getMementoIF() { return mementoIF; } public void setMementoIF(MementoIF mementoIF) { this.mementoIF = mementoIF; } }
9 策略模式: 将一个算法封装到具有共同接口的独立类中,从而使得他们可以相互替换,使得算法可以在不影响到客户端的情况下发生变化。包括Context(环境:有一个strategy类引用), Strategy(抽象策略),concreteStrategy(具体策略)
10 模版方法模式:准备一个抽象类,将部分逻辑以具体方法的形式实现,然后声明一些抽象方法来迫使子类实现剩余逻辑,就是继承。包括抽象模版,具体模版。
11访问者模式:封装一些施加于某种数据结构元素上的操作,一旦这些操作需要修改的话,接受这个操作的数据结构可以保持不变。
包括抽象访问者visitor(有一个声明一个visit方法,用来代表为对象结构添加的功能), 具体访问者,Element抽象数据元素(通常有一个accept方法,接收访问者)