设计原则
- 封装变化。
- 针对接口编程,不针对实现变成。
- 多用组合,少用继承。
- 使交互对象之间松耦合。
- 对扩展开放,对修改关闭。
- 依赖抽象,不依赖具体。
设计模式
策略模式
- 定义:
封装算法族,让它们可以互相替换,或者组合到一起,让算法的变化独立于算法的客户。
- 应用场景:
假设有一个父类派生出10个子类,而当其中有5个子类需要添加一个算法A时,把这个功能添加到父类显然不合适,因为另外5个并不需要算法A。逐个给这5各类添加该算法则造成代码冗余严重。那给这5个类与父类之间再添加一个父类怎么样?看起来也可以,但如果再给这5各类其中3个添加算法B呢?这样的扩展对整体结构来说很不灵活。这个时候策略模式派上用场了。
- 实现方式:
我们可以把算法A、算法B等封装起来,并且继承同一个interface,在父类中声明该interface的引用,子类们可以根据自己的需求对interface实例化。通过这样的算法族组合起来,使结构更具有弹性。
观察者模式
- 定义:
在对象之间定义一对多依赖,使改变一个对象的状态,其他对象都会收到通知并自动更新。
- 应用场景:
普遍应用于事件传递,如广播和UI事件监听等。被观察者无需关心谁加入观察,完全由观察者决定是否加入观察的行列。
- 实现方式:
被观察者定义了interface,并在自身状态发生改变时调用interface通知观察者。而对象要成为观察者只需要实例化interface,并把它交给被观察者。
装饰者模式
- 定义:
动态的将责任附加到对象上。这是一种有别于继承的扩展功能的方式。
- 应用场景:
当父类A派生的子类种类非常繁多,而不同子类之间又存在各种相同特性的混合关系,如BC、CD、BD等。可以把这些特性独立封装起来,如B、C、D类,使子类的数量压缩到最少,根据不同的需求把封装的特性附加到子类上。
- 实现方式:
class A {
public void do() {
return 0.1;
};
}
class B extends A {
A a;
public B (A a) {
this.a = a;
}
public void do() {
return 0.1 + a.do();
};
}
class C extends A {
A a;
public C (A a) {
this.a = a;
}
public void do() {
return 0.2 + a.do();
};
}
public static int main(String args[]) {
A a = new A();
a = new B(a); //用B装饰a
a = new C(a); //用C装饰a
}
工厂模式
- 定义:
定义了一个创建对象的接口,由子类决定要实例化的类是哪一个,让类的实例化推迟到子类。通常包括工厂方法和抽象工厂方法,前者主要以继承方式让子类决定产品类型(也包括简单工厂,即不需要派生子类,直接提供产品),后者则通过接口方式组合各种产品对象。
- 应用场景:
当只有在运行时才知道需要实例化的是哪个类,我们就可以把这种类型判断和对象创建采用工厂方法封装起来。工厂方法用于创建具体的产品,抽象工厂用于定义整个产品家族的创建接口。而后者派生出的具体工厂则是工厂方法。
- 实现方式:
简单工厂方法
public static class Factory {
public static A createObj(int type) {
if (type == 0) return new B(); //B extends A
else if (type == 1) return new C(); //C extends A
}
}
工厂方法
public abstract class Factory {
public A orderObj(int type) {
A a = createObj(type);
a.init();
a.doSomething();
return a;
}//由派生的具体工厂决定创建类型
abstract A createObj(int type);
//其他方法
}
抽象工厂方法
public interface Factory {
public A createA();
public B createB();
}
public class MyFactory implements Factory {
public A createA() { return new A(); }
public B createB() { return new B(); }
}
单件模式
- 定义:
- 应用场景:
- 实现方式:
public class Singleton {
private static Singleton instance;
//构造方法设为私有,不对外开放
private Singleton() {
}
//全局访问点
public static Singleton getInstance(){
if (instance == null) {
//延迟实例化对象(如果存在多线程调用则不建议这样做,以免因不同步而创建了多个对象。应改成在定义时直接实例化对象)
instance = new Singleton();
}
return instance;
}
}
命令模式
- 定义:
- 应用场景:
- 实现方式:
//动作执行者
public class Actor {
public void do() {
//do something
}
public void reset() {
// reset state
}
}
//封装命令
public interface Command {
public void execute();
public void undo();
}
public class ActorCommand implements Command {
Actor a;
public ActorCommand(Actor a) {
this.a = a;
}
public void execute() {
a.do();
}
public void undo() {
a.reset();
}
}
//动作请求者
public class RemoteControl {
Command cmd;
public void setCommand(Command cmd) {
this.cmd = cmd;
}
public void doCommand() {
cmd.execute();
}
public void cancel() {
cmd.undo();
}
}
public static void main(String[] args) {
RemoteControl remote = new RemoteControl();
Actor a = new Actor();
ActorCommand cmd = new ActorCommand(a);
remote.setCommand(cmd);//可设置不同请求命令
remote.doCommand();
remote.cancel();
}
适配器模式
- 定义:
- 应用场景:
- 实现方式:
public interface A {
public void walk();
public void run();
}
public interface B {
public void walk();
public void fly();
}
//让B接口适配A接口
public class BAdapter implements A {
B b;
public BAdapter(B b) {
this.b = b;
}
public void walk() {
b.walk();
}
public void run() {
b.fly();
}
}
- 外观模式
- 对比
模式 | 意图 |
装饰者 | 不改变接口,但加入行为责任 |
适配器 | 将一个接口转成另一个接口 |
外观 | 让接口更简单 |
待续……