Java:GOF的23种设计模式(下)

三:构造型模式

(1)建造者模式也叫生成器模式(Builder)

1.建造者模式的意图是把构造对象实例的代码逻辑移到要实例化的类的外部
2.生成器模式将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. public class Product {  
  2.   
  3.     private String param1;  
  4.     private String param2;  
  5.   
  6.     public Product(Builder builder) {  
  7.         this.param1 = builder.param1;  
  8.         this.param2 = builder.param2;  
  9.     }  
  10.   
  11.     private static class Builder {  
  12.         String param1;  
  13.         String param2;  
  14.   
  15.         Builder param1(String param1) {  
  16.             this.param1 = param1;  
  17.             return this;  
  18.         }  
  19.   
  20.         Builder param2(String param2) {  
  21.             this.param2 = param2;  
  22.             return this;  
  23.         }  
  24.   
  25.         public Product build() {  
  26.             return new Product(this);  
  27.         }  
  28.   
  29.     }  
  30.   
  31. }  



(2)工厂方法模式(Factory Method)

1.工厂方法的主要意图是用于创建对象的接口,同时控制对哪个类进行实例化。
2.定义一个用于创建对象的接口,让子类决定实例化哪一个类。

简单工厂是和工厂方法很相似的一种设计模式,但它不在GOF的23种设计模式之中。它用一个工厂类,里面有个静态方法,通过判断条件来返回不同的实例,也叫静态工厂。以下是工厂方法:

①抽象工厂

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. package FactoryMethod;  
  2. public abstract class Factory {  
  3.     public abstract Operation createOperation();  
  4. }  
②抽象产品类

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. package FactoryMethod;  
  2. public abstract class Operation {  
  3.     protected int num1, num2;  
  4.     public void setNum1(int num1) {  
  5.         this.num1 = num1;  
  6.     }  
  7.     public void setNum2(int num2) {  
  8.         this.num2 = num2;  
  9.     }  
  10.     public abstract int getResult();  
  11. }  
③产品类

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. package FactoryMethod;  
  2. public class OperationAdd extends Operation {  
  3.     @Override  
  4.     public int getResult() {  
  5.         // TODO 自动生成的方法存根  
  6.         return num1 + num2;  
  7.     }  
  8. }  
