选取了面试中常见的设计模式汇总以及demo示例,本文中介绍的设计模式,均在Spring中使用过。
一、工厂模式
创建对象时不暴露创建逻辑,而是通过使用一个共同的接口来创建新的对象。
(一)简单工厂模式
没有遵循开闭原则。能够外界给定的信息, 决定创建哪个具体类的对象。
// 冰淇淋接口
public interface IceCream {
public void taste();
}
// 三种口味的冰淇淋类
public class AppleIceCream implements IceCream {
public void taste(){
System.out.println("这是苹果口味的冰激凌");
}
}
public class BananaIceCream implements IceCream {
public void taste() {
System.out.println("这是香蕉口味的冰激凌");
}
}
public class OrangeIceCream implements IceCream{
public void taste(){
System.out.println("这是橘子口味的冰激凌");
}
}
// 工厂类,制作不同口味的冰淇淋
public class IceCreamFactory {
public static IceCream creamIceCream(String taste){
IceCream iceCream = null;
// 这里我们通过switch来判断,具体制作哪一种口味的冰激凌
switch(taste){
case "Apple":
iceCream = new AppleIceCream();
break;
case "Orange":
iceCream = new OrangeIceCream();
break;
case "Banana":
iceCream = new BananaIceCream();
break;
default:
break;
}
return iceCream;
}
}
// 客户端代码
// 通过统一的工厂,传入不同参数调用生产冰激凌的方法去生产不同口味的冰激凌
public class Client {
public static void main(String[] args) {
IceCream appleIceCream = IceCreamFactory.creamIceCream("Apple");
appleIceCream.taste();
IceCream bananaIceCream = IceCreamFactory.creamIceCream("Banana");
bananaIceCream.taste();
IceCream orangeIceCream = IceCreamFactory.creamIceCream("Orange");
orangeIceCream.taste();
}
}
(二)工厂模式
遵循了开闭原则,对简单工厂方法模式的一个抽象,抽离出了一个Factory类(或者接口),这个接口不负责具体产品的生产,而只是指定一些规范,具体的生产工作由其子类去完成。
// 冰淇淋接口
public interface IceCream {
public void taste();
}
// 工厂接口
public interface IceCreamFactory {
public IceCream createIceCream();
}
//三种冰淇淋工厂
public class AppleIceCreamFactory implements IceCreamFactory {
public IceCream createIceCream() {
return new AppleIceCream();
}
}
public class BananaIceCreamFactory implements IceCreamFactory {
public IceCream createIceCream() {
return new BananaIceCream();
}
}
public class OrangeIceCreamFactory implements IceCreamFactory{
public IceCream createIceCream() {
return new OrangeIceCream();
}
}
// 客户端代码
public class Client {
/**
* @param args
*/
public static void main(String[] args) {
//生产苹果味冰激凌
IceCreamFactory appleFactory = new AppleIceCreamFactory();
IceCream appleIceCream = appleFactory.createIceCream();
appleIceCream.taste();
//生产香蕉口味冰激凌
IceCreamFactory bananaFactory = new BananaIceCreamFactory();
IceCream bananaIceCream = bananaFactory.createIceCream();
bananaIceCream.taste();
//生产橘子口味冰激凌
IceCream orangeIceCream = new OrangeIceCreamFactory().createIceCream();
orangeIceCream.taste();
}
}
(三)抽象工厂模式
将一个系列的产品族统一到一起创建,比如现在要生产不同大小的冰淇淋。工厂提供多种方法,去生产“系列”产品。
// 大冰淇淋,小冰淇淋的接口
public interface BigIceCream {
public void taste();
}
public interface SmallIceCream {
public void taste();
}
// 定义不同口味的大小冰淇淋,一共6种,这里简写成2种
public class BigAppleIceCream implements BigIceCream {
public void taste() {
System.out.println("这是苹果味冰激凌(大份)");
}
}
public class SmallAppleIceCream implements SmallIceCream {
public void taste() {
System.out.println("这是苹果味冰激凌(小份)");
}
}
// 定义工厂,可以生成大份和小份的
public interface IceCreamFactory {
public BigIceCream createBigIceCream();
public SmallIceCream createSmallIceCream();
}
// 三个工厂类
public class AppleIceCreamFactory implements IceCreamFactory {
public BigIceCream createBigIceCream() {
return new BigAppleIceCream();
}
public SmallIceCream createSmallIceCream() {
return new SmallAppleIceCream();
}
}
public class BananaIceCreamFactory implements IceCreamFactory {
public BigIceCream createBigIceCream() {
return new BigBananaIceCream();
}
public SmallIceCream createSmallIceCream() {
return new SmallBananaIceCream();
}
}
public class OrangeIceCreamFactory implements IceCreamFactory {
public BigIceCream createBigIceCream() {
return new BigOrangeIceCream();
}
public SmallIceCream createSmallIceCream() {
return new SmallOrangeIceCream();
}
}
// 客户端代码
public class Client {
public static void main(String[] args) {
//生产苹果味冰激凌
IceCreamFactory appleIceCreamFactory = new AppleIceCreamFactory();
BigIceCream appleBigIceCream = appleIceCreamFactory.createBigIceCream();
SmallIceCream appleSmallIceCream = appleIceCreamFactory.createSmallIceCream();
appleBigIceCream.taste();
appleSmallIceCream.taste();
//生产香蕉味冰激凌
IceCreamFactory bananaIceCreamFactory = new BananaIceCreamFactory();
BigIceCream bananaBigIceCream = bananaIceCreamFactory.createBigIceCream();
SmallIceCream bananaSmallIceCream = bananaIceCreamFactory.createSmallIceCream();
bananaBigIceCream.taste();
bananaSmallIceCream.taste();
//生产橘子味冰激凌
IceCreamFactory orangeIceCreamFactory = new OrangeIceCreamFactory();
BigIceCream orangeBigIceCream = orangeIceCreamFactory.createBigIceCream();
SmallIceCream orangeSmallIceCream = orangeIceCreamFactory.createSmallIceCream();
orangeBigIceCream.taste();
orangeSmallIceCream.taste();
}
}
二、策略模式
主要针对if/ else/ switch。比如说对象的某个行为,在不同场景中有不同的实现方式,这样就可以将这些实现方式定义成一组策略,每个实现类对应一个策略,在不同的场景就使用不同的实现类,并且可以自由切换策略。
// 接口
public interface Strategy {
//实现2个数可以计算
public int calc(int num1,int num2);
}
// 定义加减法策略
public class AddStrategy implements Strategy {
@Override
public int calc(int num1, int num2) {
return num1+num2;
}
}
public class SubStrategy implements Strategy {
@Override
public int calc(int num1, int num2) {
return num1-num2;
}
}
// 环境角色
public class Environment {
//持有对策略类的引用
private Strategy strategy;
//有参的构造方法,通过构造器来注入
public Environment(Strategy strategy) {
this.strategy = strategy;
}
public int calulate(int a,int b){
return strategy.calc(a,b);
}
}
// 主类
public class TestStrategy {
public static void main(String[] args) {
Environment e = new Environment(new AddStrategy());//传入具体的策略类
int result = e.calulate(5, 7);
System.out.println("a+b="+result);
Environment r = new Environment(new SubStrategy());
System.out.println("a-b="+r.calulate(9,3));
}
}
三、观察者模式
当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新。
(一) 主题
// 主题接口
public interface Subject {
public void registerObserver(Observer o);
public void removeObserver(Observer o);
public void notifyObservers();
}
// 主题类
public class WeatherData implements Subject {
// 以List记录观察者
private List<Observer> observers;
private float temperature;
public WeatherData() {
observers = new ArrayList<Observer>();
}
// 注册观察者时,添加到list后即可
public void registerObserver(Observer o) {
observers.add(o);
}
// 当某个观察者取消订阅后,将其从list中删除即可
public void removeObserver(Observer o) {
observers.remove(o);
}
// 当数据变化时,遍历list,调用所有观察者的update接口进行数据更新
public void notifyObservers() {
for (Observer observer : observers) {
observer.update(temperature);
}
}
}
(二) 观察者
// 观察者接口
public interface Observer {
public void update(int value);
}
//观察者类
public class StatisticsDisplay implements Observer, DisplayElement {
private WeatherData weatherData;
public StatisticsDisplay(WeatherData weatherData) {
this.weatherData = weatherData;
weatherData.registerObserver(this);
}
public void update(float temp) {
System.out.println("temp" + "-" + temp);
}
}
四、装饰者模式
不修改现有代码的基础上,进行功能扩展。 Java的I/O就是典型的装饰者模式。
// 总基类
public abstract class Beverage {
String description = "Unknown Beverage";
public String getDescription() {
return description;
}
public abstract double cost();
}
// 装饰者基类
public abstract class CondimentDecorator extends Beverage {
Beverage beverage;
// 装饰者必须全部重新实现 getDescription()
public abstract String getDescription();
}
// 咖啡底料举例
public class DarkRoast extends Beverage {
public DarkRoast() {
description = "Dark Roast Coffee";
}
public double cost() {
return .99;
}
}
// 调料举例
public class Milk extends CondimentDecorator {
// 咖啡底以构造器入参形式注入
public Milk(Beverage beverage) {
this.beverage = beverage;
}
public String getDescription() {
return beverage.getDescription() + ", Milk";
}
public double cost() {
return .10 + beverage.cost();
}
}
// 下订单
public static void main(String args[]) {
Beverage beverage = new Espresso();
System.out.println(beverage.getDescription() + " $" + beverage.cost());
Beverage beverage2 = new DarkRoast();
beverage2 = new Mocha(beverage2);
beverage2 = new Mocha(beverage2);
beverage2 = new Whip(beverage2);
System.out.println(beverage2.getDescription() + " $" + beverage2.cost());
Beverage beverage3 = new HouseBlend();
beverage3 = new Soy(beverage3);
beverage3 = new Mocha(beverage3);
beverage3 = new Whip(beverage3);
System.out.println(beverage3.getDescription() + " $" + beverage3.cost());
}
五、适配器模式
适配器模式就是将一个类的接口转换成客户希望的另外一个接口,Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。
// 已存在的、具有特殊功能、但不符合我们既有的标准接口的类
class Adaptee {
public void specificRequest() {
System.out.println("被适配类具有 特殊功能...");
}
}
// 目标接口,或称为标准接口
interface Target {
public void request();
}
// 具体目标类,只提供普通功能
class ConcreteTarget implements Target {
public void request() {
System.out.println("普通类 具有 普通功能...");
}
}
// 适配器类,继承了被适配类,同时实现标准接口
class Adapter extends Adaptee implements Target{
public void request() {
super.specificRequest();
}
}
// 测试类public class Client {
public static void main(String[] args) {
// 使用普通功能类
Target concreteTarget = new ConcreteTarget();
concreteTarget.request();
// 使用特殊功能类,即适配类
Target adapter = new Adapter();
adapter.request();
}
}
六、单例模式
保证某类在系统中只有一个实例。