通过一个例子将他们连接起来

例子

一群鸭子想学叫

叫的行为声明一个接口,让想叫的鸭子实现它就可以了。

  1. /**
  2. * @description: 行为接口化
  3. * @date: 2020-06-21 07:59
  4. * @author: 十一
  5. */
  6. public interface Quackable {
  7. void quack();
  8. }
  9. public class MallardDuack implements Quackable {
  10. @Override
  11. public void quack() {
  12. System.out.println("MallardDuack");
  13. }
  14. }
  15. public class RedHeadDuack implements Quackable {
  16. @Override
  17. public void quack() {
  18. System.out.println("RedHeadDuack");
  19. }
  20. }
  21. // 模拟鸭子叫
  22. public class DuckSimulator {
  23. public static void main(String[] args) {
  24. DuckSimulator duckSimulator = new DuckSimulator();
  25. duckSimulator.simulator1();
  26. }
  27. public void simulator1() {
  28. Quackable mallardDuack = new MallardDuack();
  29. Quackable redHeadDuack = new RedHeadDuack();
  30. quack(mallardDuack);
  31. quack(redHeadDuack);
  32. }
  33. public void quack(Quackable quackable) {
  34. quackable.quack();
  35. }
  36. }

天鹅也想学鸭子叫——适配器模式

【天鹅也想学鸭子叫】,如何满足要求,但不违反开闭原则呢?适配器模式

  1. /**
  2. * @description: 适配器模式谁需要什么功能,谁就创建个新的适配器类
  3. * @date: 2020-06-21 08:13
  4. * @author: 十一
  5. */
  6. public class GooseAdapter implements Quackable {
  7. private Goose goose;
  8. @Override
  9. public void quack() {
  10. goose.hook();
  11. }
  12. public GooseAdapter(Goose goose) {
  13. this.goose = goose;
  14. }
  15. }
  16. /**
  17. * @description: 鹅也想呱呱叫,所以可以加入适配器模式
  18. * @date: 2020-06-21 08:11
  19. * @author: 十一
  20. */
  21. public class Goose {
  22. public void hook() {
  23. System.out.println("hook");
  24. }
  25. }
  26. // 天鹅也能quack了
  27. public void simulator2() {
  28. Quackable mallardDuack = new MallardDuack();
  29. Quackable redHeadDuack = new RedHeadDuack();
  30. Goose goose = new Goose();
  31. Quackable gooseAdapter = new GooseAdapter(goose);
  32. quack(mallardDuack);
  33. quack(redHeadDuack);
  34. quack(gooseAdapter);
  35. }

统计呱呱叫的次数——装饰者模式

给鸭子加入【统计呱呱叫次数的行为】,如何满足要求,但不违反开闭原则呢?装饰者模式

  1. /**
  2. * @description: 鸭子新的行为,给鸭子叫行为添加了计数的功能
  3. * @date: 2020-06-21 08:24
  4. * @author: 十一
  5. */
  6. public class QuackCounter implements Quackable {
  7. Quackable quackable;
  8. static int numberOfQuackables;
  9. @Override
  10. public void quack() {
  11. quackable.quack();
  12. numberOfQuackables++;
  13. }
  14. public static int getNumberOfQuackables() {
  15. return numberOfQuackables;
  16. }
  17. }
  18. public void simulator3() {
  19. Quackable mallardDuack = new QuackCounter(new MallardDuack());
  20. Quackable redHeadDuack = new QuackCounter(new RedHeadDuack());
  21. Goose goose = new Goose();
  22. Quackable gooseAdapter = new QuackCounter(new GooseAdapter(goose));
  23. quack(mallardDuack);
  24. quack(redHeadDuack);
  25. quack(gooseAdapter);
  26. System.out.println("鸭子叫的次数:"+QuackCounter.getNumberOfQuackables());
  27. }

困境!

如果一只鸭子忘记被 QuackCounter 包装了,那么它的叫声就不能被统计了。我们需要强制让鸭子包装,以免出现这样的问题。

化解——抽象工厂模式

