1. 策略模式
策略模式定义了算法族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化独立于使用算法的客户
1.1 定义算法族
public interface FlyBehavior {
String fly(); // 飞的行为
}
public interface QuackBehavior {
String quack(); // 叫的行为
}
public class FlyNoWay implements FlyBehavior {
@Override
public String fly() {
return "I can't fly";
}
}
public class FlyRocketPowered implements FlyBehavior {
@Override
public String fly() {
return "I'm flying with a rocket";
}
}
public class MuteQuack implements QuackBehavior {
@Override
public String quack() {
return "Silence";
}
}
public class Quack implements QuackBehavior {
@Override
public String quack() {
return "Quack";
}
}
1.2 客户使用算法
public class ModelDuck extends Duck {
FlyBehavior flyBehavior;
QuackBehavior quackBehavior;
public ModelDuck() {
flyBehavior = new FlyNoWay();
quackBehavior = new Quack();
}
@Override
public String display() {
return "I'm a model duck";
}
}
其中Duck类为:
public abstract class Duck {
FlyBehavior flyBehavior;
QuackBehavior quackBehavior;
public Duck(){
}
public abstract String display();
public String performFly(){
return flyBehavior.fly();
}
public String performQuack(){
return quackBehavior.quack();
}
public String swim(){
return "All ducks float";
}
public void setFlyBehavior(FlyBehavior flyBehavior){
this.flyBehavior = flyBehavior;
}
public void setQuackBehavior(QuackBehavior quackBehavior){
this.quackBehavior = quackBehavior;
}
}
体现设计原则: 发现变化,封装变化 多用组合,少用继承 针对接口编程,而非实现编程
2. 观察者模式
观察者模式,定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新
2.1 定义主题
public interface Subject {
void registerObserver(Observer observer);
void removeObserver(Observer observer);
void notifyObserver();
}
2.2 定义观察者
public interface Observer {
void update(float temperature, float humidity, float pressure);
}
2.3 实现主题
public class WeatherData implements Subject {
private float temperature;
private float humidity;
private float pressure;
private List<Observer> observers;
public WeatherData() {
observers = new ArrayList<>();
}
@Override
public void registerObserver(Observer observer) {
if (null == observer) {
return;
}
if (!observers.contains(observer)) {
observers.add(observer);
}
}
@Override
public void removeObserver(Observer observer) {
if (observers.indexOf(observer) != -1) {
observers.remove(observer);
}
}
@Override
public void notifyObserver() {
observers.forEach(observer -> {
observer.update(temperature, humidity, pressure);
});
}
public void setMeasurements(float temperature,float humidity,float pressure){
this.temperature=temperature;
this.humidity=humidity;
this.pressure=pressure;
measurementsChanged();
}
private void measurementsChanged() {
notifyObserver();
}
}
2.4 实现观察者
public interface DisplayElement {
void display();
}
public class CurrentConditionsDisplay implements Observer, DisplayElement {
private float temperature;
private float humidity;
private Subject weatherData;
public CurrentConditionsDisplay(Subject weatherData) {
this.weatherData = weatherData;
weatherData.registerObserver(this);
}
@Override
public void display() {
System.out.println("Current conditions: " + temperature + "F degree and " + humidity + "% humidity");
}
@Override
public void update(float temperature, float humidity, float pressure) {
this.temperature = temperature;
this.humidity = humidity;
display();
}
}
2.5 JDK自带观察者方式实现
import java.util.Observable;
import java.util.Observer;
public class WeatherData extends Observable {
private float temperature;
private float humidity;
private float pressure;
public void setMeasurements(float temperature, float humidity, float pressure) {
this.temperature = temperature;
this.humidity = humidity;
this.pressure =pressure;
measurementsChanged();
}
private void measurementsChanged() {
setChanged();
notifyObservers();
}
public float getTemperature() {
return temperature;
}
public float getHumidity() {
return humidity;
}
public float getPressure() {
return pressure;
}
}
public class CurrentConditionsDisplay implements Observer, DisplayElement {
private Observable observable;
private float temperature;
private float humidity;
public CurrentConditionsDisplay(Observable observable) {
this.observable = observable;
observable.addObserver(this);
}
@Override
public void update(Observable observable, Object arg) {
if (observable instanceof WeatherData) {
WeatherData weatherData = (WeatherData) observable;
// 观察者主动的拉取想要的消息
this.temperature = weatherData.getTemperature();
this.humidity = weatherData.getHumidity();
display();
}
}
@Override
public void display() {
System.out.println("Current conditions: " + temperature + "F degree and " + humidity + "% humidity");
}
}
体现设计原则:为了交互对象之间的松耦合设计而努力
虽然jdk也自带了Observer与Observable,但不建议使用,其违反了多用组合,少用继承设计规则。 从该气象站实例中,得不到正确的通知结果(JDK自带倒叙输出),并且当某一观察者update异常时,未正确捕获将导致其他通知失败,而自定义可以在notifyObserver()中统一捕获处理
3. 单例模式
单例模式:确保一个类只有一个实例,并提供一个全局访问点
3.1 饿汉式单例
public class HungrySingleton {
private static HungrySingleton instance = new HungrySingleton();
private HungrySingleton() {};
public static HungrySingleton getInstance() {
return instance;
}
}
3.2 懒汉式单例
public class LazySingleton {
private static LazySingleton instance;
private LazySingleton() {};
public static synchronized LazySingleton getInstance() {
if (null == instance) {
instance = new LazySingleton();
}
return instance;
}
}
3.3 双重检查锁实现
public class DoubleCheckedSingleton {
private volatile static DoubleCheckedSingleton instance;
private DoubleCheckedSingleton() {};
public static DoubleCheckedSingleton getInstance() {
if (null == instance) {
synchronized(DoubleCheckedSingleton.class) {
if (null == instance) {
instance = new DoubleCheckedSingleton();
}
}
}
return instance;
}
}
3.4 静态内部类实现
public class Singleton {
private Singleton() {};
public static Singleton getInstance() {
return SingletonHolder.singleton;
}
private static class SingletonHolder {
private static final Singleton singleton = new Singleton();
}
}
3.5 枚举方式实现
public class EnumSingleton {
public enum ResourceInstance {
INSTANCE;
private Resource resource;
ResourceInstance() {
this.resource = new Resource();
}
public Resource getResource() {
return this.resource;
}
}
}
class Resource {}
4. 命令模式
命令模式:将“请求”封装成对象,以便使用不同的请求、队列或者日志来参数化其他对象。命令模式也支持可撤销的操作
SpringMVC中HandlerMapping方法中HandlerExecutionChain getHandler(HttpServletRequest request)便是典型的Command模式的使用
4.1 命令接口定义
public interface Command {
void execute();
}
4.2 遥控器类组合命令
public class SimpleRemoteControl {
private Command slot;
public SimpleRemoteControl() {};
public void setCommand(Command command) {
slot = command;
}
public void buttonWasPressed() {
slot.execute();
}
}
4.3 开灯命令
public class LightOnCommand implements Command {
private Light light;
public LightOnCommand() {};
public LightOnCommand(Light light) {
this.light = light;
}
@Override
public void execute() {
light.on();
}
}
其中Light.java
为:
public class Light {
private String roomName;
public Light() {};
public Light(String roomName) {
this.roomName = roomName;
}
public void on() {
System.out.println(roomName + "light is on");
}
public void off() {
System.out.println(roomName + "light is off");
}
}
4.4 测试
public class ComplexCommandTest {
@Test
public void testParameterCommand() {
Light light = new Light("Living Room");
Command lightOnCommand = new LightOnCommand(light);
SimpleRemoteControl control = new SimpleRemoteControl();
control.setCommand(lightOnCommand);
control.buttonWasPressed();
}
}
4.5 输出
Living Roomlight is on
5. 适配器模式
适配器模式:将一个类的接口,转换为客户期望的另一个类的接口。适配器让原本接口不兼容的类可以合作无间。
5.1 鸭子、火鸡接口
public interface Duck {
void quack();
void fly();
}
public interface Turkey {
void gobble();
void fly();
}
5.2 火鸡实现器
public class WildTurkey implements Turkey {
@Override
public void gobble() {
System.out.println("Gobble gobble");
}
@Override
public void fly() {
System.out.println("I am flying a short distance");
}
}
5.3 火鸡适配器
public class TurkeyAdapter implements Duck {
private Turkey turkey;
public TurkeyAdapter(Turkey turkey) {
this.turkey = turkey;
}
@Override
public void quack() {
turkey.gobble();
}
@Override
public void fly() {
for (int i = 0; i < 5; i++) {
turkey.fly();
}
}
}
5.4 测试
public class AdpterTest {
@Test
public void testDuckAdapter() {
Turkey wildTurkey = new WildTurkey();
Duck turkeyAdapter = new TurkeyAdapter(wildTurkey);
turkeyAdapter.quack();
turkeyAdapter.fly();
}
}
5.5 输出
Gobble gobble
I am flying a short distance
I am flying a short distance
I am flying a short distance
I am flying a short distance
I am flying a short distance
再如旧世界的Enumeration与新世界的Iterator进行适配
6. 外观模式
外观模式:提供了一个统一的接口,用来访问子系统的一群接口。外观模式定义了一个高层接口,让子系统更容易使用。
public class CarFacade {
Engine engine;
public CarFacade() {}
public void start(Key key) {
Doors doors = new Doors();
boolean authorized = key.turns();
if (authorized) {
engine.start();
updateDashboardDispaly();
doors.lock();
}
}
}
体现设计原则:最少知识原则-只和你的密友谈话
7. 装饰者模式
装饰者模式动态的将责任附加到对象上,若要扩展功能,装饰者提供了比继承更具有弹性的替代方案
7.1 定义共同的超类
// 饮料类
public abstract class Beverage {
protected String description = "Unknown Beverage";
public abstract double cost();
public String getDescription() {
return description;
}
}
7.2 定义装饰者基类
// 调料装饰者
public abstract class CondimentDecorator extends Beverage {
public abstract String getDescription();
}
7.3 实现被装饰者具体类
// 浓咖啡
public class DarkRoast extends Beverage {
public DarkRoast() {
description = "Dark Roast Coffee";
}
@Override
public double cost() {
return .99;
}
}
7.4 实现装饰者具体类
// 摩卡调料
public class Mocha extends CondimentDecorator {
private Beverage beverage;
public Mocha(Beverage beverage) {
this.beverage = beverage;
}
@Override
public double cost() {
return beverage.cost() + .20;
}
@Override
public String getDescription() {
return beverage.getDescription() + ",Mocha";
}
}
体现设计原则: 类应该对扩展开放,对修改关闭
备注:装饰者和被装饰者必须是一样的类型,也就是有共同的超类,这是相当关键的地方。在这里,我们利用继承达到“类型匹配”,而不是利用继承获得“行为”
8. 工厂模式与抽象工厂
工厂方法模式:定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个。工厂方法让类把实例化推迟到子类。
抽象工厂模式:提供了一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类。
8.1 工厂方法
public abstract class PizzaStore {
public Pizza orderPizza(String type) {
Pizza pizza = createPizza(type); //开分店的奥,每个分店需要不同的口味的幺
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
return pizza;
}
protected abstract Pizza createPizza(String type);
}
public class NYPizzaStore extends PizzaStore {
@Override
protected Pizza createPizza(String item) {
if (item.equals("cheese")) {
return new NYStyleCheesePizza();
}
if (item.equals("veggie")) {
return new NYStyleVeggiePizza();
}
return null;
}
}
8.2 抽象工厂
public interface PizzaIngredientFactory {
Cheese createCheese();
Clam createClam();
}
public class NYPizzaIngredientFactory implements PizzaIngredientFactory {
@Override
public Cheese createCheese() {
return new ReggianoCheese();
}
@Override
public Clam createClam() {
return new FreshClam();
}
}
public class CheesePizza extends Pizza {
private PizzaIngredientFactory ingredientFactory;
public CheesePizza(PizzaIngredientFactory ingredientFactory) {
this.ingredientFactory = ingredientFactory;
}
@Override
public void prepare() {
System.out.println("Preparing " + name);
cheese = ingredientFactory.createCheese();
}
}
public class NYPizzaStore extends PizzaStore {
@Override
public Pizza createPizza(String item) {
Pizza pizza = null;
PizzaIngredientFactory ingredientFactory = new NYPizzaIngredientFactory();
if (item.equals("cheese")) {
pizza = new CheesePizza(ingredientFactory);
pizza.setName("New York Style Cheese Pizza");
} else if (item.equals("clam")) {
pizza = new ClamPizza(ingredientFactory);
pizza.setName("New York Style Clam Pizza");
}
return pizza;
}
}
8.3 简单工厂
public class SimplePizzaFactory {
public static Pizza createPizza(String type) {
Pizza pizza = null;
if (type.equals("cheese")) {
pizza = new CheesePizza();
} else if (type.equals("veggie")) {
pizza = new VeggiePizza();
}
return pizza;
}
}
抽象工厂与工厂方法区别:
抽象工厂的方法经常以工厂方法的方式实现。抽象工厂的任务是负责创建一组产品的接口,这个接口中的每个方法负责创建一个具体的产品,同时我们利用实现抽象工厂的子类来实现这些具体的做法,所以,在抽象工厂中利用工厂方法实现生产方法是相当自然的事情;
工厂方法创建对象通过继承,抽象工厂通过组合;
扩展新产品抽象工厂接口要改变,工厂方法不需要改变;
抽象工厂用于创建产品家族,让创建的相关产品集合起来,工厂方法使客户代码从实例化的具体类解耦,使用简单
体现设计原则: 依赖倒置原则(依赖于抽象,而非具体类)
备注: 简单工厂不是一种设计模式,反而更像一种编程习惯
9. 桥接模式
桥接是用于把抽象化与实现化解耦,使得二者可以独立变化。属于结构型模式,它通过提供抽象化和实现化之间的桥接结构,来实现二者的解耦。
主要解决:在有多种可能会变化的情况下,用继承会造成类爆炸问题,扩展起来不灵活。
优点:
- 抽象和实现的分离
- 优秀的扩展能力
- 实现细节对客户透明
缺点:桥接模式的引入会增加系统的理解与设计难度,由于聚合关联关系建立在抽象层,要求开发者针对抽象进行设计与编程。
public class BridgePatternTest {
@Test
public void testBridgePattern(){
Shape redCircle=new Circle(100,10,10,new RedCircle());
Shape greenCircle=new Circle(50,10,10,new GreenCircle());
redCircle.draw();
greenCircle.draw();
}
}
public interface DrawAPI {
void drawCircle(int radius,int x,int y);
}
public class GreenCircle implements DrawAPI{
@Override
public void drawCircle(int radius, int x, int y) {
System.out.println("[Draw GreenCircle -> radius:"+radius+"x:"+x+"y:"+y+"]");
}
}
public class RedCircle implements DrawAPI {
@Override
public void drawCircle(int radius, int x, int y) {
System.out.println("[Draw RedCircle -> radius:"+radius+"x:"+x+"y:"+y+"]");
}
}
public abstract class Shape {
protected DrawAPI drawAPI;
protected Shape(DrawAPI drawAPI){
this.drawAPI=drawAPI;
}
public abstract void draw();
}
public class Circle extends Shape{
private int radius;
private int x;
private int y;
public Circle(int radius,int x,int y,DrawAPI drawAPI) {
super(drawAPI);
this.radius=radius;
this.x=x;
this.y=y;
}
public void draw(){
drawAPI.drawCircle(radius, x, y);
}
}