常见设计模式的种类与一些原则
一、设计模式
1、简单工厂模式
public class OperationFactory { public static Operation createOperation(String operate) { Operation oper = null; switch (operate) { case "+": oper = new OperationAdd(); break; case "-": oper = new OperationMinus(); break; case "*": oper = new OperationMul(); break; case "/": oper = new OperationDiv(); break; } return oper; } }
2、策略模式
定义了算法家族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化不会影响到使用算法的客户
1 package design.strategy; 2 3 /** 4 * Created by adrian.wu on 2019/5/22. 5 */ 6 public class Context { 7 Strategy strategy; 8 9 public Context(Strategy strategy) { 10 this.strategy = strategy; 11 } 12 13 public void ContextInterface() { 14 strategy.AlgorithmInterface(); 15 } 16 17 public static void main(String[] args) { 18 Context context; 19 context = new Context(new ConcreteStrategyA()); 20 context.ContextInterface(); 21 22 context = new Context(new ConcreteStrategyB()); 23 context.ContextInterface(); 24 25 context = new Context(new ConcreteStrategyC()); 26 context.ContextInterface(); 27 } 28 }
3、装饰模式
动态的给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更为灵活
1 package design.component; 2 3 /** 4 * Created by adrian.wu on 2019/5/21. 5 */ 6 abstract public class Component { 7 abstract public void operation(); 8 }
1 package design.component; 2 3 /** 4 * Created by adrian.wu on 2019/5/21. 5 */ 6 public class ConcreteComponent extends Component{ 7 @Override 8 public void operation() { 9 10 } 11 }
1 package design.component; 2 3 /** 4 * Created by adrian.wu on 2019/5/21. 5 */ 6 public class ConcretedDecoratorA extends Decorator { 7 private String addedState; 8 9 @Override 10 public void operation() { 11 super.operation(); 12 addedState = "New State"; 13 } 14 }
1 package design.component; 2 3 /** 4 * Created by adrian.wu on 2019/5/21. 5 */ 6 public class ConcretedDecoratorB extends Decorator { 7 @Override 8 public void operation() { 9 super.operation(); 10 addedBehavior(); 11 } 12 13 private void addedBehavior() { 14 15 } 16 }
1 package design.component; 2 3 /** 4 * Created by adrian.wu on 2019/5/21. 5 */ 6 public class Decorator extends Component { 7 protected Component component; 8 9 public void setComponent(Component component) { 10 this.component = component; 11 } 12 13 @Override 14 public void operation() { 15 if (component != null) { 16 component.operation(); 17 } 18 } 19 }
1 package design.component; 2 3 /** 4 * Created by adrian.wu on 2019/5/21. 5 */ 6 public class DecoratorMain { 7 public static void main(String[] args) { 8 ConcreteComponent c = new ConcreteComponent(); 9 ConcretedDecoratorA d1 = new ConcretedDecoratorA(); 10 ConcretedDecoratorB d2 = new ConcretedDecoratorB(); 11 12 d1.setComponent(c); 13 d2.setComponent(d1); 14 d2.operation(); 15 } 16 }
Component是定义一个对象接口,可以给这些对象动态地添加职责。ConcreteComponent是定义了一个具体的对象,也可以给这个对象添加一些职责。Decorator,装饰抽象类,继承了Component,从外类扩展Component类的功能,但对于Component来说,是无需知道Decorator的存在的,
4、代理模式
为其它对象提供一种代理以控制对这个对象的访问
1 package design.prox; 2 3 /** 4 * Created by adrian.wu on 2019/5/21. 5 */ 6 interface GiveGift { 7 void giveDolls(); 8 9 void giveFlowers(); 10 11 void giveChocolate(); 12 }
1 package design.prox; 2 3 /** 4 * Created by adrian.wu on 2019/5/21. 5 */ 6 public class Proxy implements GiveGift { 7 Pursuit gg; 8 9 public Proxy(SchoolGirl mm) { 10 gg = new Pursuit(mm); 11 } 12 13 public void giveDolls() { 14 } 15 16 public void giveFlowers() { 17 18 } 19 20 public void giveChocolate() { 21 22 } 23 }
1 package design.prox; 2 3 /** 4 * Created by adrian.wu on 2019/5/21. 5 */ 6 public class Pursuit implements GiveGift { 7 SchoolGirl mm; 8 9 public Pursuit(SchoolGirl mm) { 10 this.mm = mm; 11 } 12 13 public void giveDolls() { 14 15 } 16 17 public void giveFlowers() { 18 19 } 20 21 public void giveChocolate() { 22 23 } 24 }
1 package design.prox; 2 3 /** 4 * Created by adrian.wu on 2019/5/21. 5 */ 6 public class SchoolGirl { 7 public String name; 8 }
代理模式的应用:
- 远程代理。就是为一个对象在不同的地址空间提供局部代表。这样可以隐藏一个对象存在于不同地址空间的事实。
- 虚拟代理。是根据需要创建开销很大的对象。通过它来存放实例化需要很长时间的真实对象。
- 安全代理。用来控制真实对象访问时的权限。
5、工厂模式
相比较于简单工厂模式,这里把抽象类换成了接口
package design.ifactory; /** * Created by adrian.wu on 2019/5/22. */ interface IFactory { LeiFeng createLeiFeng(); }
package design.ifactory; /** * Created by adrian.wu on 2019/5/22. */ public class LeiFeng { public void sweep() { } public void wash() { } public void buyRice() { } }
package design.ifactory; /** * Created by adrian.wu on 2019/5/22. */ public class UndergraduateFactory implements IFactory { public LeiFeng createLeiFeng() { return new Undergradute(); } }
package design.ifactory; /** * Created by adrian.wu on 2019/5/22. */ public class Undergradute extends LeiFeng{ }
package design.ifactory; /** * Created by adrian.wu on 2019/5/22. */ public class Volunteer extends LeiFeng { }
package design.ifactory; /** * Created by adrian.wu on 2019/5/22. */ public class VolunteerFactory implements IFactory { @Override public LeiFeng createLeiFeng() { return new Volunteer(); } }
6、原型模式
用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
1 package design.prototype; 2 3 /** 4 * Created by adrian.wu on 2019/5/22. 5 */ 6 abstract public class Prototype { 7 public String id; 8 9 public Prototype(String id) { 10 this.id = id; 11 } 12 13 abstract public Prototype clone(); 14 }
package design.prototype; /** * Created by adrian.wu on 2019/5/22. */ public class ConcretePrototype1 extends Prototype { public ConcretePrototype1(String id) { super(id); } @Override public Prototype clone() { return (Prototype) this.MemberwiseClone(); } }
注意使用好深浅拷贝的时机就好
7、模版方法模式
既然用了继承,并且肯定这个继承有意义,就应该要成为子类的模版,所有重复的代码都应该要上升到父类中,而不是让每个子类都去重复。当我们要完成在某一细节层次一致的一个过程或一系列步骤。但其个别步骤在更详细的层次上的实现可能不同时,我们通常考虑模版方法模式来处理。
定义一个操作中的算法骨架,而将一些步骤延迟到子类中,模版方法使得子类可以不改变一个算法的结构可重定义该算法的某些特定步骤。
package design.template; /** * Created by adrian.wu on 2019/5/22. */ abstract public class AbstractClass { abstract public void PrimitiveOperation1(); abstract public void PrimitiveOperation2(); public void TemplateMethod() { PrimitiveOperation1(); PrimitiveOperation2(); } }
1 package design.template; 2 3 /** 4 * Created by adrian.wu on 2019/5/22. 5 */ 6 public class ConcreteClassA extends AbstractClass { 7 @Override 8 public void PrimitiveOperation1() { 9 System.out.println("A ope1"); 10 } 11 12 @Override 13 public void PrimitiveOperation2(){ 14 System.out.println("A ope2"); 15 } 16 }
package design.template; /** * Created by adrian.wu on 2019/5/22. */ public class ConcreteClassB extends AbstractClass { @Override public void PrimitiveOperation1() { System.out.println("B ope1"); } @Override public void PrimitiveOperation2(){ System.out.println("B ope2"); } }
package design.template; /** * Created by adrian.wu on 2019/5/22. */ public class Main { public static void main(String[] args) { AbstractClass c; c = new ConcreteClassA(); c.TemplateMethod(); c = new ConcreteClassB(); c.TemplateMethod(); } }
8、外观模式
为子系统中的一组接口提供一个一致的界面。此模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。
package design.waiguanmoshi; /** * Created by adrian.wu on 2019/5/22. */ public class Facade { private SubSystemOne one; private SubSystemTwo two; private SubSystemThree three; private SubSystemFour four; public Facade() { one = new SubSystemOne(); two = new SubSystemTwo(); three = new SubSystemThree(); four = new SubSystemFour(); } public void MethodA() { one.Method1(); System.out.println("1"); } public void MethodB() { one.Method1(); System.out.println("2"); } public void MethodC() { one.Method1(); System.out.println("3"); } public void MethodD() { one.Method1(); System.out.println("4"); } }
1 package design.waiguanmoshi; 2 3 /** 4 * Created by adrian.wu on 2019/5/22. 5 */ 6 public class SubSystemOne { 7 public void Method1() { 8 9 } 10 } 11 12 13 public class SubSystemTwo { 14 public void Method2() { 15 16 } 17 } 18 19 20 public class SubSystemThree { 21 public void Method3() { 22 23 } 24 } 25 26 public class SubSystemFour { 27 public void Method4() { 28 29 } 30 }
使用外观模式:
- 首先,在设计初期阶段,应该有意识的将不同的两个层分离。
- 其次,在开发阶段,子系统往往因为不断的重构演化而变得越来越复杂
- 增加外观Facade可以提供一个简单的接口,减少它们之间的依赖。
- 在维护一个遗留的大型系统时,可能这个系统已经非常难以维护和扩展了,可以为新系统开发一个外观Facade类,来提供设计粗糙或高度复杂的遗留代码的比较清晰简单的接口,让新系统与Facde对象交互,Facade与遗留代码交互所有复杂的工作
9、建造者模式
将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
1 package design.product; 2 3 /** 4 * Created by adrian.wu on 2019/5/22. 5 */ 6 abstract public class Builder { 7 abstract public void buildPartA(); 8 9 abstract public void buildPartB(); 10 11 abstract public Product getResult(); 12 }
package design.product; /** * Created by adrian.wu on 2019/5/22. */ public class ConcreteBuilder1 extends Builder { private Product product = new Product(); public void buildPartA() { product.add("A"); } public void buildPartB() { product.add("B"); } public Product getResult() { return product; } }
package design.product; /** * Created by adrian.wu on 2019/5/22. */ public class ConcreteBuilder2 extends Builder { private Product product = new Product(); public void buildPartA() { product.add("A"); } public void buildPartB() { product.add("B"); } public Product getResult() { return product; } }
package design.product; /** * Created by adrian.wu on 2019/5/22. */ public class Director { public void Construct(Builder builder) { builder.buildPartA(); builder.buildPartB(); } }
package design.product; import java.util.ArrayList; import java.util.List; /** * Created by adrian.wu on 2019/5/22. */ public class Product { List<String> parts = new ArrayList<>(); public void add(String part) { parts.add(part); } public void show() { } }
创建者模式是在当创建复杂对象的算法应该独立于该对象的组成部分以及它们的装配方式时适用的模式。
10、观察者模式
定义了一种一对多的依赖关系,让多个观察者对象同时监听某个主题对象。这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己。
1 package design.observe; 2 3 import java.util.ArrayList; 4 import java.util.List; 5 6 /** 7 * Created by adrian.wu on 2019/5/22. 8 */ 9 public class Subject { 10 private List<Observer> observers = new ArrayList<>(); 11 12 public void attach(Observer observer) { 13 observers.add(observer); 14 } 15 16 public void detach(Observer observer) { 17 observers.remove(observer); 18 } 19 20 public void Notify() { 21 22 } 23 }
1 package design.observe; 2 3 /** 4 * Created by adrian.wu on 2019/5/22. 5 */ 6 abstract public class Observer { 7 public abstract void update(); 8 }
package design.observe; /** * Created by adrian.wu on 2019/5/22. */ public class ConcreteSubject extends Subject { private String subjectState; public String SubjectState() { return ""; } }
package design.observe; /** * Created by adrian.wu on 2019/5/22. */ public class ConcreteObserver extends Observer { private String name; private String observerState; private ConcreteSubject subject; public ConcreteObserver(ConcreteSubject subject, String name) { this.subject = subject; this.name = name; } @Override public void update() { } public ConcreteSubject subject() { return subject; } }
package design.observe; /** * Created by adrian.wu on 2019/5/22. */ public class Main { public static void main(String[] args) { ConcreteSubject s = new ConcreteSubject(); s.attach(new ConcreteObserver(s, "X")); s.attach(new ConcreteObserver(s, "Y")); s.attach(new ConcreteObserver(s, "Z")); s.SubjectState(); s.Notify(); } }
11、状态模式
当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类。
状态模式主要解决的是当控制一个对象状态转换的条件表达式过于复杂时的情况,把状态的判断逻辑转移到表示不同状态的一系列类当中,可以把复杂的判断逻辑简化。
1 package design.state; 2 3 /** 4 * Created by adrian.wu on 2019/5/23. 5 */ 6 public class Context { 7 public State state; 8 9 public Context(State state) { 10 this.state = state; 11 } 12 13 public void request() { 14 state.handle(this); 15 } 16 }
1 package design.state; 2 3 4 /** 5 * Created by adrian.wu on 2019/5/23. 6 */ 7 abstract class State { 8 abstract public void handle(Context context); 9 }
1 package design.state; 2 3 4 /** 5 * Created by adrian.wu on 2019/5/23. 6 */ 7 public class ConcreteStateA extends State { 8 @Override 9 public void handle(Context context) { 10 context.state = new ConcreteStateB(); 11 } 12 }
1 package design.state; 2 3 /** 4 * Created by adrian.wu on 2019/5/23. 5 */ 6 public class ConcreteStateB extends State { 7 @Override 8 public void handle(Context context) { 9 context.state = new ConcreteStateA(); 10 } 11 }
1 package design.state; 2 3 /** 4 * Created by adrian.wu on 2019/5/23. 5 */ 6 public class Main { 7 public static void main(String[] args) { 8 Context c = new Context(new ConcreteStateA()); 9 10 c.request(); 11 c.request(); 12 c.request(); 13 c.request(); 14 } 15 }
12、适配器模式
将一个类的接口转换成客户希望的另外一个接口。Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。使用一个已经存在的类,但如果它的接口,也就是它的方法和你的要求不同时,就应该考虑用适配器模式。两个类所做的事情相同或相似,但是具体不同的接口时要使用它。客户代码可以统一调用同一接口,这样可以更简单,更直接,更紧凑。
package design.adapter; /** * Created by adrian.wu on 2019/5/23. */ public class Adaptee { public void SpecificRequest() { } }
package design.adapter; /** * Created by adrian.wu on 2019/5/23. */ public class Adapter extends Target { private Adaptee adaptee = new Adaptee(); public void Request() { adaptee.SpecificRequest(); } }
package design.adapter; /** * Created by adrian.wu on 2019/5/23. */ public class Target { public void request() { } }
package design.adapter; /** * Created by adrian.wu on 2019/5/23. */ public class Main { public static void main(String[] args) { Target target = new Adapter(); target.request(); } }
二、原则
1、单一职责原则
就一个类而言,应该只有一个引起它变化的原因
2、开放封闭原则
软件实体(类、模块、函数等)应该是可以扩展的,但是不可修改的
3、依赖倒转原则
依赖倒转原则其实可以说是面向对象设计的标志,用哪种语言来编写程序不重要,如果编写时考虑的都是如何针对抽象而不是针对编程细节,即程序中的所有依赖关系都是终止于抽象类或者接口,那就是面向对象的设计,反之就是过程化的设计
4、迪米特法则
如果两个类不必彼此直接通信,那么这两个类就不应当发生直接的相互作用。如果其中一个类需要调用另一个类的某一方法的化,可以通过第三者转发这个调用。