设计模式简单描述,主要用于工作中模式选择和应用参考,文章中的定义和规则均参阅《Head First 设计模式》一书。
希望通过了解学习,达到“在这里采用装饰着模式相当自然”这样一个比较顺其自然的设计方案的设计,同时也本着模式是工具而不是规则,以期达到目标设计要求。
设计模式其实无处不在,特别是在JDK的jar包源码中大量存在,我们只是对其概念不太了解而导致在别人问起时无法回答。总之,设计模式就是解决问题时使用的策略,设计模式间不是单纯使用,好的方案往往针对不同部分使用不同的设计模式,总体之间达到有机的组合嵌套来实现。
一、设计原则:
找出应用程序中可能需要变化之处,把他们独立出来,不要和不需要变化的代码混合在一起;
剥离出业务中经常会变化的部分和不变的部分,将会变化的部分抽出封装,以便以后改动扩充,而不影响不变的部分。
针对接口编程,不针对实现编程;
利用多态,针对超类编程,使程序在运行使根据实际状况执行真正的行为(自类具体实现Animal dog = new Dog())
多用组合少用继承;
通过组合是系统具有较大弹性,如将不同的算法簇封装,只要在组合的行为对象符合正确的接口标准即可。
为了交互对象间的松耦合设计而努力;
可建立有弹性的OO系统,达到不同对象间的松耦合,即可拆分替换。
类应该对扩展开放,对修改关闭;
在不修改现有代码情况下,搭配出新的功能,防止引入新的bug。即对于扩展变化的部分使用。
要依赖抽象,不要依赖具体;
不要让高层组件(低层组件定义了具体的行为)依赖低层组件,而且两者都需要依赖抽象。减少代码中对具体类的依赖。
最少只是原则,只和你的密友谈话;
明确系统间涉及的类,不要让太多的类耦合在一起,防止因系统修改引起新BUG,是系统太脆弱。
别调用我们,我们会调用你;
防止“依赖腐败”发生,降低系统的复杂性,即高层组件可以决定何时调用低层组件,而低层组件不可直接调用高层组件。
一个类应该只有一个引起变化的原因。
尽量让类保持单一职责,避免其他业务修改产生新的错误。
二、常见设计模式及应用场景
单例模式:
确保一个类只有一个实例,并提供一个全局访问点。多用于连接池等单个实例对象的创建。
public class Singleton {
private static Singleton uniqueInstance;
// other useful instance variables here
private Singleton() {}
public static synchronized Singleton getInstance() {
if (uniqueInstance == null) {
uniqueInstance = new Singleton();
}
return uniqueInstance;
}
// other useful methods here
public String getDescription() {
return "I'm a thread safe Singleton!";
}
}
适配器:
将一个类的接口转换为客户希望的另外一个借口,让原本接口不兼容的类可以合作无间。分为类适配器和对象适配器,类适配器通过继承,而对象适配通过组合的方式适配。
将枚举适配到迭代器:
public class EnumerationIterator implements Iterator<Object> {
Enumeration<?> enumeration;
public EnumerationIterator(Enumeration<?> enumeration) {
this.enumeration = enumeration;
}
public boolean hasNext() {
return enumeration.hasMoreElements();
}
public Object next() {
return enumeration.nextElement();
}
public void remove() {
throw new UnsupportedOperationException();
}
public static void main (String args[]) {
Vector<String> v = new Vector<String>(Arrays.asList(args));
Iterator<?> iterator = new EnumerationIterator(v.elements());
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
}
}
装饰者模式:
动态的将责任添加到对象上。装饰者可以在所委托被装饰者的行为前或后,加上自己的行为,达到特定目的。例如计算不同饮料的价格。自类继承抽象父类,实现具体的业务细节。
public abstract class Beverage {
public enum Size { TALL, GRANDE, VENTI };
Size size = Size.TALL;
String description = "Unknown Beverage";
public String getDescription() {
return description;
}
public void setSize(Size size) {
this.size = size;
}
public Size getSize() {
return this.size;
}
public abstract double cost();
}
public class Decaf extends Beverage {
public Decaf() {
description = "Decaf Coffee";
}
public double cost() {
return 1.05;
}
}
外观模式
实现业务流程需要调用一系列的具有特定次序的接口,通过提供统一的接口,来实现子系统一群接口的访问。外观定义了一个高层接口,让子系统更加方便使用。
举例:
遥控器等按键,通过将单一的不同功能在一个类初始化时加载调用,然后组合实现业务功能,最后化为一个接口。
外观将客户从将客户从复杂系统中解耦,而适配器是将一个对象包装起来,以改变接口,装饰者是将一个对象包装起来以增加新的行为和责任,而外观是将一群对象包括起来,实现简化。