抽象工厂模式,用来生成各种不同类型的鸭子产品家族。

  1. public abstract class AbstractDuckFactory {
  2. public abstract Quackable createMallardDuack();
  3. public abstract Quackable createRedHeadDuack();
  4. public abstract Quackable createGooseAdapter();
  5. }
  6. public class CountingDuckFactory extends AbstractDuckFactory {
  7. @Override
  8. public Quackable createMallardDuack() {
  9. return new QuackCounter(new MallardDuack());
  10. }
  11. @Override
  12. public Quackable createRedHeadDuack() {
  13. return new QuackCounter(new RedHeadDuack());
  14. }
  15. @Override
  16. public Quackable createGooseAdapter() {
  17. return new QuackCounter(new GooseAdapter(new Goose()));
  18. }
  19. }
  20. public void simulator4(AbstractDuckFactory duckFactory) {
  21. Quackable mallardDuack = duckFactory.createMallardDuack();
  22. Quackable redHeadDuack = duckFactory.createMallardDuack();
  23. Quackable gooseAdapter = duckFactory.createGooseAdapter();
  24. quack(mallardDuack);
  25. quack(redHeadDuack);
  26. quack(gooseAdapter);
  27. System.out.println("鸭子叫的次数:"+QuackCounter.getNumberOfQuackables());
  28. }
  29. public static void main(String[] args) {
  30. DuckSimulator duckSimulator = new DuckSimulator();
  31. // duckSimulator.simulator1();
  32. // duckSimulator.simulator2();
  33. // duckSimulator.simulator3();
  34. AbstractDuckFactory duckFactory = new CountingDuckFactory();
  35. duckSimulator.simulator4(duckFactory);
  36. }

中央集权制度——组合模式

这种方式管理鸭子还是不太方便,如果以后扩大规模成败上千的呢?很容易出问题!

  1. Quackable mallardDuack = duckFactory.createMallardDuack();
  2. Quackable redHeadDuack = duckFactory.createMallardDuack();
  3. Quackable gooseAdapter = duckFactory.createGooseAdapter();
  4. ...
  5. // 每个都要去quack下,太麻烦了
  6. quack(mallardDuack);
  7. quack(redHeadDuack);
  8. quack(gooseAdapter);
  9. quack(gooseAdapter);
  10. quack(gooseAdapter);
  11. ...

使用组合模式,组合模式需要和叶子节点一样实现接口,这里的叶子节点是Quackable的实现类

  1. /**
  2. * @description: 组合模式需要和叶子节点一样实现接口,这里的叶子节点是Quackable的实现类
  3. * @date: 2020-06-21 09:21
  4. * @author: 十一
  5. */
  6. public class Flock implements Quackable {
  7. List<Quackable> quackers = new ArrayList();
  8. @Override
  9. public void quack() {
  10. for (Quackable quacker : quackers) {
  11. quacker.quack();
  12. }
  13. }
  14. public void add(Quackable quackable) {
  15. quackers.add(quackable);
  16. }
  17. }
  18. public static void main(String[] args) {
  19. DuckSimulator duckSimulator = new DuckSimulator();
  20. // duckSimulator.simulator1();
  21. // duckSimulator.simulator2();
  22. // duckSimulator.simulator3();
  23. // AbstractDuckFactory duckFactory = new CountingDuckFactory();
  24. // duckSimulator.simulator4(duckFactory);
  25. Flock flock = new Flock();
  26. AbstractDuckFactory duckFactory = new CountingDuckFactory();
  27. flock.add(duckFactory.createMallardDuack());
  28. flock.add(duckFactory.createMallardDuack());
  29. flock.add(duckFactory.createGooseAdapter());
  30. duckSimulator.quack(flock);
  31. }

鸭子的背叛——观察者模式

一切都很顺利,天下鸭子尽在掌握之中,鸭子们都会学会了呱呱叫,但是最近有个别鸭子用呱呱叫搞起了歪心思,似乎有叛变的冲动,需要对他们进行24小时的全方位无死角监控!