JAVA设计模式

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. 桥接模式

桥接是用于把抽象化与实现化解耦,使得二者可以独立变化。属于结构型模式,它通过提供抽象化和实现化之间的桥接结构,来实现二者的解耦。
主要解决:在有多种可能会变化的情况下,用继承会造成类爆炸问题,扩展起来不灵活。
优点:

  1. 抽象和实现的分离
  2. 优秀的扩展能力
  3. 实现细节对客户透明

缺点:桥接模式的引入会增加系统的理解与设计难度,由于聚合关联关系建立在抽象层,要求开发者针对抽象进行设计与编程。

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);
	}
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

算法小生Đ

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值