[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. package FactoryMethod;  
  2. public class OperationSub extends Operation {  
  3.     @Override  
  4.     public int getResult() {  
  5.         // TODO 自动生成的方法存根  
  6.         return num1 - num2;  
  7.     }  
  8. }  
④具体工厂类

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. package FactoryMethod;  
  2. public class AddFactory extends Factory{  
  3.     @Override  
  4.     public Operation createOperation() {  
  5.         // TODO 自动生成的方法存根  
  6.         return new OperationAdd();  
  7.     }  
  8. }  
[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. package FactoryMethod;  
  2. public class SubFactory extends Factory {  
  3.     @Override  
  4.     public Operation createOperation() {  
  5.         // TODO 自动生成的方法存根  
  6.         return new OperationSub();  
  7.     }  
  8. }  
⑤Test类

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. package FactoryMethod;  
  2. public class Test {  
  3.     public static void main(String[] args) {  
  4.         // TODO 自动生成的方法存根  
  5.         Factory factory = new AddFactory(); // 用特定的工厂产生特定的对象  
  6.         Operation operation = factory.createOperation();  
  7.         operation.num1 = 1;  
  8.         operation.num2 = 2;  
  9.         System.out.println(operation.getResult());  
  10.     }  
  11. }  
可以看到当需要一个功能类时,就应该相应增加一个工厂类。

工厂方法模式:
一个抽象产品类,可以派生出多个具体产品类。   
一个抽象工厂类,可以派生出多个具体工厂类。   
每个具体工厂类只能创建一个具体产品类的实例。
抽象工厂模式:
多个抽象产品类,每个抽象产品类可以派生出多个具体产品类。   
一个抽象工厂类,可以派生出多个具体工厂类。   
每个具体工厂类可以创建多个具体产品类的实例。


(3)抽象工厂模式(Abstract Factory)

1.抽象工厂模式的意图在于创建一系列相互关联或相互依赖的对象。
2.提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。

①多个抽象产品类

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. package a13_AbstractFactory;  
  2. public abstract class IUser {  
  3.     public abstract void insert(User user);  
  4.     public abstract User getUser(int id);  
  5. }  
[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. package a13_AbstractFactory;  
  2. public abstract class IDepartment {  
  3.     public abstract void insert(Department department);  
  4.     public abstract Department getDepartment(int i);  
  5. }  
②具体产品类

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. package a13_AbstractFactory;  
  2. public class SqlserverUser extends IUser {  
  3.     @Override  
  4.     public void insert(User user) {  
  5.         // TODO 自动生成的方法存根  
  6.         System.out.println("在Sql Server中给User表增加了一条记录");  
  7.     }  
  8.     @Override  
  9.     public User getUser(int id) {  
  10.         // TODO 自动生成的方法存根  
  11.         System.out.println("在Sql Server中根据ID得到User表一条记录");  
  12.         return null;  
  13.     }  
  14. }  
[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. package a13_AbstractFactory;  
  2. public class AccessUser extends IUser {  
  3.     @Override  
  4.     public void insert(User user) {  
  5.         // TODO 自动生成的方法存根  
  6.         System.out.println("在Access中给User表增加了一条记录");  
  7.     }  
  8.     @Override  
  9.     public User getUser(int id) {  
  10.         // TODO 自动生成的方法存根  
  11.         System.out.println("在Access中根据ID得到User表一条记录");  
  12.         return null;  
  13.     }  
  14. }  
[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. package a13_AbstractFactory;  
  2. public class SqlserverDepartment extends IDepartment {  
  3.     @Override  
  4.     public void insert(Department department) {  
  5.         // TODO 自动生成的方法存根  
  6.         System.out.println("在Sql Server中给Department表增加了一条记录");  
  7.     }  
  8.     @Override  
  9.     public Department getDepartment(int i) {  
  10.         // TODO 自动生成的方法存根  
  11.         System.out.println("在Sql Server中给根据ID得到Department表一条记录");  
  12.         return null;  
  13.     }  
  14. }  
[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. package a13_AbstractFactory;  
  2. public class AccessDepartment extends IDepartment {  
  3.     @Override  
  4.     public void insert(Department department) {  
  5.         // TODO 自动生成的方法存根  
  6.         System.out.println("在Access中给Department表添加了一条记录");  
  7.     }  
  8.     @Override  
  9.     public Department getDepartment(int i) {  
  10.         // TODO 自动生成的方法存根  
  11.         System.out.println("在Access中给根据ID得到Department表一条记录");  
  12.         return null;  
  13.     }  
  14. }  
③抽象工厂类

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. package a13_AbstractFactory;  
  2. public abstract class IFactory {  
  3.     public abstract IUser creatUser();  //注意,它是可以产生两个不同类型产品对象的,分别对应两个产品抽象类  
  4.     public abstract IDepartment createDepartment();  
  5. }  
④具体工厂类

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. package a13_AbstractFactory;  
  2. public class SqlserverFactory extends IFactory {  
  3.     @Override  
  4.     public IUser creatUser() {  
  5.         // TODO 自动生成的方法存根  
  6.         return new SqlserverUser();  
  7.     }  
  8.     @Override  
  9.     public IDepartment createDepartment() {  
  10.         // TODO 自动生成的方法存根  
  11.         return new SqlserverDepartment();  
  12.     }  
  13.   
  14. }  
[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. package a13_AbstractFactory;  
  2. public class AccessFactory extends IFactory {  
  3.     @Override  
  4.     public IUser creatUser() {  
  5.         // TODO 自动生成的方法存根  
  6.         return new AccessUser();  
  7.     }  
  8.     @Override  
  9.     public IDepartment createDepartment() {  
  10.         // TODO 自动生成的方法存根  
  11.         return new AccessDepartment();  
  12.     }  
  13. }  
⑤差点忘了两个最小单元
[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. package a13_AbstractFactory;  
  2.   
  3. public class User {  
  4.     private String name;  
  5.     private int id;  
  6.     public String getName() {  
  7.         return name;  
  8.     }  
  9.     public void setName(String name) {  
  10.         this.name = name;  
  11.     }  
  12.     public int getId() {  
  13.         return id;  
  14.     }  
  15.     public void setId(int id) {  
  16.         this.id = id;  
  17.     }  
  18. }  
[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. package a13_AbstractFactory;  
  2.   
  3. public class Department {  
  4.     private String departmentType;  
  5.     private int id;  
  6.     public String getDepartmentType() {  
  7.         return departmentType;  
  8.     }  
  9.     public void setDepartmentType(String departmentType) {  
  10.         this.departmentType = departmentType;  
  11.     }  
  12.     public int getId() {  
  13.         return id;  
  14.     }  
  15.     public void setId(int id) {  
  16.         this.id = id;  
  17.     }  
  18. }  
⑥Test类

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. package a13_AbstractFactory;  
  2. public class Test {  
  3.     public static void main(String[] args) {  
  4.         // TODO 自动生成的方法存根  
  5.         /* 一个抽象产品类 */  
  6.         // IFactory factory = new SqlserverFactory();  
  7.         // IUser iu = factory.creatUser();  
  8.         // User user = new User();  
  9.         // iu.insert(user);  
  10.         // iu.getUser(1);  
  11.         /* 多个抽象产品类 */  
  12.         IFactory sqlserverFactory = new SqlserverFactory();  
  13.         IUser user = sqlserverFactory.creatUser();  
  14.         User concreteUser = new User();  
  15.         user.insert(concreteUser);  
  16.         user.getUser(1);  
  17.         IFactory accessFactory = new AccessFactory();  
  18.         IDepartment department = accessFactory.createDepartment();  
  19.         Department concreteDepartment = new Department();  
  20.         department.insert(concreteDepartment);  
  21.         department.getDepartment(1);  
  22.     }  
  23.   
  24. }  

打印结果:

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. 在Sql Server中给User表增加了一条记录  
  2. 在Sql Server中根据ID得到User表一条记录  
  3. 在Access中给Department表添加了一条记录  
  4. 在Access中给根据ID得到Department表一条记录  

(4)原型模式(Prototype)

1.原型模式不通过实例化类来创建一个新的未初始化的实例,而是通过复制一个现有对象来生成新的对象。
2.用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
3.原型模式其实就是从一个对象再创建另外一个可定制的对象,而且不需知道任何创建的细节。
概念:
1.浅克隆:被克隆对象的所有变量都含有与原来的对象相同的值,而它所有的对其他对象的引用都仍然指向原来的对象。换一种说法就是浅克隆仅仅克隆所考虑的对象,而不克隆它所引用的对象。 
2.深克隆:被克隆对象的所有变量都含有与原来的对象相同的值,但它所有的对其他对象的引用不再是原有的,而这是指向被复制过的新对象。

①原型类,实现Cloneable接口

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. package a14_Prototype_2;  
  2. public class Prototype implements Cloneable {  
  3.     private String name;  
  4.     public String getName() {  
  5.         return name;  
  6.     }  
  7.     public void setName(String name) {  
  8.         this.name = name;  
  9.     }  
  10.     public Object clone() {  
  11.         try {  
  12.             return super.clone();  
  13.         } catch (CloneNotSupportedException e) {  
  14.             e.printStackTrace();  
  15.             return null;  
  16.         }  
  17.     }  
  18. }  
②具体原型类

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. package a14_Prototype_1;  
  2. public class NewPrototype implements Cloneable {  
  3.     private String id;  // 添加了ID属性  
  4.     public String getId() {  
  5.         return id;  
  6.     }  
  7.     public void setId(String id) {  
  8.         this.id = id;  
  9.     }  
  10.     private Prototype prototype;  
  11.     public Prototype getPrototype() {  
  12.         return prototype;  
  13.     }  
  14.     public void setPrototype(Prototype prototype) {  
  15.         this.prototype = prototype;  
  16.     }  
  17.     public Object clone() {  
  18.         try {  
  19.             return super.clone();  
  20.         } catch (CloneNotSupportedException e) {  
  21.             e.printStackTrace();  
  22.             return null;  
  23.         }  
  24.     }  
  25.   
  26. }  
③Test类

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. package a14_Prototype_1;  
  2.   
  3. public class Test {  
  4.     public static void main(String[] args) {  
  5.         //浅克隆,克隆对象copyObj的Prototype对象与原先newObj对象共用一个对象引用  
  6.         //而沒有創建一個新的對象,所以可得出下列打印结果  
  7.         Prototype pro = new Prototype();  
  8.         pro.setName("original object");  
  9.           
  10.         NewPrototype newObj = new NewPrototype();  
  11.         newObj.setId("test1");  
  12.         newObj.setPrototype(pro);  
  13.   
  14.         NewPrototype copyObj = (NewPrototype) newObj.clone();  
  15.         copyObj.setId("testCopy");  
  16.         copyObj.getPrototype().setName("changed object");  
  17.   
  18.         System.out.println("original object id:" + newObj.getId());  
  19.         System.out.println("original object name:"  
  20.                 + newObj.getPrototype().getName());  
  21.   
  22.         System.out.println("cloned object id:" + copyObj.getId());  
  23.         System.out.println("cloned object name:"  
  24.                 + copyObj.getPrototype().getName());  
  25.     }  
  26. }  
打印结果:

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. original object id:test1  
  2. original object name:changed object  
  3. cloned object id:testCopy  
  4. cloned object name:changed object  
要实现深克隆则修改需要具体原型类的clone方法如下:

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. public Object clone() {  
  2.     NewPrototype ret = null;  
  3.     try {  
  4.         // 将对象本身以及它的引用都克隆下来  
  5.         ret = (NewPrototype) super.clone();  
  6.         ret.prototype = (Prototype) this.prototype.clone();  
  7.         return ret;  
  8.     } catch (CloneNotSupportedException e) {  
  9.         e.printStackTrace();  
  10.         return null;  
  11.     }  
  12. }  
打印结果:

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. original object id:test1  
  2. original object name:original object  
  3. cloned object id:testCopy  
  4. cloned object name:changed object  

(5)备忘录模式(Memento)

1.备忘录模式的意图在于为对象提供状态存储和状态恢复功能
2.备忘录模式可以帮助我们获取对象的状态,以便于将来把对象恢复为以前的状态。
3.在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到原先的状态。
①发起者类

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. package a15_Memento;  
  2. public class Originator {  
  3.     private String state;  
  4.     public String getState() {  
  5.         return state;  
  6.     }  
  7.     public void setState(String state) {  
  8.         this.state = state;  
  9.     }  
  10.     public Memento createMemento() {  
  11.         return (new Memento(state));  
  12.     }  
  13.     public void setMemento(Memento memento) {  
  14.         state = memento.getState();  
  15.     }  
  16.     public void show() {  
  17.         System.out.println("State:" + state);  
  18.     }  
  19. }  
②备忘录类,相当于存储的信息

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. package a15_Memento;  
  2. public class Memento {  
  3.     private String state;  
  4.     public Memento(String state) {  
  5.         this.state = state;  
  6.     }  
  7.     public String getState() {  
  8.         return state;  
  9.     }  
  10.   
  11. }  
③管理者类,管理存储的信息

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. package a15_Memento;  
  2. public class Cracker {  
  3.     private Memento memento;  
  4.     public Memento getMemento() {  
  5.         return memento;  
  6.     }  
  7.     public void setMemento(Memento memento) {  
  8.         this.memento = memento;  
  9.     }  
  10.   
  11. }  
[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. package a15_Memento;  
  2. public class Test {  
  3.     public static void main(String[] args) {  
  4.         // TODO 自动生成的方法存根  
  5.         Originator originator = new Originator();  
  6.         originator.setState("i am very well");  
  7.         originator.show();  
  8.         Cracker cracker = new Cracker();  
  9.         cracker.setMemento(originator.createMemento());  
  10.         originator.setState("i am not good");  
  11.         originator.show();  
  12.         originator.setMemento(cracker.getMemento());  
  13.         originator.show();  
  14.     }  
  15.   
  16. }  


四:操作型模式

(1)模板方法模式(Template Method)
1.模板方法模式的目的在一个方法中实现一个算法,并将算法中某些步骤的定义推迟,从而使得其他类可以重新定义这些步骤。
2.定义一个操作的算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。

①抽象模板类,里面的方法有些是抽象的有些是有方法体的

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. package a16_TemplateMethod;  
  2. public abstract class AbstractTemplate {  
  3.     public abstract void primitiveOperation1();  
  4.     public abstract void primitiveOperation2();  
  5.     public void templateMethod() {  
  6.         primitiveOperation1();  
  7.         primitiveOperation2();  
  8.     }  
  9. }  
②抽象方法的实现类

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. package a16_TemplateMethod;  
  2. public class ConcreteClassA extends AbstractTemplate {  
  3.     @Override  
  4.     public void primitiveOperation1() {  
  5.         // TODO 自动生成的方法存根  
  6.         System.out.println("类A模板方法1实现");  
  7.     }  
  8.     @Override  
  9.     public void primitiveOperation2() {  
  10.         // TODO 自动生成的方法存根  
  11.         System.out.println("类A模板方法2实现");  
  12.   
  13.     }  
  14. }  
[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. package a16_TemplateMethod;  
  2. public class ConcreteClassB extends AbstractTemplate {  
  3.     @Override  
  4.     public void primitiveOperation1() {  
  5.         // TODO 自动生成的方法存根  
  6.         System.out.println("类B模板方法1实现");  
  7.     }  
  8.     @Override  
  9.     public void primitiveOperation2() {  
  10.         // TODO 自动生成的方法存根  
  11.         System.out.println("类B模板方法2实现");  
  12.   
  13.     }  
  14. }  
③Test类

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. package a16_TemplateMethod;  
  2. public class Test {  
  3.     public static void main(String[] args) {  
  4.         // TODO 自动生成的方法存根  
  5.         AbstractTemplate at;  
  6.         at = new ConcreteClassA();  
  7.         at.templateMethod();  
  8.         at = new ConcreteClassB();  
  9.         at.templateMethod();  
  10.     }  
  11. }  


(2)状态模式(State)

1.状态模式的意图在于将与状态有关的处理逻辑分散到代表对象状态的各个类中
2.当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类。
3.状态模式主要解决的是当控制一个对象状态转换的条件表达式过于复杂时的情况,把状态的判断逻辑转移到表示不同状态的一系列类当中,可以把复杂的判断逻辑简化。而如果这个状态判断很简单,那就没必要用状态模式了。

①抽象状态类

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. package a17_State;  
  2. public abstract class State {  
  3.     public abstract void Handle(Context context);  
  4. }  
②具体状态类

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. package a17_State;  
  2. public class ConcreteStateA extends State {  
  3.     @Override  
  4.     public void Handle(Context context) {  
  5.         // TODO 自动生成的方法存根  
  6.         context.setState(new ConcreteStateB());  
  7.     }  
  8. }  
[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. package a17_State;  
  2. public class ConcreteStateB extends State {  
  3.     @Override  
  4.     public void Handle(Context context) {  
  5.         // TODO 自动生成的方法存根  
  6.         context.setState(new ConcreteStateA());  
  7.     }  
  8. }  
③Context环境类

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. package a17_State;  
  2. public class Context {  
  3.     private State state;  
  4.     public Context(State state) {  
  5.         this.state = state;  
  6.     }  
  7.     public State getState() {  
  8.         return state;  
  9.     }  
  10.     public void setState(State state) {  
  11.         this.state = state;  
  12.         System.out.println("当前状态:" + state.getClass().getName());  
  13.     }  
  14.     public void request() {  
  15.         state.Handle(this); //key,控制状态切换  
  16.     }  
  17.   
  18. }  
④Test类

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. package a17_State;  
  2. public class Test {  
  3.     public static void main(String[] args) {  
  4.         // TODO 自动生成的方法存根  
  5.         Context context = new Context(new ConcreteStateA());  
  6.         context.request();  
  7.         context.request();  
  8.         context.request();  
  9.         context.request();  
  10.         context.request();  
  11.     }  
  12. }  


(3)策略模式(Strategy)

1.策略模式的意图在于把可选的策略或方案封装在不同的类中,并在这些类中实现一个共同的操作。
2.策略模式定义了算法家族,分别封装起来,让它们之间可以相互替换,此模式让算法的变化,不会影响到使用算法的用户。

①抽象算法类

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. package a18_Strategy;  
  2. public abstract class Strategy {  
  3.     public abstract void algorithm();  
  4. }  
②具体算法类

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. package a18_Strategy;  
  2. public class concreteStrategyA extends Strategy {  
  3.     @Override  
  4.     public void algorithm() {  
  5.         // TODO 自动生成的方法存根  
  6.         System.out.println("算法A实现");  
  7.     }  
  8. }  
[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. package a18_Strategy;  
  2. public class concreteStrategyB extends Strategy {  
  3.     @Override  
  4.     public void algorithm() {  
  5.         // TODO 自动生成的方法存根  
  6.         System.out.println("算法B实现");  
  7.     }  
  8. }  
[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. package a18_Strategy;  
  2. public class concreteStrategyC extends Strategy {  
  3.     @Override  
  4.     public void algorithm() {  
  5.         // TODO 自动生成的方法存根  
  6.         System.out.println("算法C实现");  
  7.     }  
  8. }  
③上下文环境类

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. package a18_Strategy;  
  2. public class Context {  
  3.     private Strategy strategy;  
  4.     public Context(Strategy strategy) {  
  5.         this.strategy = strategy;  
  6.     }  
  7.     public Context(String choice) {  
  8.         if (choice.endsWith("A"))  
  9.             strategy = new concreteStrategyA();  
  10.         else if (choice.equals("B"))  
  11.             strategy = new concreteStrategyB();  
  12.         else  
  13.             strategy = new concreteStrategyC();  
  14.   
  15.     }  
  16.     public void run() {  
  17.         strategy.algorithm();  
  18.     }  
  19. }  
④Test类

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. package a18_Strategy;  
  2.   
  3. public class Test {  
  4.   
  5.     public static void main(String[] args) {  
  6.         // TODO 自动生成的方法存根  
  7.         String choice = "z";  
  8.         // 客户端的判断可以转移到Context类中用简单工厂实现  
  9.         // if (choice.endsWith("A"))  
  10.         // context = new Context(new concreteStrategyA());  
  11.         // else if (choice.equals("B"))  
  12.         // context = new Context(new concreteStrategyB());  
  13.         // else  
  14.         // context = new Context(new concreteStrategyC());  
  15.         Context context = new Context(choice);  
  16.         context.run();  
  17.   
  18.     }  
  19. }  

(4)命令模式(command)

1.命令模式的意图是把请求封装在对象中
2.把一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤销的操作。

①抽象命令类

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. package a19_Command;  
  2. public abstract class Command {  
  3.     protected Receiver receiver;  
  4.     public Command(Receiver receiver) {  
  5.         this.receiver = receiver;  
  6.     }  
  7.     abstract public void execute();  
  8. }  
②具体命令类

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. package a19_Command;  
  2. public class concreteCommand extends Command {  
  3.     public concreteCommand(Receiver receiver) {  
  4.         super(receiver);  
  5.         // TODO 自动生成的构造函数存根  
  6.     }  
  7.     @Override  
  8.     public void execute() {  
  9.         // TODO 自动生成的方法存根  
  10.         receiver.action("洗衣服");  
  11.     }  
  12. }  
[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. package a19_Command;  
  2. public class concreteCommand1 extends Command {  
  3.     public concreteCommand1(Receiver receiver) {  
  4.         super(receiver);  
  5.         // TODO 自动生成的构造函数存根  
  6.     }  
  7.     @Override  
  8.     public void execute() {  
  9.         // TODO 自动生成的方法存根  
  10.         receiver.action("做饭");  
  11.     }  
  12. }  
③通知者或者说管理类

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. package a19_Command;  
  2. import java.util.ArrayList;  
  3. import java.util.List;  
  4. public class Invoker {  
  5.     private List<Command> commands = new ArrayList<Command>();  
  6.     public void setCommand(Command command) {  
  7.         commands.add(command);  
  8.     }  
  9.     public void execute() {  
  10.         for (Command command : commands)  
  11.             command.execute();  
  12.     }  
  13. }  
④执行者类

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. package a19_Command;  
  2. public class Receiver {  
  3.     public void action(String command) {  
  4.         System.out.println(command);  
  5.     }  
  6. }  
⑤Test类

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. package a19_Command;  
  2. public class Test {  
  3.     public static void main(String[] args) {  
  4.         // TODO 自动生成的方法存根  
  5.         Receiver receiver = new Receiver();  
  6.         Command command = new concreteCommand(receiver);  
  7.         Invoker invoker = new Invoker();  
  8.         invoker.setCommand(command);  
  9.         invoker.setCommand(command);  
  10.         Command command2 = new concreteCommand1(receiver);  
  11.         invoker.setCommand(command2);  
  12.         invoker.execute();  
  13.     }  
  14. }  

(5)解释器模式(Interpreter)

1.解释器模式的主要意图是可以按照自己定义的组合规则集合来组合可执行对象。
2.给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言的句子。

①抽象表达式类

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. package a20_Interpreter;  
  2. public abstract class AbstractExpression {  
  3.     public abstract void interpret(Context context);  
  4. }  
②具体实现类

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. package a20_Interpreter;  
  2. public class TerminalExpression extends AbstractExpression {  
  3.   
  4.     @Override  
  5.     public void interpret(Context context) {  
  6.         // TODO 自动生成的方法存根  
  7.         System.out.println("终端解释器");  
  8.     }  
  9. }  
[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. package a20_Interpreter;  
  2. public class NonterminalExpression extends AbstractExpression {  
  3.     @Override  
  4.     public void interpret(Context context) {  
  5.         // TODO 自动生成的方法存根  
  6.         System.out.println("非终端解释器");  
  7.     }  
  8. }  

③上下文环境类,包含解释器以外的一些全局信息

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. package a20_Interpreter;  
  2. public class Context {  
  3.     private String input, output;  
  4.     public String getInput() {  
  5.         return input;  
  6.     }  
  7.     public void setInput(String input) {  
  8.         this.input = input;  
  9.     }  
  10.     public String getOutput() {  
  11.         return output;  
  12.     }  
  13.     public void setOutput(String output) {  
  14.         this.output = output;  
  15.     }  
  16. }  

④Test类

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. package a20_Interpreter;  
  2. import java.util.ArrayList;  
  3. import java.util.List;  
  4. public class Test {  
  5.     public static void main(String[] args) {  
  6.         // TODO 自动生成的方法存根  
  7.         Context context = new Context();  
  8.         List<AbstractExpression> list = new ArrayList<AbstractExpression>();  
  9.         list.add(new TerminalExpression());  
  10.         list.add(new NonterminalExpression());  
  11.         list.add(new TerminalExpression());  
  12.         list.add(new TerminalExpression());  
  13.         for (AbstractExpression ae : list) {  
  14.             ae.interpret(context);  
  15.         }  
  16.     }  
  17. }  
其实这个例子感觉不是很好,但又找不到更好的- -


五:拓展型模式

(1)装饰器模式

1.装饰器模式的意图是在运行时组合操作的新变化
2.动态地给一个对象增加一些额外的职责,就增加功能来说,装饰模式比生成子类更加灵活。

①抽象组件类,可以在此添加职责

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. package a21_Decorator;  
  2. public abstract class Component {  
  3.     public abstract void operation();  
  4. }  
②具体组件类

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. package a21_Decorator;  
  2. public class ConcreteComponent extends Component {  
  3.   
  4.     @Override  
  5.     public void operation() {  
  6.         // TODO 自动生成的方法存根  
  7.         System.out.println("具体对象的操作");  
  8.     }  
  9. }  
③装饰父类

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. package a21_Decorator;  
  2. public class Decorator extends Component {  
  3.     protected Component component;  
  4.     @Override  
  5.     public void operation() {  
  6.         // TODO 自动生成的方法存根  
  7.         if (component != null) {  
  8.             component.operation();  
  9.         }  
  10.     }  
  11.     public void setComponent(Component component) {  
  12.         this.component = component;  
  13.     }  
  14. }  
④具体装饰子类

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. package a21_Decorator;  
  2. public class ConcreteDecoratorA extends Decorator {  
  3.     @Override  
  4.     public void operation() {  
  5.         // TODO 自动生成的方法存根  
  6.         super.operation();  
  7.         addedBehavior();  
  8.     }  
  9.     private void addedBehavior() {  
  10.         System.out.println("装饰A");  
  11.     }  
  12. }  
[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. package a21_Decorator;  
  2. public class ConcreteDecoratorB extends Decorator {  
  3.     @Override  
  4.     public void operation() {  
  5.         // TODO 自动生成的方法存根  
  6.         super.operation();  
  7.         addedBehavior();  
  8.     }  
  9.     private void addedBehavior() {  
  10.         System.out.println("装饰B");  
  11.     }  
  12. }  
⑤Test类

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. package a21_Decorator;  
  2. public class Test {  
  3.     public static void main(String[] args) {  
  4.         // TODO 自动生成的方法存根  
  5.         ConcreteComponent c = new ConcreteComponent();  
  6.         ConcreteDecoratorA d1 = new ConcreteDecoratorA();  
  7.         ConcreteDecoratorB d2 = new ConcreteDecoratorB();  
  8.         d1.setComponent(c);  
  9.         d2.setComponent(d1);  
  10.         d2.operation();  
  11.     }  
  12. }  

(2)迭代器模式(Iterator)

1.迭代器模式的意图在于为开发人员提供一种顺序访问集合元素的方法
2.提供一种方法顺序访问一个聚合对象中各个元素,而又不暴露该对象的内部表示。

①抽象集合类

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. package a22_Iterator;  
  2. public abstract class AbstractAggregate {  
  3.     public abstract void add(Object obj);  
  4.     public abstract void remove(Object obj);  
  5.     public abstract AbstractIterator iterator();  
  6. }  
②抽象迭代器类

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. package a22_Iterator;  
  2. public abstract class AbstractIterator {  
  3.     public abstract Object next();  
  4.     public abstract boolean hasNext();  
  5. }  
③具体集合类
[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. package a22_Iterator;  
  2. import java.util.ArrayList;  
  3. import java.util.Iterator;  
  4. import java.util.List;  
  5. class ConcreteAggregate extends AbstractAggregate {  
  6.     private List list = new ArrayList();  
  7.     public void add(Object obj) {  
  8.         list.add(obj);  
  9.     }  
  10.     public AbstractIterator iterator() {  
  11.         return new ConcreteIterator(list);  
  12.     }  
  13.     public void remove(Object obj) {  
  14.         list.remove(obj);  
  15.     }  
  16. }  

④具体迭代器

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. package a22_Iterator;  
  2. import java.util.ArrayList;  
  3. import java.util.List;  
  4. class ConcreteIterator extends AbstractIterator {  
  5.     private List list = new ArrayList();  
  6.     private int cursor = 0;  
  7.     public ConcreteIterator(List list) {  
  8.         this.list = list;  
  9.     }  
  10.     public boolean hasNext() {  
  11.         if (cursor == list.size()) {  
  12.             return false;  
  13.         }  
  14.         return true;  
  15.     }  
  16.     public Object next() {  
  17.         Object obj = null;  
  18.         if (this.hasNext()) {  
  19.             obj = this.list.get(cursor++);  
  20.         }  
  21.         return obj;  
  22.     }  
  23. }  
⑤Test类,迭代器因其常用性,现在很多语言都直接支持了。

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. package a22_Iterator;  
  2. public class Test {  
  3.     public static void main(String[] args) {  
  4.         // TODO 自动生成的方法存根  
  5.         AbstractAggregate ag = new ConcreteAggregate();  
  6.         ag.add("1");  
  7.         ag.add("2");  
  8.         ag.add("3");  
  9.         AbstractIterator it = ag.iterator();  
  10.         while (it.hasNext()) {  
  11.             String str = (String) it.next();  
  12.             System.out.println(str);  
  13.         }  
  14.     }  
  15.   
  16. }  


(3)访问者模式(Visitor)

1.访问者模式的意图在于让代码用户能够在不修改现有类层次结构的前提下,定义该类层次结构的相关操作。
2.表示一个作用于某对象结构中各元素的操作。它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。

3.访问者模式适用于数据结构相对稳定的系统

①抽象访问者类

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. package a23_Visitor;  
  2. public abstract class Visitor {  
  3.     public abstract void visitConcreteElementA(ConcreteElementA a);  
  4.     public abstract void visitConcreteElementB(ConcreteElementB b);  
  5. }  
②具体访问者类

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. package a23_Visitor;  
  2. public class ConcreteVisitor1 extends Visitor {  
  3.     @Override  
  4.     public void visitConcreteElementA(ConcreteElementA a) {  
  5.         // TODO 自动生成的方法存根  
  6.         System.out.println(a.getClass().getName() + "被"  
  7.                 + this.getClass().getName() + "访问");  
  8.     }  
  9.     @Override  
  10.     public void visitConcreteElementB(ConcreteElementB b) {  
  11.         // TODO 自动生成的方法存根  
  12.         System.out.println(b.getClass().getName() + "被"  
  13.                 + this.getClass().getName() + "访问");  
  14.     }  
  15. }  
[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. package a23_Visitor;  
  2. public class ConcreteVisitor1 extends Visitor {  
  3.     @Override  
  4.     public void visitConcreteElementA(ConcreteElementA a) {  
  5.         // TODO 自动生成的方法存根  
  6.         System.out.println(a.getClass().getName() + "被"  
  7.                 + this.getClass().getName() + "访问");  
  8.     }  
  9.     @Override  
  10.     public void visitConcreteElementB(ConcreteElementB b) {  
  11.         // TODO 自动生成的方法存根  
  12.         System.out.println(b.getClass().getName() + "被"  
  13.                 + this.getClass().getName() + "访问");  
  14.     }  
  15. }  
③抽象元素类,被访问的元素

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. package a23_Visitor;  
  2. public abstract class Element {  
  3.     public abstract void accept(Visitor visitor);  
  4. }  
④具体元素类

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. package a23_Visitor;  
  2. public class ConcreteElementA extends Element {  
  3.     @Override  
  4.     public void accept(Visitor visitor) {  
  5.         // TODO 自动生成的方法存根  
  6.         visitor.visitConcreteElementA(this);  
  7.     }  
  8. }  
[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. package a23_Visitor;  
  2. public class ConcreteElementB extends Element {  
  3.     @Override  
  4.     public void accept(Visitor visitor) {  
  5.         // TODO 自动生成的方法存根  
  6.         visitor.visitConcreteElementB(this);  
  7.     }  
  8. }  
⑤组织类,提供一个高层接口以允许访问者访问它的元素

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. package a23_Visitor;  
  2. import java.util.ArrayList;  
  3. import java.util.List;  
  4. public class ObjectStructure {  
  5.     private List<Element> list = new ArrayList<>();  
  6.     public void attach(Element element) {  
  7.         list.add(element);  
  8.     }  
  9.     public void detach(Element element) {  
  10.         list.remove(element);  
  11.     }  
  12.     public void accept(Visitor visitor) {  
  13.         for (Element element : list) {  
  14.             element.accept(visitor);  
  15.         }  
  16.     }  
  17. }  
⑥Test类

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. package a23_Visitor;  
  2. public class Test {  
  3.     public static void main(String[] args) {  
  4.         // TODO 自动生成的方法存根  
  5.         ObjectStructure os = new ObjectStructure();  
  6.         os.attach(new ConcreteElementA());  
  7.         os.attach(new ConcreteElementB());  
  8.         ConcreteVisitor1 cv1 = new ConcreteVisitor1();  
  9.         // ConcreteVisitor2 cv2 = new ConcreteVisitor2();  
  10.         os.accept(cv1);  
  11.         // os.accept(cv2);  
  12.     }  
  13. }  


     终于整理完了, 现在再叫我写上述23个设计模式的大部分模式,我都是写不出来的。 某年某月某日看到某些代码时,可以惊觉这怎么这么像之前学的那些设计模式的?这样我的学习的目标就达到了。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
GoF 的 23 种设计模式的分类,现在对各个模式的功能进行介绍。 单例(Singleton)模式:某个类只能生成一个实例,该类提供了一个全局访问点供外部获取该实例,其拓展是有限多例模式。 原型(Prototype)模式:将一个对象作为原型,通过对其进行复制而克隆出多个和原型类似的新实例。 工厂方法(Factory Method)模式:定义一个用于创建产品的接口,由子类决定生产什么产品。 抽象工厂(AbstractFactory)模式:提供一个创建产品族的接口,其每个子类可以生产一系列相关的产品。 建造者(Builder)模式:将一个复杂对象分解成多个相对简单的部分,然后根据不同需要分别创建它们,最后构建成该复杂对象。 代理(Proxy)模式:为某对象提供一种代理以控制对该对象的访问。即客户端通过代理间接地访问该对象,从而限制、增强或修改该对象的一些特性。 适配器(Adapter)模式:将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类能一起工作。 桥接(Bridge)模式:将抽象与实现分离,使它们可以独立变化。它是用组合关系代替继承关系来实现,从而降低了抽象和实现这两个可变维度的耦合度。 装饰(Decorator)模式:动态的给对象增加一些职责,即增加其额外的功能。 外观(Facade)模式:为多个复杂的子系统提供一个一致的接口,使这些子系统更加容易被访问。 享元(Flyweight)模式:运用共享技术来有效地支持大量细粒度对象的复用。 组合(Composite)模式:将对象组合成树状层次结构,使用户对单个对象和组合对象具有一致的访问性。 模板方法(TemplateMethod)模式:定义一个操作中的算法骨架,而将算法的一些步骤延迟到子类中,使得子类可以不改变该算法结构的情况下重定义该算法的某些特定步骤。 策略(Strategy)模式:定义了一系列算法,并将每个算法封装起来,使它们可以相互替换,且算法的改变不会影响使用算法的客户。 命令(Command)模式:将一个请求封装为一个对象,使发出请求的责任和执行请求的责任分割开。 职责链(Chain of Responsibility)模式:把请求从链中的一个对象传到下一个对象,直到请求被响应为止。通过这种方式去除对象之间的耦合。 状态(State)模式:允许一个对象在其内部状态发生改变时改变其行为能力。 观察者(Observer)模式:多个对象间存在一对多关系,当一个对象发生改变时,把这种改变通知给其他多个对象,从而影响其他对象的行为。 中介者(Mediator)模式:定义一个中介对象来简化原有对象之间的交互关系,降低系统中对象间的耦合度,使原有对象之间不必相互了解。 迭代器(Iterator)模式:提供一种方法来顺序访问聚合对象中的一系列数据,而不暴露聚合对象的内部表示。 访问者(Visitor)模式:在不改变集合元素的前提下,为一个集合中的每个元素提供多种访问方式,即每个元素有多个访问者对象访问。 备忘录(Memento)模式:在不破坏封装性的前提下,获取并保存一个对象的内部状态,以便以后恢复它。 解释器(Interpreter)模式:提供如何定义语言的文法,以及对语言句子的解释方法,即解释器。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值