设计模式
设计模式
除了类本身,设计模式更强调多个类/对象之间的关系和交互过程---比接口/类复用的粒度更大
1.Creational patterns 创建型模式
2.Structural patterns 结构型模式
3.Behavioral patterns 行为类模式
1.1工厂模式
工厂模式就是一个虚拟构造器,为创建对象定义一个接口,让子类决定初始化哪个类
当client不知道要创建哪个具体类的实例,或者不想在client代码中指明要具体创建的实例时,用工厂方法。
定义一个用于创建对象的接口,让其子类来决定实例化哪一个类,从而使一个类的实例化延迟到其子类。
常规情况下,client直接创建具体对象 Product p = new ProductTwo();
在工厂方法模式下: Product p = new ConcreteTwo().makeObject();
即Abstraction接口的子类ConcreteTwo中的方法makeObject来进行实例化。
Trace log1 = new Factory1().getTrace(); log1.setDebug(true); log1.debug( "entering log" ); Trace log2 = new Factory2().getTrace("system"); log2.setDebug(false); log2.debug("...");
2.1Adaptor 适配器模式
将一个类的接口转换成客户希望的另外一个接口。
Adapter模式使原本由于接口不兼容而不能一起工作的类可以一起工作。
模式的本质是通过委派或者继承,通过适配器,对现有的代码进行复用,因为现有类代码各种原因导致的无法适配的情况,创建一个接口并进行实现。
如图,IEmployee类中的方法showHappiness显然无法直接复用Consultant类中的showSmile方法,但如果创建一个接口IEmployee,用类EmployeeAdapter实现接口的showhappiniess方法,同时EmployeeAdapter继承自Consultant,那么EmployeeAdapter就可以利用ShowHappiness方法调用showSmile方法,完成了接口之间的协作,此时EmployeeAdapter相当于一个Adaptor。
public class Consultant { //已存在的类 private String name; public Consultant(String name) { this.name = name; } protected void ShowSmile() { System.out.println("Consultant " + this.name + " showed smile"); } } public interface IEmployee {//目标接口 void ShowHappiness(); } public class EmployeeAdapter extends Consultant implements IEmployee { //Adapter public EmployeeAdapter(String name){ super(name); } @Override public void ShowHappiness() { ShowSmile(); // call the parent Consultant class } } public class Client { public static void main(String[] args){ IEmployee em = new EmployeeAdapter("Bruno"); em.ShowHappiness(); } } Result: Consultant Bruno showed smile
这是基于继承的复用,而如果Consultant也是一个接口,那么就可以基于委托复用:
新建一个接口,可以将已存在的子类包装起来,面向接口编程就可以隐藏子类
如图,新建一个Shape接口,创建一个子类Rectangle,将display方法委托给LegacyRectangle,这就将内部类型LegacyRectangle与用户隔离了起来,增强了安全性,同时,Adaptor处理了调用接口传入的参数,再委托给LegacyRectangle,这就完成了方法间不兼容的适配。
2.2Decorator
装饰(Decorator)模式的定义: 指在不改变现有对象结构的情况下,动态地给该对象增加一些职责(即增加其额外功能)的模式,它属于对象结构型模式。
装饰(Decorator)模式的主要优点有: 采用装饰模式扩展对象的功能比采用继承方式更加灵活。 可以设计出多个不同的具体装饰类,创造出多个不同行为的组合。
装饰模式主要包含以下角色。
抽象构件(Component)角色:定义一个抽象接口以规范准备接收附加责任的对象。
具体构件(Concrete Component)角色:实现抽象构件,通过装饰角色为其添加一些职责。
抽象装饰(Decorator)角色:继承抽象构件,并包含具体构件的实例,可以通过其子类扩展具体构件的功能。
具体装饰(ConcreteDecorator)角色:实现抽象装饰的相关方法,并给具体构件对象添加附加的责任。
抽象构件就是一个接口,具体构件是该接口的子类并添加了最基础的职责,而抽象装饰内都有具体构建的实例,并且实现这些实例的职责,同时,抽象装饰的子类具体装饰可以添加职责,在修饰后就相当于先执行父类的职责(即基础职责),在执行新添加的职责。
decorator的应用
static List<T> unmodifiableList(List<T> lst);
static Set<T> unmodifiableSet( Set<T> set);
static Map<K,V> unmodifiableMap( Map<K,V> map);
3.Behavioral patterns 行为模式
3.1strategy 整体地替换算法
针对特定任务存在多种算法,调用者需要根据上下文环境动态的选择和切换。
定义一个算法的接口,每个算法用一个类来实现,客户端针对接口编写程序。
有多种不同的算法来实现同一个任务,但需要client根据需要动态切换算法,而不是写死在代码里
为不同的实现算法构造抽象接口,利用delegation,运行时动态传入client倾向的算法类实例
3.2Template Method
不同的客户端具有相同的算法步骤,但是每个步骤的具体实现不同。
子类中进行各步骤的具体实现
比较:3.1委托;3.2继承+重写
3.3Visitor Pattern
对特定类型的object的特定操作(visit),在运行时将二者动态绑定到一起,该操作可以灵活更改,无需更改被visit的类
访问者模式实际做的是创建一个使用其他类中数据的外部类。
如果操作逻辑发生变化,那么我们只需要在visitor实现中进行更改,而不是在所有的item类中进行更改。
本质上:将数据和作用于数据上的某种/些特定操作分离开来。