设计模式
文章目录
- 设计模式
- 设计模式总览
- 单例模式
- 类图
- 定义
- 特点
- 单例模式的实现方式
- 工厂模式
- 类图
- 定义
- 特点
- 实现方式
- 抽象工厂模式
- 类图
- 定义
- 特点
- 实现方式
- 观察者模式
- 类图
- 简单理解
- 使用场景
- 实例代码
- 策略模式
- 类图
- 简单理解
- 使用场景
- 实例代码
- 模板方法模式
- 类图
- 简单理解
- 实例代码
- 原型模式
- 类图
- 简单理解
- **关键代码:**
- 实例代码
- 代理模式
- 静态代理
- 类图
- JDK 动态代理
- 类图
- Cglib代理
- 类图
- 适配器模式
- 类图
- 角色
- Target(目标抽象类)
- AdapterClass(适配器类)
- MatchesClass(适配者类)
- 类适配器模式
- 对象适配器模式
- 主要优点
- 实例
- 建造者模式
- 类图
- 定义
- 特点
- 实例代码
- 桥接模式
- 简单理解
- 类图
- 实例代码
- 过滤器模式
- 类图
- 定义
- 实例
- 组合模式
- 类图
- 定义
- 实例代码
- 装饰器模式
- 类图
- 定义
- 特点
- 实现代码
- 外观模式
- 类图
- 定义
- 特点
- 实现代码
- 享元模式
- 类图
- 定义
- 实现代码
- 责任链模式
- 类图
- 定义
- 特点
- 实现代码
- 命令模式
- 类图
- 定义
- 实现代码
- 解释器模式
- 类图
- 定义
- 特点
- 实现代码
- 迭代器模式
- 类图
- 定义
- 实现代码
- 中介者模式
- 类图
- 定义
- 实现代码
- 备忘录模式
- 类图
- 定义
- 实现代码
- 状态模式
- 类图
- 定义
- 实现代码
- 访问者模式
- 类图
- 定义
- 实现代码
设计模式总览
单例模式
类图
定义
一个类只有一个实例,该类能自己创建该类的一个实例。
特点
- 单例类只有一个实例对象。
- 单例对象必须由该类自己创建。
- 单例类对外提供一个访问该单例的全局访问点。
单例模式的实现方式
- 懒汉模式:加载类的时候没有生成单例模式,调用生成实例对象的方法的时候创建单例。
public class LazySingleton {//保证lazySingleton在线程中同步private static volatile LazySingleton lazySingleton = null;//保证类不在别的地方被实例化private LazySingleton() {}//synchronize保证线程安全public static synchronized LazySingleton getInstance() {if (lazySingleton == null) {lazySingleton = new LazySingleton();}return lazySingleton;}
}
- 饿汉模式:类一旦加载就创建一个单例。创建的这个对象之后就不会再改变,所以是线程安全的。
public class HungrySingleton {private static final HungrySingleton hungrySingleton = new HungrySingleton();private HungrySingleton() {}public static HungrySingleton getInstance() {return hungrySingleton;}
}
工厂模式
类图
定义
对象的实际创建工作推迟到子类当中。
特点
- 用户主需要知道工厂的名称,则可得到对应的产品,无需知道产品的创建过程。
- 系统增加产品时只需添加具体产品类和对应的具体工厂类,无需对原工厂进行修改。
- 每增加一个产品就得增加一个具体产品类和和一个对应的具体工厂类。
实现方式
- 提供产品的接口
public interface Product {public void show();
}
- 具体产品1实现产品接口
public class ProductImpl1 implements Product {@Overridepublic void show() {System.out.println("我生产了1");}
}
- 具体产品2实现产品接口
public class ProductImpl2 implements Product {@Overridepublic void show() {System.out.println("我生产了2");}
}
- 抽象工厂,提供生成产品的方法
public interface AbstractFactory {public Product getInstance();
}
- 实现产品生成
public class FactoryTest {public static void main(String[] args) {CreateFactory1 createFactory1 = new CreateFactory1();createFactory1.getInstance();CreateFactory2 createFactory2 = new CreateFactory2();createFactory2.getInstance();}static class CreateFactory1 implements AbstractFactory {@Overridepublic Product getInstance() {System.out.println("工厂1生产产品");ProductImpl1 productImpl1 = new ProductImpl1();productImpl1.show();return productImpl1;}}static class CreateFactory2 implements AbstractFactory {@Overridepublic Product getInstance() {System.out.println("工厂2生产产品");ProductImpl2 productImpl2 = new ProductImpl2();productImpl2.show();return productImpl2;}}
}
抽象工厂模式
类图
定义
是一种为访问类提供一个创建一组相关或相互依赖对象的接口,且访问类无须指定所要产品的具体类就能得到同族的不同等级的产品的模式结构。抽象工厂模式是工厂方法模式的升级版本,工厂方法模式只生产一个等级的产品,而抽象工厂模式可生产多个等级的产品。
特点
- 可以在类的内部对产品族中相关联的多等级产品共同管理,而不必专门引入多个新的类来进行管理。
- 当增加一个新的产品族时不需要修改原代码。
实现方式
- 形状类以及具体的图形
public interface Shape {/*** 画形状*/void draw();
}
public class Rectangle implements Shape {private static final Logger logger = LoggerFactory.getLogger(Rectangle.class);public static final String SHAPE = "rectangle";@Overridepublic void draw() {logger.info("我是长方形");}
}
public class Square implements Shape {private static final Logger logger = LoggerFactory.getLogger(Square.class);public static final String SHAPE = "square";@Overridepublic void draw() {logger.info("我是矩形");}
}
- 颜色以及具体的颜色
public interface Color {/*** 填充颜色*/void fill();
}
public class Green implements Color {private static final Logger logger = LoggerFactory.getLogger(Green.class);public static final String COLOR = "green";@Overridepublic void fill() {logger.info("填充绿色");}
}
public class Red implements Color {private static final Logger logger = LoggerFactory.getLogger(Red.class);public static final String COLOR = "red";@Overridepublic void fill() {logger.info("填充红色");}
}
- 得到颜色和形状的抽象工厂
public abstract class AbstractFactory {public abstract Color getColor(String color);public abstract Shape getShape(String shape);}
- 得到具体颜色、具体形状的方法
public class ColorFactory extends AbstractFactory {public static final String TYPE = "color";@Overridepublic Color getColor(String color) {if (color == null) {return null;} else if (Red.COLOR.equalsIgnoreCase(color)) {return new Red();} else if (Green.COLOR.equalsIgnoreCase(color)) {return new Green();}return null;}@Overridepublic Shape getShape(String shape) {return null;}
}
public class ShapeFactory extends AbstractFactory {public static final String TYPE = "shape";@Overridepublic Color getColor(String color) {return null;}@Overridepublic Shape getShape(String shape) {if (shape == null) {return null;}if (Rectangle.SHAPE.equalsIgnoreCase(shape)) {return new Rectangle();} else if (Square.SHAPE.equalsIgnoreCase(shape)) {return new Square();}return null;}
}
- 得到颜色或者形状的工厂
public class FactoryProducer {/*** 获取工厂实例** @param type 工厂类型* @return AbstractFactory*/public static AbstractFactory getFactoryInstance(String type) {if (ShapeFactory.TYPE.equalsIgnoreCase(type)) {return new ShapeFactory();} else if (ColorFactory.TYPE.equalsIgnoreCase(type)) {return new ColorFactory();}return null;}
}
- 根据传入的东西判断得到具体的形状或者具体的颜色
public static void main(String[] args) {//获取形状工厂AbstractFactory shape = FactoryProducer.getFactoryInstance("shape");Shape rectangle = Objects.requireNonNull(shape).getShape("rectangle");rectangle.draw();Shape square = shape.getShape("square");square.draw();// 获取颜色工厂AbstractFactory colorFactory = FactoryProducer.getFactoryInstance("COLOR");Color color1 = Objects.requireNonNull(colorFactory).getColor("RED");color1.fill();
}
观察者模式
类图
简单理解
- 观察者模式是一种行为性模式,定义对象之间的一对多的依赖关系,当一个对象状态改变时候依赖于它的对象的状态会相应的更新。
使用场景
- 关联行为场景,关联行为是可拆分的,事件多级触发。
- 消息队列、时间总线处理机制。
- 一个抽象模型有两个方面,其中一个方面依赖于另一个方面。将这些方面封装在独立的对象中使它们可以各自独立地改变和复用。
- 一个对象的改变将导致其他一个或多个对象也发生改变,而不知道具体有多少对象将发生改变,可以降低对象之间的耦合度。
- 一个对象必须通知其他对象,而并不知道这些对象是谁。
- 需要在系统中创建一个触发链,A对象的行为将影响B对象,B对象的行为将影响C对象……,可以使用观察者模式创建一种链式触发机制
实例代码
- 抽象类定义观察者共同的方法
public abstract class Observer {protected Subject subject;/*** 通知观察者状态*/public abstract void update();}
- 定义具体的观察者
public class ObserverOne extends Observer {private static final Logger logger = LoggerFactory.getLogger(ObserverOne.class);public ObserverOne(Subject subject) {this.subject = subject;this.subject.attach(this);}@Overridepublic void update() {logger.info("ObserverOne 收到通知!");}
}public class ObserverTwo extends Observer{private static final Logger logger = LoggerFactory.getLogger(ObserverTwo.class);public ObserverTwo(Subject subject) {this.subject = subject;this.subject.attach(this);}@Overridepublic void update() {logger.info("ObserverTwo 收到通知!");}
}
- 定义主题
public class Subject {/*** 定义观察者的集合 使用vector 线程安全*/private final Vector<Observer> observerList = new Vector<>();private int state;/*** 注册观察者** @param observer 观察者*/public void registerObserver(Observer observer) {observerList.add(observer);}/*** 通知所有的观察者*/public void notifyAllObservers() {for (Observer observer : observerList) {observer.update();}}public int getState() {return state;}public void setState(int state) {this.state = state;notifyAllObservers();}
}
- 测试代码
public class AppTest {private static final Logger logger = LoggerFactory.getLogger(AppTest.class);@Testpublic void test() {Subject subject = new Subject();new ObserverOne(subject);new ObserverTwo(subject);logger.info("第一次状态改变:12");subject.setState(12);logger.info("第二次状态改变:8");subject.setState(8);}}
策略模式
类图
简单理解
- 在接口中定义方法,不同的实现类在重写的方法中做出不同的操作。
使用场景
- 当符合场景时候可以替换
if、else
实例代码
- 策略接口
public interface Strategy {/*** 计算数值** @param num1 num1* @param num2 num2* @return int*/int calculate(int num1, int num2);}
- 策略实现类
public class CalculateAdd implements Strategy {@Overridepublic int calculate(int num1, int num2) {return num1 + num2;}}
public class CalculateSub implements Strategy {@Overridepublic int calculate(int num1, int num2) {return num1 - num2;}}
- 控制类
public class Context {private Strategy strategy;public Context(Strategy strategy) {this.strategy = strategy;}public int executeStrategy(int num1, int num2) {return strategy.calculate(num1, num2);}
}
- 测试类
public class AppTest {private static final Logger logger = LoggerFactory.getLogger(AppTest.class);@Testpublic void test(){Context context = new Context(new CalculateAdd());int i = context.executeStrategy(1, 2);logger.info(String.valueOf(i));context = new Context(new CalculateSub());int i1 = context.executeStrategy(2, 3);logger.info(String.valueOf(i1));}}
模板方法模式
类图
简单理解
- 在模板模式(
Template Pattern
)中,一个抽象类公开定义了执行它的方法的方式/模板。它的子类可以按需要重写方法实现,但调用将以抽象类中定义的方式进行。这种类型的设计模式属于行为型模式。
实例代码
- 抽象父类
public abstract class AbstractCookMeal {// 去市场abstract void moveToMarket();// 购买蔬菜abstract void buyVegetables();// 回家abstract void goHome();// 做饭abstract void cookMeal();public void doCooking(){moveToMarket();buyVegetables();goHome();cookMeal();}}
- 子类
public class PeopOneCookMeal extends AbstractCookMeal {private static final Logger logger = LoggerFactory.getLogger(PeopOneCookMeal.class);private String name;public PeopOneCookMeal(String name) {this.name = name;}@Overridevoid moveToMarket() {logger.info(this.name + "去超市!");}@Overridevoid buyVegetables() {logger.info(this.name + "买蔬菜!");}@Overridevoid goHome() {logger.info(this.name + "回家!");}@Overridevoid cookMeal() {logger.info(this.name + "做饭!");}
}
- 测试
/*** 模板模式* <p>* 使用继承关系:父类中定义相关的一系列行为,不同的子类通过继承抽象父类实现不同的行为*/
@Test
public void test() {PeopOneCookMeal oneCookMeal = new PeopOneCookMeal("张三");oneCookMeal.doCooking();
}
原型模式
类图
简单理解
- 用一个已经创建的实例作为原型,通过复制该原型对象来创建一个和原型相同或相似的新对象。在这里,原型实例指定了要创建的对象的种类。用这种方式创建对象非常高效,根本无须知道对象创建的细节。
关键代码:
- 实现克隆操作,在
JAVA
继承Cloneable
,重写clone()
- 原型模式同样用于隔离类对象的使用者和具体类型(易变类)之间的耦合关系,它同样要求这些"易变类"拥有稳定的接口。
实例代码
- 实现
Cloneable
接口,重写对象的clone
方法
/*** 机器人实现 Cloneable** @author LiDong* @version 1.0.0* @createTime 2021年11月14日 11:00:00*/
public class Robot implements Cloneable {private String sno;private String name;public Robot(String sno, String name) {this.sno = sno;this.name = name;}/*** 克隆 Robot 的实例** @return* @throws CloneNotSupportedException*/@Overrideprotected Object clone() {Robot robot = null;try {robot = (Robot) super.clone();} catch (Exception e) {System.out.println("error occurred while cloning robot: " + e.getMessage());}return robot;}@Overridepublic String toString() {return "Robot{" +"sno='" + sno + '\'' +", name='" + name + '\'' +'}';}
}
- 测试类
public class ProtoTypeTest {private static final Logger logger = LoggerFactory.getLogger(ProtoTypeTest.class);@Testpublic void test() {Robot robot = new Robot("1001", "张三");Robot robot1 = (Robot) robot.clone();Robot robot2 = (Robot) robot.clone();Robot robot3 = (Robot) robot.clone();Robot robot4 = (Robot) robot.clone();Robot robot5 = (Robot) robot.clone();Robot robot6 = (Robot) robot.clone();logger.info("info: " + robot);logger.info("info: " + robot1);logger.info("info: " + robot2);logger.info("info: " + robot3);logger.info("info: " + robot4);logger.info("info: " + robot5);logger.info("info: " + robot6);}
}
- 简单理解就是快速创建克隆对象
代理模式
- 在代理模式(
Proxy Pattern
)中,一个类代表另一个类的功能。这种类型的设计模式属于结构型模式。在代理模式中,我们创建具有现有对象的对象,以便向外界提供功能接口。
静态代理
类图
静态代理的代理关系在编译期间就已经确定了的。它适合于代理类较少且确定的情况。如果委托类多了那么,就得要写好多代理方法。
- 公用接口
/*** UserService 接口* @author root*/
public interface UserService {/*** 接口中的方法*/void methodTest();
}
- 被代理的类:实现接口
public class UserServiceImpl implements UserService {private static final Logger log = Logger.getLogger(String.valueOf(UserServiceImpl.class));@Overridepublic void methodTest() {log.info("UserServiceImpl 中 methodTest()");}
}
- 代理类:实现接口,维护一个被代理的对象
public class UserServiceProxyImpl implements UserService {private static final Logger log = Logger.getLogger(String.valueOf(UserServiceImpl.class));/*** 维护的需要代理的对象*/private final UserService userService;public UserServiceProxyImpl(UserService userService) {this.userService = userService;}@Overridepublic void methodTest() {log.info("UserServiceProxy 中 methodTest() 开始...");userService.methodTest();log.info("UserServiceProxy 中 methodTest() 结束...");}
}
- 测试方法
/*** 静态代理*/
@Test
public void test1() {UserService userService = new UserServiceImpl();UserServiceProxyImpl userServiceProxy = new UserServiceProxyImpl(userService);// 用代理类执行 UserServiceImpl 中test1()userServiceProxy.methodTest();
}
JDK 动态代理
类图
-
通过实现
InvocationHandler
接口创建自己的调用处理器;通过为Proxy
类指定ClassLoader
对象和一组interface
来创建动态代理类;通过反射机制获得动态代理类的构造函数,其唯一参数类型是调用处理器接口类型;通过构造函数创建动态代理类实例,构造时调用处理器对象作为参数被传入。动态代理主要是性能问题。 -
公用接口
/*** UserService 接口* @author root*/
public interface UserService {/*** 接口中的方法*/void methodTest();
}
- 被代理的类:实现接口
public class UserServiceImpl implements UserService {private static final Logger log = Logger.getLogger(String.valueOf(UserServiceImpl.class));@Overridepublic void methodTest() {log.info("UserServiceImpl 中 methodTest()");}
}
- 代理类:实现
InvocationHandler
接口,维护一个被代理的对象,重写invoke()
public class DynamicUserServiceProxy implements InvocationHandler {private static final Logger log = Logger.getLogger(String.valueOf(UserServiceProxyImpl.class));/*** 代理对象*/private final Object object;public DynamicUserServiceProxy(Object object) {this.object = object;}/*** 为目标对象生成代理对象*/public Object getProxyInstance() {log.info("-----> 开始生成代理对象...");return Proxy.newProxyInstance(object.getClass().getClassLoader(), object.getClass().getInterfaces(), this);}/**** 重写 invoke 方法再里面实现业务逻辑* @param object 对象* @param method 方法* @param args 参数* @return Object*/@Overridepublic Object invoke(Object object, Method method, Object[] args) throws Throwable {log.info("-----> invoke()...");//这里就可以进行所谓的AOP编程了//在调用具体函数方法前,执行功能处理log.info("Aop开始...");return method.invoke(this.object, args);}}
- 测试方法
/*** JDK 动态代理*/
@Test
public void test2() {UserService userService = new UserServiceImpl();DynamicUserServiceProxy dynamicUserServiceProxy = new DynamicUserServiceProxy(userService);UserService userService1 = (UserService) dynamicUserServiceProxy.getProxyInstance();userService1.methodTest();
}
Cglib代理
类图
-
cglib
代理无需实现接口,通过生成类字节码实现代理,比反射稍快,不存在性能问题,但cglib
会继承目标对象,需要重写方法,所以目标对象不能为final
类。 -
引入jar包
<dependency><groupId>cglib</groupId><artifactId>cglib</artifactId><version>3.2.5</version>
</dependency>
- 代理类:
public class CglibUserServiceProxy implements MethodInterceptor {private static final Logger log = Logger.getLogger(String.valueOf(CglibUserServiceProxy.class));private Object target;//维护一个目标对象public CglibUserServiceProxy(Object target) {this.target = target;}//为目标对象生成代理对象public Object getProxyInstance() {//工具类Enhancer en = new Enhancer();//设置父类en.setSuperclass(target.getClass());//设置回调函数en.setCallback(this);//创建子类对象代理return en.create();}@Overridepublic Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {log.info("方法前...");// 执行目标对象的方法method.invoke(target, args);log.info("方法后....");return null;}
}
- 测试代码
/*** CGlib 动态代理*/
@Test
public void tes3() {//目标对象UserService userService = new UserServiceImpl();//代理对象UserService proxy = (UserService) new CglibUserServiceProxy(userService).getProxyInstance();//执行代理对象方法proxy.methodTest();
}
适配器模式
类图
-
将一个类的接口转换成客户希望的另外一个接口。适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。
-
在适配器模式中,我们通过增加一个新的适配器类来解决接口不兼容的问题,使得原本没有任何关系的类可以协同工作。
角色
Target(目标抽象类)
定义所需要的接口,可以是抽象类或接口也可以是具体类。
AdapterClass(适配器类)
适配器继承被适配者类,实现Target,在接口的实现方法中调用超类的方法。
MatchesClass(适配者类)
适配者即被适配的角色,它定义了一个已经存在的接口,这个接口需要适配,适配者类一般是一个具体类,包含了客户希望使用的业务方法,在某些情况下可能没有适配者类的源代码。
类适配器模式
- 被适配者类(MatchesClass)
public class ClassAdapter {public void testMethodOne(){System.out.println("被适配的方法!");}
}
- 适配器类(AdapterClass)
public class Adapter extends ClassAdapter implements TargetInterface {/*** @Author LiDong* @Description //TODO 重写接口中的方法,调用超类的方法* @Date 21:24 2020/12/5* @Param [] * @return void**/@Overridepublic void testMethod() {System.out.println("调用Adapter的testMethod()!");super.testMethodOne();}
}
- 目标抽象类
public interface TargetInterface {void testMethod();
}
- 测试类
public static void main(String[] args) {TargetInterface targetInterface = new Adapter();targetInterface.testMethod();
}
对象适配器模式
对象适配器与类适配器不同之处在于,类适配器通过继承来完成适配,对象适配器则是通过调用对象的属性完成。
public class Adapter implements TargetInterface {private ClassAdapter classAdapter = new ClassAdapter();/*** @Author LiDong* @Description //TODO 重写接口中的方法,对象调用类的方法* @Date 21:24 2020/12/5* @Param [] * @return void**/@Overridepublic void testMethod() {System.out.println("调用Adapter的testMethod()!");classAdapter.testMethodOne();}
}
主要优点
-
将目标类和适配者类解耦,通过引入一个适配器类来重用现有的适配者类,无需修改原有结构。
-
增加了类的透明性和复用性。
-
灵活性和扩展性都非常好,通过使用配置文件,可以很方便地更换适配器
实例
- 播放器接口
@FunctionalInterface
public interface MediaPlayer {/*** 播放歌曲** @param audioType 歌曲类型*/void play(String audioType);}
- 播放器实现类
@Slf4j
public class AudioPlayer implements MediaPlayer {@Overridepublic void play(String audioType) {//播放 mp3 音乐文件的内置支持if ("mp3".equalsIgnoreCase(audioType)) {log.info("Playing mp3 file. ");}//mediaAdapter 提供了播放其他文件格式的支持else if ("vlc".equalsIgnoreCase(audioType) || "mp4".equalsIgnoreCase(audioType)) {MediaAdapter mediaAdapter = new MediaAdapter(audioType);mediaAdapter.play(audioType);} else {log.info("Invalid media. {} format not supported", audioType);}}
}
- 高级播放器接口
public interface AdvancedMediaPlayer {/*** 播放 vlc*/void playVlc();/*** 播放 mp4*/void playMp4();}
- 高级播放器接口实现类
public class Mp4Player implements AdvancedMediaPlayer{public static final Logger logger = LoggerFactory.getLogger(Mp4Player.class);@Overridepublic void playVlc() {logger.info("......");}@Overridepublic void playMp4() {logger.info("Mp4Player 播放mp4...");}
}public class VlcPlayer implements AdvancedMediaPlayer {public static final Logger logger = LoggerFactory.getLogger(VlcPlayer.class);@Overridepublic void playVlc() {logger.info("VlcPlayer 播放vlc...");}@Overridepublic void playMp4() {logger.info("......");}
}
- 适配器类
public class MediaAdapter implements MediaPlayer {/*** 维护一个 advancedMediaPlayer*/private AdvancedMediaPlayer advancedMediaPlayer;MediaAdapter(String audioType) {if ("vlc".equalsIgnoreCase(audioType)) {advancedMediaPlayer = new VlcPlayer();} else if ("mp4".equalsIgnoreCase(audioType)) {advancedMediaPlayer = new Mp4Player();}}@Overridepublic void play(String audioType) {if ("vlc".equalsIgnoreCase(audioType)) {advancedMediaPlayer.playVlc();} else if ("mp4".equalsIgnoreCase(audioType)) {advancedMediaPlayer.playMp4();}}
}
- 测试代码
@Test
public void test() {AudioPlayer audioPlayer = new AudioPlayer();audioPlayer.play("mp3");audioPlayer.play("mp4");audioPlayer.play("vlc");audioPlayer.play("avi");
}
建造者模式
类图
- 建造者模式(
Builder Pattern
)使用多个简单的对象一步一步构建成一个复杂的对象。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。 - 一个
Builder
类会一步一步构造最终的对象。该Builder
类是独立于其他对象的。
定义
- 将一个复杂的构建与其表示相分离,使得同样的构建过程可以创建不同的表示。
特点
- 建造者独立,易扩展。 便于控制细节风险。产品必须有共同点,范围有限制。如内部变化复杂,会有很多的建造类。
实例代码
- 创建一个表示食物条目和食物包装的接口。
public interface Item {String name();Packing packing();float price();}
public interface Packing {/*** 打包** @return void*/String pack();
}
- 创建实现 Packing 接口的实体类。
public class Wrapper implements Packing {@Overridepublic String pack() {return "Wrapper";}
}
public class Bottle implements Packing {@Overridepublic String pack() {return "Bottle";}
}
- 创建实现
Item
接口的抽象类,该类提供了默认的功能。
public abstract class Burger implements Item {@Overridepublic Packing packing() {return new Wrapper();}@Overridepublic abstract float price();
}
public abstract class ColdDrink implements Item {@Overridepublic Packing packing() {return new Bottle();}@Overridepublic abstract float price();}
- 创建扩展了
Burger
和ColdDrink
的实体类。
public class Coke extends ColdDrink {@Overridepublic float price() {return 30.0f;}@Overridepublic String name() {return "Coke";}
}
public class VegBurger extends Burger {public static final float PRICE = 25.0f;@Overridepublic float price() {return PRICE;}@Overridepublic String name() {return "Veg Burger";}}
public class ChickenBurger extends Burger {public static final float PRICE = 50.5f;@Overridepublic float price() {return PRICE;}@Overridepublic String name() {return "Chicken Burger";}
}
public class Pepsi extends ColdDrink {@Overridepublic float price() {return 35.0f;}@Overridepublic String name() {return "Pepsi";}
}
- 创建一个
Meal
类,带有上面定义的Item
对象。
@Slf4j
public class Meal {private final List<Item> items = new ArrayList<>();public void addItem(Item item){items.add(item);}public float getCost(){float cost = 0.0f;for (Item item : items) {cost += item.price();}return cost;}public void showItems(){for (Item item : items) {log.info("Item : {}", item.name());log.info(", Packing : {}", item.packing().pack());log.info(", Price : {}", item.price());}}
}
- 创建一个
MealBuilder
类,实际的builder
类负责创建Meal
对象。
public class MealBuilder {public Meal prepareVegMeal() {Meal meal = new Meal();meal.addItem(new VegBurger());meal.addItem(new Coke());return meal;}public Meal prepareNonVegMeal() {Meal meal = new Meal();meal.addItem(new ChickenBurger());meal.addItem(new Pepsi());return meal;}
}
- 测试代码
@Slf4j
public class AppTest {public static final String TOTAL_COST = "Total Cost: {}";@Testpublic void test() {MealBuilder mealBuilder = new MealBuilder();Meal vegMeal = mealBuilder.prepareVegMeal();log.info("Veg Meal");vegMeal.showItems();float cost = vegMeal.getCost();log.info(TOTAL_COST, cost);Meal nonVegMeal = mealBuilder.prepareNonVegMeal();log.info("Non-Veg Meal");nonVegMeal.showItems();float cost1 = nonVegMeal.getCost();log.info(TOTAL_COST, cost1);}}
桥接模式
简单理解
- 桥接(
Bridge
)是用于把抽象化与实现化解耦,使得二者可以独立变化。这种类型的设计模式属于结构型模式,它通过提供抽象化和实现化之间的桥接结构,来实现二者的解耦。
类图
实例代码
- 画图接口
public interface DrawApi {/*** 画圆*/void drawCircle();}
- 接口实现类
@Slf4j
public class GreenCircle implements DrawApi {@Overridepublic void drawCircle() {log.info("我画了一个绿色的圆圈");}
}
@Slf4j
public class RedCircle implements DrawApi{@Overridepublic void drawCircle() {log.info("我画了一个红色的圆圈");}
}
- 抽象类:维护一个接口对象,提供抽象方法
public abstract class Shape {protected DrawApi drawApi;public Shape(DrawApi drawApi) {this.drawApi = drawApi;}protected abstract void draw();
}
- 抽象类子类
@Slf4j
public class Circle extends Shape{public Circle(DrawApi drawApi) {super(drawApi);}@Overrideprotected void draw() {drawApi.drawCircle();}
}
过滤器模式
类图
定义
- 过滤器模式(
Filter Pattern
)或标准模式(Criteria Pattern
)是一种设计模式,这种模式允许开发人员使用不同的标准来过滤一组对象,通过逻辑运算以解耦的方式把它们连接起来。这种类型的设计模式属于结构型模式,它结合多个标准来获得单一标准。
实例
- 定义
Person
对象
@SuppressWarnings("all")
public class Person {private String name;private String gender;/*** 婚姻状况*/private String martialStatus;
}
- 定义标准接口
public interface Criteria {List<Person> meetCriteria(List<Person> persons);
}
- 接口的实现:对象过滤的实现
public class CriteriaMale implements Criteria {@Overridepublic List<Person> meetCriteria(List<Person> persons) {List<Person> malePersons = new ArrayList<>();for (Person person : persons) {if ("MALE".equalsIgnoreCase(person.getGender())) {malePersons.add(person);}}return malePersons;}
}
public class AndCriteria implements Criteria {private final Criteria criteria;private final Criteria otherCriteria;public AndCriteria(Criteria criteria, Criteria otherCriteria) {this.criteria = criteria;this.otherCriteria = otherCriteria;}@Overridepublic List<Person> meetCriteria(List<Person> persons) {List<Person> firstCriteriaPersons = criteria.meetCriteria(persons);return otherCriteria.meetCriteria(firstCriteriaPersons);}
}
- 测试代码
@Slf4j
public class AppTest {public static final String SINGLE = "Single";public static final String MARRIED = "Married";public static final String FEMALE = "Female";@Testpublic void test() {List<Person> persons = new ArrayList<>();persons.add(new Person("Robert", "Male", SINGLE));persons.add(new Person("John", "Male", MARRIED));persons.add(new Person("Laura", FEMALE, MARRIED));persons.add(new Person("Diana", FEMALE, SINGLE));persons.add(new Person("Mike", "Male", SINGLE));persons.add(new Person("Bobby", "Male", SINGLE));Criteria male = new CriteriaMale();Criteria female = new CriteriaFemale();Criteria single = new CriteriaSingle();Criteria singleMale = new AndCriteria(single, male);Criteria singleOrFemale = new OrCriteria(single, female);log.info("Males: ");printPersons(male.meetCriteria(persons));log.info("Females: ");printPersons(female.meetCriteria(persons));log.info("Single Males: ");printPersons(singleMale.meetCriteria(persons));log.info("Single Or Females: ");printPersons(singleOrFemale.meetCriteria(persons));}public static void printPersons(List<Person> persons) {for (Person person : persons) {log.info("Person : [ Name : {}, Gender : {}, Marital Status : {} ]", person.getName(), person.getGender(), person.getMartialStatus());}}}
组合模式
类图
定义
- 组合模式(
Composite Pattern
),又叫部分整体模式,是用于把一组相似的对象当作一个单一的对象。组合模式依据树形结构来组合对象,用来表示部分以及整体层次。这种类型的设计模式属于结构型模式,它创建了对象组的树形结构。
实例代码
- 员工类
public class Employee {private String name;private String dept;private int salary;private List<Employee> subordinates;//构造函数public Employee(String name, String dept, int sal) {this.name = name;this.dept = dept;salary = sal;subordinates = new ArrayList<>();}public void add(Employee e) {subordinates.add(e);}public void remove(Employee e) {subordinates.remove(e);}public List<Employee> getSubordinates() {return subordinates;}@Overridepublic String toString() {return "Employee{" +"name='" + name + '\'' +", dept='" + dept + '\'' +", salary=" + salary +", subordinates=" + subordinates +'}';}
}
装饰器模式
类图
定义
-
装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构。这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装。
-
这种模式创建了一个装饰类,用来包装原有的类,并在保持类方法签名完整性的前提下,提供了额外的功能。
-
我们通过下面的实例来演示装饰器模式的用法。其中,我们将把一个形状装饰上不同的颜色,同时又不改变形状类。
特点
- 装饰类和被装饰类可以独立发展,不会相互耦合,装饰模式是继承的一个替代模式,装饰模式可以动态扩展一个实现类的功能。
- 多层装饰比较复杂。
实现代码
- 定义画图形的接口
public interface Shape {/*** 画图*/void draw();
}
- 接口实现类
@Slf4j
public class Circle implements Shape {@Overridepublic void draw() {log.info("画了一个圆!");}
}
@Slf4j
public class Rectangle implements Shape {@Overridepublic void draw() {log.info("画了一个矩形!");}
}
- 定义装饰器
public class ShapeDecorator implements Shape {protected Shape decoratorShape;public ShapeDecorator(final Shape shape) {this.decoratorShape = shape;}@Overridepublic void draw() {decoratorShape.draw();}
}
- 装饰器扩展类
@Slf4j
public class RedShapeDecorator extends ShapeDecorator {public RedShapeDecorator(Shape shape) {super(shape);}@Overridepublic void draw() {decoratorShape.draw();setRedBorder(decoratorShape);}private void setRedBorder(Shape decoratedShape) {log.info("Border Color: Red");}
}
- 测试代码
@Test
public void test() {Shape circle = new Circle();ShapeDecorator redCircle = new RedShapeDecorator(new Circle());ShapeDecorator redRectangle = new RedShapeDecorator(new Rectangle());circle.draw();redCircle.draw();redRectangle.draw();
}
外观模式
类图
定义
-
外观模式(
Facade Pattern
)隐藏系统的复杂性,并向客户端提供了一个客户端可以访问系统的接口。这种类型的设计模式属于结构型模式,它向现有的系统添加一个接口,来隐藏系统的复杂性。 -
这种模式涉及到一个单一的类,该类提供了客户端请求的简化方法和对现有系统类方法的委托调用。
特点
-
减少系统相互依赖。 提高灵活性。提高了安全性。
-
不符合开闭原则,如果要改东西很麻烦,继承重写都不合适。
实现代码
- 创建一个接口
public interface Shape {void draw();
}
- 接口实现类
@Slf4j
public class Circle implements Shape{@Overridepublic void draw() {log.info("画出一个圆!");}
}
@Slf4j
public class Rectangle implements Shape{@Overridepublic void draw() {log.info("画出一个矩形!");}
}
- 外观类
public class ShapeMaker {private Shape circle;private Shape rectangle;public ShapeMaker() {circle = new Circle();rectangle = new Rectangle();}public void drawCircle() {circle.draw();}public void drawRectangle() {rectangle.draw();}}
- 测试代码
public class AppTest {@Testpublic void test() {ShapeMaker shapeMaker = new ShapeMaker();shapeMaker.drawCircle();shapeMaker.drawRectangle();}
}
享元模式
类图
定义
- 享元模式(
Flyweight Pattern
)主要用于减少创建对象的数量,以减少内存占用和提高性能。这种类型的设计模式属于结构型模式,它提供了减少对象数量从而改善应用所需的对象结构的方式。
实现代码
- 创建一个接口
public interface Shape {void draw();
}
- 接口实现类
@Slf4j
public class Circle implements Shape {private String color;private int x;private int y;private int radius;public Circle(String color) {this.color = color;}@Overridepublic void draw() {log.info(toString());}public void setX(int x) {this.x = x;}public void setY(int y) {this.y = y;}public void setRadius(int radius) {this.radius = radius;}
}
- 创建一个工厂,生成基于给定信息的实体类的对象。
@Slf4j
public class ShapeFactory {private static final HashMap<String, Circle> circleMap = new HashMap<>();public static Circle getCircle(String color) {Circle circle = circleMap.get(color);if (Objects.isNull(circle)) {circle = new Circle(color);circleMap.put(color, circle);log.info("创建一个 {} 颜色的Circle:", color);}return circle;}
}
- 测试代码
public class AppTest {private static final String[] colors ={"Red", "Green", "Blue", "White", "Black"};@Testpublic void test() {for (int i = 0; i < 20; ++i) {Circle circle = ShapeFactory.getCircle(getRandomColor());circle.setX(getRandomX());circle.setY(getRandomY());circle.setRadius(100);circle.draw();}}private static String getRandomColor() {return colors[(int) (Math.random() * colors.length)];}private static int getRandomX() {return (int) (Math.random() * 100);}private static int getRandomY() {return (int) (Math.random() * 100);}
}
责任链模式
类图
定义
- 责任链模式(
Chain of Responsibility Pattern
)为请求创建了一个接收者对象的链。这种模式给予请求的类型,对请求的发送者和接收者进行解耦。这种类型的设计模式属于行为型模式。 - 在这种模式中,通常每个接收者都包含对另一个接收者的引用。如果一个对象不能处理该请求,那么它会把相同的请求传给下一个接收者,依此类推。
特点
-
降低了系统耦合度。新的命令可以很容易添加到系统中去。
-
使用命令模式可能会导致某些系统有过多的具体命令类。
实现代码
- 创建抽象的记录器类。
public abstract class AbstractLogger {public static int INFO = 1;public static int DEBUG = 2;public static int ERROR = 3;protected int level;/*** 责任链中的下一个元素*/protected AbstractLogger nextLogger;public void setNextLogger(AbstractLogger nextLogger) {this.nextLogger = nextLogger;}public void logMessage(int level, String message) {if (this.level <= level) {write(message);}if (nextLogger != null) {nextLogger.logMessage(level, message);}}/*** @param message 输出日志*/abstract protected void write(String message);
}
- 创建扩展了该记录器类的实体类。
@Slf4j
public class ErrorLogger extends AbstractLogger {public ErrorLogger(int level) {this.level = level;}@Overrideprotected void write(String message) {log.info("Error Console::Logger: {}", message);}
}
@Slf4j
public class FileLogger extends AbstractLogger {public FileLogger(int level) {this.level = level;}@Overrideprotected void write(String message) {log.info("File::Logger: {}", message);}
}
@Slf4j
public class ConsoleLogger extends AbstractLogger {public ConsoleLogger(int level) {this.level = level;}@Overrideprotected void write(String message) {log.info("Standard Console::Logger: {}", message);}
}
- 创建不同类型的记录器。赋予它们不同的错误级别,并在每个记录器中设置下一个记录器。每个记录器中的下一个记录器代表的是链的一部分。
public class AppTest {private AbstractLogger getChainOfLogs() {AbstractLogger errorLogger = new ErrorLogger(AbstractLogger.ERROR);AbstractLogger fileLogger = new FileLogger(AbstractLogger.DEBUG);AbstractLogger consoleLogger = new ErrorLogger(AbstractLogger.INFO);errorLogger.setNextLogger(fileLogger);fileLogger.setNextLogger(consoleLogger);return errorLogger;}@Testpublic void test() {AbstractLogger loggerChain = getChainOfLogs();loggerChain.logMessage(AbstractLogger.INFO, "This is an information.");loggerChain.logMessage(AbstractLogger.DEBUG, "This is a debug level information.");loggerChain.logMessage(AbstractLogger.ERROR, "This is an error information.");}}
命令模式
类图
定义
- 命令模式(
Command Pattern
)是一种数据驱动的设计模式,它属于行为型模式。请求以命令的形式包裹在对象中,并传给调用对象。调用对象寻找可以处理该命令的合适的对象,并把该命令传给相应的对象,该对象执行命令。
实现代码
- 创建一个命令接口。
public interface Order {/*** 执行命令*/void execute();}
- 命令接口实现类
public class BuyStock implements Order {private Stock abcStock;public BuyStock(Stock abcStock) {this.abcStock = abcStock;}@Overridepublic void execute() {abcStock.buy();}
}
public class SellStock implements Order {private Stock abcStock;public SellStock(Stock abcStock) {this.abcStock = abcStock;}@Overridepublic void execute() {abcStock.sell();}
}
- 创建命令调用类
public class Broker {private List<Order> orderList = new ArrayList<>();public void takeOrder(Order order) {orderList.add(order);}public void placeOrders() {for (Order order : orderList) {order.execute();}orderList.clear();}
}
- 测试类
public class AppTest {@Testpublic void test() {Stock abcStock = new Stock();BuyStock buyStockOrder = new BuyStock(abcStock);SellStock sellStockOrder = new SellStock(abcStock);Broker broker = new Broker();broker.takeOrder(buyStockOrder);broker.takeOrder(sellStockOrder);broker.placeOrders();}
}
解释器模式
类图
定义
- 释器模式(
Interpreter Pattern
)提供了评估语言的语法或表达式的方式,它属于行为型模式。这种模式实现了一个表达式接口,该接口解释一个特定的上下文。这种模式被用在 SQL 解析、符号处理引擎等。
特点
-
可扩展性比较好,灵活。 增加了新的解释表达式的方式。 易于实现简单文法。
-
可利用场景比较少。 对于复杂的文法比较难维护。 解释器模式会引起类膨胀。 解释器模式采用递归调用方法。
实现代码
- 创建一个表达式接口。
public interface Expression {/*** 解释* @return*/boolean interpret(String context);}
- 创建实现了上述接口的实体类。
public class TerminalExpression implements Expression {private String data;public TerminalExpression(String data) {this.data = data;}@Overridepublic boolean interpret(String context) {if (context.contains(data)) {return true;}return false;}
}
public class AndExpression implements Expression {private Expression expression1 = null;private Expression expression2 = null;public AndExpression(Expression expression1, Expression expression2) {this.expression1 = expression1;this.expression2 = expression2;}@Overridepublic boolean interpret(String context) {return expression1.interpret(context) && expression2.interpret(context);}
}
public class OrExpression implements Expression {private Expression expression1 = null;private Expression expression2 = null;public OrExpression(Expression expression1, Expression expression2) {this.expression1 = expression1;this.expression2 = expression2;}@Overridepublic boolean interpret(String context) {return expression1.interpret(context) || expression2.interpret(context);}
}
InterpreterPatternDemo
使用Expression
类来创建规则,并解析它们。
@Slf4j
public class AppTest {private Expression getMaleExpression() {Expression expression = new TerminalExpression("张三");Expression expression1 = new TerminalExpression("李四");return new OrExpression(expression, expression1);}private Expression getMarrieWomanExpression() {Expression expression = new TerminalExpression("张青");Expression expression1 = new TerminalExpression("李玉");return new AndExpression(expression, expression1);}@Testpublic void test() {Expression isMale = getMaleExpression();Expression isMarriedWoman = getMarrieWomanExpression();log.info("张三是男性吗? {} ", isMale.interpret("张三"));log.info("张青已婚吗? {} ", isMarriedWoman.interpret("张青"));log.info("张青和李玉已婚吗? {} ", isMarriedWoman.interpret("张青 李玉"));}
}
迭代器模式
类图
定义
- 迭代器模式(
Iterator Pattern
)是Java
和.Net
编程环境中非常常用的设计模式。这种模式用于顺序访问集合对象的元素,不需要知道集合对象的底层表示。迭代器模式属于行为型模式。
实现代码
- 迭代器接口
public interface Iterator {boolean hasNext();Object next();
}
public interface Container {Iterator getIterator();}
- 创建实现了
Container
接口的实体类。该类有实现了Iterator
接口的内部类NameIterator
。
public class Persons implements Container {public String[] names = {"张三", "李四", "王五"};@Overridepublic Iterator getIterator() {return new NameIterator();}private class NameIterator implements Iterator {int index;NameIterator() {}@Overridepublic boolean hasNext() {return index < names.length;}@Overridepublic Object next() {if (hasNext()) {String s = names[index];index++;return s;}return null;}}
}
- 测试代码
@Slf4j
public class AppTest {@Testpublic void test() {Persons persons = new Persons();for (Iterator iterator = persons.getIterator(); iterator.hasNext(); ) {Object next = iterator.next();log.info((String) next);}}}
中介者模式
类图
定义
- 中介者模式(
Mediator Pattern
)是用来降低多个对象和类之间的通信复杂性。这种模式提供了一个中介类,该类通常处理不同类之间的通信,并支持松耦合,使代码易于维护。中介者模式属于行为型模式。
实现代码
- 创建中介类。
@Slf4j
public class ChatRoom {public static void showMessage(User user, String message) {log.info(new Date().toString()+user.toString()+": " +message);}
}
- 创建
user
类。
public class User {private String name;public User(final String name) {this.name = name;}public void sendMessage(String message){ChatRoom.showMessage(this,message);}public String getName() {return this.name;}public void setName(final String name) {this.name = name;}@Overridepublic String toString() {return "User{" +"name='" + name + '\'' +'}';}
}
- 使用
User
对象来显示他们之间的通信。
public class AppTest {@Testpublic void test() {User robert = new User("Robert");User john = new User("John");robert.sendMessage("Hi! John!");john.sendMessage("Hello! Robert!");}
}
备忘录模式
类图
定义
- 备忘录模式(
Memento Pattern
)保存一个对象的某个状态,以便在适当的时候恢复对象。备忘录模式属于行为型模式。
实现代码
- 创建
Memento
类。
public class Memento {private String state;public Memento(String state) {this.state = state;}public String getState() {return state;}}
- 创建
Originator
类。
public class Originator {private String state;public void setState(String state) {this.state = state;}public String getState() {return state;}public Memento saveStateToMemento() {return new Memento(state);}public void getStateFromMemento(Memento Memento) {state = Memento.getState();}}
- 创建
CareTaker
类。
public class CareTaker {private List<Memento> mementoList = new ArrayList<Memento>();public void add(Memento state) {mementoList.add(state);}public Memento get(int index) {return mementoList.get(index);}
}
- 使用
CareTaker
和Originator
对象。
@Slf4j
public class AppTest {@Testpublic void test() {Originator originator = new Originator();CareTaker careTaker = new CareTaker();originator.setState("State #1");originator.setState("State #2");careTaker.add(originator.saveStateToMemento());originator.setState("State #3");careTaker.add(originator.saveStateToMemento());originator.setState("State #4");log.info("Current State: " + originator.getState());originator.getStateFromMemento(careTaker.get(0));log.info("First saved State: " + originator.getState());originator.getStateFromMemento(careTaker.get(1));log.info("Second saved State: " + originator.getState());}
}
状态模式
类图
定义
- 在状态模式(
State Pattern
)中,类的行为是基于它的状态改变的。这种类型的设计模式属于行为型模式。 - 在状态模式中,我们创建表示各种状态的对象和一个行为随着状态对象改变而改变的
context
对象。
实现代码
- 创建环境类
public class Context {private State state;/*** 初始化*/public Context() {this.state = new ConcreteStateA();}//对请求做处理public void handle() {state.Handle(this);}public State getState() {return state;}public void setState(State state) {this.state = state;}
}
- 抽象状态类
public abstract class State {public abstract void Handle(Context context);}
- 具体状态类
@Slf4j
public class ConcreteStateA extends State{@Overridepublic void Handle(Context context) {log.info("当前状态是 A");context.setState(new ConcreteStateB());}
}
@Slf4j
public class ConcreteStateB extends State {@Overridepublic void Handle(Context context) {log.info("当前状态是 B");context.setState(new ConcreteStateA());}
}
- 测试代码
public class AppTest {@Testpublic void test() {Context context = new Context();context.handle();context.handle();context.handle();context.handle();}
}
访问者模式
类图
定义
- 将作用于某种数据结构中的各元素的操作分离出来封装成独立的类,使其在不改变数据结构的前提下可以添加作用于这些元素的新的操作,为数据结构中的每个元素提供多种访问方式。它将对数据的操作与数据结构进行分离,是行为类模式中最复杂的一种模式。
实现代码
- 抽象访问者
public interface Visitor {void visit(ConcreteElementA element);void visit(ConcreteElementB element);}
- 具体访问者
@Slf4j
public class ConcreteVisitorA implements Visitor{@Overridepublic void visit(ConcreteElementA element) {log.info("具体访问者A访问-->" + element.operationA());}@Overridepublic void visit(ConcreteElementB element) {log.info("具体访问者A访问-->" + element.operationB());}
}
@Slf4j
public class ConcreteVisitorB implements Visitor {@Overridepublic void visit(ConcreteElementA element) {log.info("具体访问者B访问-->" + element.operationA());}@Overridepublic void visit(ConcreteElementB element) {log.info("具体访问者B访问-->" + element.operationB());}
}
- 抽象元素类
public interface Element {void accept(Visitor visitor);
}
- 具体元素类
@Slf4j
public class ConcreteElementA implements Element {@Overridepublic void accept(Visitor visitor) {visitor.visit(this);}public String operationA() {return "具体元素A的操作。";}
}
public class ConcreteElementB implements Element {@Overridepublic void accept(Visitor visitor) {visitor.visit(this);}public String operationB() {return "具体元素B的操作。";}
}
- 对象结构角色
public class ObjectStructure {private List<Element> list = new ArrayList<Element>();public void accept(Visitor visitor) {Iterator<Element> i = list.iterator();while (i.hasNext()) {((Element) i.next()).accept(visitor);}}public void add(Element element) {list.add(element);}public void remove(Element element) {list.remove(element);}}
- 测试代码
public class AppTest {@Testpublic void test() {ObjectStructure os = new ObjectStructure();os.add(new ConcreteElementA());os.add(new ConcreteElementB());Visitor visitor = new ConcreteVisitorA();os.accept(visitor);System.out.println("------------------------");visitor = new ConcreteVisitorB();os.accept(visitor);}
}
完整代码地址 :https://gitee.com/Marlon_Brando/JavaTest/tree/master/src/main/java/designpatterns