常见的设计模式(资料:《设计模式》,青岛东合信息技术有限公司编著,电子工业出版社出版,ISBN:978-7-121-15582-6)
例子代码:https://github.com/Youyou-0826/disign_pattern.git
1. 单一职责原则(single reposibility principle)
定义类时必须考虑职责与对象之间的关系。
2. 里氏替换原则(Liskov substitution principle)
使用基类的地方,子类一定适用。
①子类必须完全实现父类的方法;
②子类可以有自己的个性
③覆盖或实现父类的方法时输入参数可以被放大;
④覆盖或实现父类的方法时输出结果可以被缩小。
策略模式,组合模式,代理模式体现了“里氏替换原则”。
3. 依赖倒置原则(dependence inversion principle)
①模块间的依赖通过抽象发生,实现类之间不发生直接的依赖关系,其依赖是通过接口或抽象类发生的;
②接口或抽象类不依赖于实现类;
③实现类依赖于就扣或抽象类。
4. 接口隔离原则(interface segregation principle)
只提供调用者需要的方法,屏蔽不需要的方法。
应尽量使用原子接口和原子类:
①一个借口只对一个子模块或者业务逻辑进行服务;
②只保留接口中业务逻辑需要的public方法;
③尽量修改污染了的接口,若修改的风险较大,这可才使用适配器模式进行转化处理;
5. 迪米特法则(law of demeter)
一个对象应当其他对象尽可能少的了解。
外观模式,中介者模式体现了迪米特原则。
6. 开闭原则(open-closed principle)
软件实体应当对扩展开放,对修改关闭。
一. 单例模式
确保一个类中只有一个实例,而且自行实例化并向整个系统提供这个实例。
①饿汉式单例:类加载时就进行对象实例化。
public class Singleton {
private static Singleton instance = new Singleton();
//构造方法私有,外界无法直接实例化
private Singleton() {
}
public static Singleton getInstance() {
return instance;
}
}
②懒汉式单例:第一次引用类时才进行对象实例化,更符合java语言的特点。
public class Singleton {
private static Singleton instance = null;
private Singleton() {
}
synchroinzed public static Singleton getInstance() {
if(instance == null) {
instance = new Singleton();
}
return instance;
}
}
使用单例模式的场景:
要求生成唯一的序列号,web网页的计数器,IO资源和数据库访问,需要频繁使用的工具类等。
二. 工厂方法
定义一个创建产品对象的工厂接口,将实际创建性工作推迟到子类中。
定义一个用于创建对象的接口,让子类实例化哪个类。
public interface Creator {
/**
*工厂方法
*创建一个产品对象,输入参数可以自行设置
*/
public <T extends Product> T factory(Class<T> c);
}
public interface Product {
//产品类的公共方法
public void method1();
public void method2();
}
public class ConcreteCreator implements Creator {
public <T extends Product> T factory(Class<T> c) {
Product product = null;
try{
product = (Product) Class.forName(c.getName()).newInstance();
}catch(Exception e) {
}
return (T) product;
}
}
public class ConcreteProduct implements Product {
public void method1() {
//公共业务处理
}
public method2() {
//业务处理逻辑
}
}
三. 抽象工厂
为创建一组相关或相互依赖的对象提供一个接口,而且无需指定他们的具体类。在有多个业务品种,业务分类时,通过抽象工厂产生所需对象是一种很好的解决方式。
public interface AbstractFactory {
//创建产品A
public ProductA factoryA();
//创建产品B
public ProductB factoryB();
}
public class ConcreteFactory1 implements AbstractFactory {
//创建等级为1的产品A
public ProductA factoryA() {
return new ProductA1();
}
//创建等级为1的产品B
public ProductB factoryB() {
return new ProductB1();
}
}
public class ConcreteFactory2 implements AbstractFactory {
//创建等级为2的产品A
public ProductA factoryA() {
return new ProductA2();
}
//创建等级为2的产品B
public ProductB factoryB() {
return new ProductB2();
}
}
public interface ProductA {
//产品A的方法
public void method1();
public void method2();
}
public class ProductA1 implements ProductA {
public void method1() {
//等级为1的产品A
}
public void method2() {
//业务逻辑
}
}
public class ProductA2 implements ProductA {
public void method1() {
//等级为2的产品A
}
public void method2() {
//业务逻辑
}
}
四. 建造者模式
将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
public class Product {
//产品业务处理方法
}
public abstract class Builder {
//设置产品的不同部分以获得不同产品
public abstract void setPart1();
public abstract void setPart2();
public abstract void setPart3();
//其他部分
//建造产品
public abstract Product builderProduct();
}
public class ConcreteBuilder extends Builder {
private Product product = new Product();
//设置产品零件
public void setPart1() {
//设置part1
}
public void setPart2() {
//设置part2
}
public void setPart3() {
//设置part3
}
//生产一个产品
public Product builderProduct() {
return product;
}
}
public class Director {
private Builder builder = new ConcreteBuilder();
//构造产品,负责调用各个零件构造方法
public Product build() {
builder.setPart1();
builder.setPart2();
builder.setPart3();
//其他部件
return builder.builderProduct();
}
}
建造者模式的使用场景:产品类复杂,多个部件和零件多可装到同一个对象中,产生结果不同,多个方法,不同调用顺序产生不同结果。
五. 原型模式
用原型实例指定创建对象的种类,并且通过复制这些原型创建新的对象。
public interface ClientDemo extends Cloneable {
//克隆方法
Prototype clone();
}
public class ConcretePrototype implements Prototype {
public Prototype clone() {
try {
return (Prototype) super.clone();
}catch(CloneNotSupportedException e) {
e.printStackTrace();
return null;
}
}
}
public class Client {
public void operation(Prototype example) {
//得到example的副本
Prototype p = example.clone();
}
}
原型模式的使用场景:
资源优化场景,性能和安全要求场景,一个对象多个修改者的场景。
六. 代理模式
为其他对象提供一种代理以控制对这个对象的访问。
public interface Subject {
//定义一个请求方法
public void request();
}
public class RealSubject implements Subject {
private void request() {
//具体业务逻辑
}
}
public class ProxySubject implements Subject {
private Subject subject;
public ProxySubject(Subject subject) {
this.subject = subject;
}
//实现请求方法
public void request() {
this.beforeRequest();
this.request();
this.afterRequest();
}
//实现请求前的操作
private void beforeRequest() {
//预处理
}
//请求后的操作
private void afterRequest() {
//善后处理
}
}
代理模式的优点:职责清晰,高扩展性,智能化,是一种很常用的模式
七. 装饰模式
动态的给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更为灵活。
抽象构件角色
具体构件角色
装饰角色
具体装饰角色
public interface Compontent {
public void operation();
}
public class ConcreteComponent implements Compontent {
public void operation() {
//具体业务
}
}
public abstract class Decorator implements Component {
private Component component = null;
public Decorator(Component component) {
this.component = component;
}
public void operation() {
this.component.operation();
}
}
public class ConcreteDecorator extends Decorator {
public ConcreteDecorator(Component component) {
super(component);
}
//定义自己的方案
private void method() {
System.out.println("decoration...");
}
//重写operation方法
public void operation() {
this.method();
super.operation();
}
}
public class Client {
public static void main(String[] args) {
Component component = new ConcreteComponent();
//进行装饰
component = new ConcreteComponent(component);
component.operation();
}
}
八. 适配器模式
将一个类接口变换成客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起工作的两个类能够在一起工作。
涉及源,目标角色和适配器角色。
public class Adaptee {
//原有的业务处理逻辑
public void specificRequest() {
}
}
public interface Target {
public void request() {
}
}
public class Adapter extends Adaptee implements Target {
public void request() {
super.specificRequest();
}
}
public class Client {
public static void main(String[] args) {
//适配器模式的应用
Target target = new Adapter();
target.request();
}
}
九. 外观模式
要求子系统的外部与其内部的通信必须通过一个统一的对象进行,外观模式提供一个高层次的接口,使得子系统容易使用。
public class ClassA {
public void methodA() {
}
}
public class ClassB {
public void methodB() {
}
}
public class ClassC {
public void methodC() {
}
}
public class Facade {
//被委托的对象
private ClassA a = new ClassA();
private ClassB b = new ClassB();
private ClassC c = new ClassC();
//提供临界的方法
public void methodA() {
a.methodA();
}
public void methodB() {
b.methodB();
}
public void methodC() {
c.methodC();
}
}
十. 模板方法
定义一个操作中的算法的框架,而将一些步骤延迟到子类中,使得子类可以改变一个算法的结构,即可定义该算法的某些特定步骤。
public abstract class AbstractClass {
//基本方法
protected abstract void operation();
//模板方法
public void templateMethod() {
//调用基本方法,完成相关逻辑
this.operation();
}
}
public class ConcreteClass extends AbstractClass {
//实现基本业务方法
protected void operation() {
//业务逻辑
}
}
public class Client {
public static void main(String[] args) {
AbstractClass abstractClass = new ConcreteClass();
//调用模板方法
abstractClass.templateMethod();
}
}
十一. 策略模式
定义一组算法,将每个方法都封装起来,并且使他们之间可以互换。
其用意是针对一组算法,将每一个算法封装到具有共同接口的独立的类中,从而使得它们可以相互替换,使得算法可以在不影响客户端的情况下发生变化。
public abstract class Strategy {
//策略方法
public abstract void strategyInterface();
}
//具体策略类
public class ConcreteStrategy extends Strategy {
//实现策略方法
public void strategyInterface() {
//具体算法
}
}
public class Context {
private Strategy strategy = null;
//构造函数
public Context(Strategy strategy) {
this.strategy = strategy;
}
//策略方法
public void contextInterface() {
this.strategy.strategyInterface();
}
}
十二. 迭代器模式
提供一种方法访问一个容器对象中各个元素,而又不暴露该对象的内部细节。
public interface Iterator {
public Object next();
public boolean hasNext();
}
public class ConcreteIterator implements Iterator {
private ConcreteAggregate agg;
private int index = 0;
private int size = 0;
public ConcreteIterator(ConcreteAggregate agg) {
this.agg = agg;
size = agg.size();
index = 0;
}
public boolean hasNext() {
return index < size;
}
public Object next() {
if(index < size) {
return agg.getElement(index++);
} else {
return null;
}
}
}
public interface Aggregate {
public void add(Object obj);
public Iterator creatIterator();
}
public class ConcreteAggregate implements Aggregate {
private Vector vector = new Vector();
public void add(Object object) {
this.vector.add(object);
}
public Object getElement(int index) {
if(index < vector.size()) {
return vector.get(index);
} else {
return null;
}
}
public int size() {
return vector.size();
}
public Iterator creatIterator() {
return new ConcreteIterator(this);
}
}
十三. 观察者模式
定义对象间一种一对多的依赖关系,使得每当一个对象改变状态时,则所有依赖于它的对象都会得到通知并被自动更新。
public interface Subject {
public void attach(Observer observer);
public void detach(Observer observer);
public void notifyObserver();
}
public interface Observer {
public void update();
}
public class ConcreteSubject implements Subject {
private Vector<Observer> obsVector = new Vector<Observer>();
public void attach(Observer observer) {
obsVector.add(observer);
}
public void detach(Observer observer) {
obsVector.remove(observer);
}
public void notifyObserver() {
for(Observer obs : obsVector) {
obs.update();
}
}
public Enumeration<Observer> observers() {
return obsVector.elements();
}
public void change() {
this.notifyObserver();
}
}
public class ConcreteObserver implements Observer {
//实现更新方法
public void update() {
System.out.println("updated...");
}
}
public class Client {
public static void main(String[] args) {
ConcreteSubject subject = new ConcreteSubject();
Observer observer = new ConcreteObserver();
subject.attach(observer);
subject.change();
}
}
例子代码:https://github.com/Youyou-0826/disign_pattern.git
1. 单一职责原则(single reposibility principle)
定义类时必须考虑职责与对象之间的关系。
2. 里氏替换原则(Liskov substitution principle)
使用基类的地方,子类一定适用。
①子类必须完全实现父类的方法;
②子类可以有自己的个性
③覆盖或实现父类的方法时输入参数可以被放大;
④覆盖或实现父类的方法时输出结果可以被缩小。
策略模式,组合模式,代理模式体现了“里氏替换原则”。
3. 依赖倒置原则(dependence inversion principle)
①模块间的依赖通过抽象发生,实现类之间不发生直接的依赖关系,其依赖是通过接口或抽象类发生的;
②接口或抽象类不依赖于实现类;
③实现类依赖于就扣或抽象类。
4. 接口隔离原则(interface segregation principle)
只提供调用者需要的方法,屏蔽不需要的方法。
应尽量使用原子接口和原子类:
①一个借口只对一个子模块或者业务逻辑进行服务;
②只保留接口中业务逻辑需要的public方法;
③尽量修改污染了的接口,若修改的风险较大,这可才使用适配器模式进行转化处理;
5. 迪米特法则(law of demeter)
一个对象应当其他对象尽可能少的了解。
外观模式,中介者模式体现了迪米特原则。
6. 开闭原则(open-closed principle)
软件实体应当对扩展开放,对修改关闭。
一. 单例模式
确保一个类中只有一个实例,而且自行实例化并向整个系统提供这个实例。
①饿汉式单例:类加载时就进行对象实例化。
public class Singleton {
private static Singleton instance = new Singleton();
//构造方法私有,外界无法直接实例化
private Singleton() {
}
public static Singleton getInstance() {
return instance;
}
}
②懒汉式单例:第一次引用类时才进行对象实例化,更符合java语言的特点。
public class Singleton {
private static Singleton instance = null;
private Singleton() {
}
synchroinzed public static Singleton getInstance() {
if(instance == null) {
instance = new Singleton();
}
return instance;
}
}
使用单例模式的场景:
要求生成唯一的序列号,web网页的计数器,IO资源和数据库访问,需要频繁使用的工具类等。
二. 工厂方法
定义一个创建产品对象的工厂接口,将实际创建性工作推迟到子类中。
定义一个用于创建对象的接口,让子类实例化哪个类。
public interface Creator {
/**
*工厂方法
*创建一个产品对象,输入参数可以自行设置
*/
public <T extends Product> T factory(Class<T> c);
}
public interface Product {
//产品类的公共方法
public void method1();
public void method2();
}
public class ConcreteCreator implements Creator {
public <T extends Product> T factory(Class<T> c) {
Product product = null;
try{
product = (Product) Class.forName(c.getName()).newInstance();
}catch(Exception e) {
}
return (T) product;
}
}
public class ConcreteProduct implements Product {
public void method1() {
//公共业务处理
}
public method2() {
//业务处理逻辑
}
}
三. 抽象工厂
为创建一组相关或相互依赖的对象提供一个接口,而且无需指定他们的具体类。在有多个业务品种,业务分类时,通过抽象工厂产生所需对象是一种很好的解决方式。
public interface AbstractFactory {
//创建产品A
public ProductA factoryA();
//创建产品B
public ProductB factoryB();
}
public class ConcreteFactory1 implements AbstractFactory {
//创建等级为1的产品A
public ProductA factoryA() {
return new ProductA1();
}
//创建等级为1的产品B
public ProductB factoryB() {
return new ProductB1();
}
}
public class ConcreteFactory2 implements AbstractFactory {
//创建等级为2的产品A
public ProductA factoryA() {
return new ProductA2();
}
//创建等级为2的产品B
public ProductB factoryB() {
return new ProductB2();
}
}
public interface ProductA {
//产品A的方法
public void method1();
public void method2();
}
public class ProductA1 implements ProductA {
public void method1() {
//等级为1的产品A
}
public void method2() {
//业务逻辑
}
}
public class ProductA2 implements ProductA {
public void method1() {
//等级为2的产品A
}
public void method2() {
//业务逻辑
}
}
四. 建造者模式
将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
public class Product {
//产品业务处理方法
}
public abstract class Builder {
//设置产品的不同部分以获得不同产品
public abstract void setPart1();
public abstract void setPart2();
public abstract void setPart3();
//其他部分
//建造产品
public abstract Product builderProduct();
}
public class ConcreteBuilder extends Builder {
private Product product = new Product();
//设置产品零件
public void setPart1() {
//设置part1
}
public void setPart2() {
//设置part2
}
public void setPart3() {
//设置part3
}
//生产一个产品
public Product builderProduct() {
return product;
}
}
public class Director {
private Builder builder = new ConcreteBuilder();
//构造产品,负责调用各个零件构造方法
public Product build() {
builder.setPart1();
builder.setPart2();
builder.setPart3();
//其他部件
return builder.builderProduct();
}
}
建造者模式的使用场景:产品类复杂,多个部件和零件多可装到同一个对象中,产生结果不同,多个方法,不同调用顺序产生不同结果。
五. 原型模式
用原型实例指定创建对象的种类,并且通过复制这些原型创建新的对象。
public interface ClientDemo extends Cloneable {
//克隆方法
Prototype clone();
}
public class ConcretePrototype implements Prototype {
public Prototype clone() {
try {
return (Prototype) super.clone();
}catch(CloneNotSupportedException e) {
e.printStackTrace();
return null;
}
}
}
public class Client {
public void operation(Prototype example) {
//得到example的副本
Prototype p = example.clone();
}
}
原型模式的使用场景:
资源优化场景,性能和安全要求场景,一个对象多个修改者的场景。
六. 代理模式
为其他对象提供一种代理以控制对这个对象的访问。
public interface Subject {
//定义一个请求方法
public void request();
}
public class RealSubject implements Subject {
private void request() {
//具体业务逻辑
}
}
public class ProxySubject implements Subject {
private Subject subject;
public ProxySubject(Subject subject) {
this.subject = subject;
}
//实现请求方法
public void request() {
this.beforeRequest();
this.request();
this.afterRequest();
}
//实现请求前的操作
private void beforeRequest() {
//预处理
}
//请求后的操作
private void afterRequest() {
//善后处理
}
}
代理模式的优点:职责清晰,高扩展性,智能化,是一种很常用的模式
七. 装饰模式
动态的给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更为灵活。
抽象构件角色
具体构件角色
装饰角色
具体装饰角色
public interface Compontent {
public void operation();
}
public class ConcreteComponent implements Compontent {
public void operation() {
//具体业务
}
}
public abstract class Decorator implements Component {
private Component component = null;
public Decorator(Component component) {
this.component = component;
}
public void operation() {
this.component.operation();
}
}
public class ConcreteDecorator extends Decorator {
public ConcreteDecorator(Component component) {
super(component);
}
//定义自己的方案
private void method() {
System.out.println("decoration...");
}
//重写operation方法
public void operation() {
this.method();
super.operation();
}
}
public class Client {
public static void main(String[] args) {
Component component = new ConcreteComponent();
//进行装饰
component = new ConcreteComponent(component);
component.operation();
}
}
八. 适配器模式
将一个类接口变换成客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起工作的两个类能够在一起工作。
涉及源,目标角色和适配器角色。
public class Adaptee {
//原有的业务处理逻辑
public void specificRequest() {
}
}
public interface Target {
public void request() {
}
}
public class Adapter extends Adaptee implements Target {
public void request() {
super.specificRequest();
}
}
public class Client {
public static void main(String[] args) {
//适配器模式的应用
Target target = new Adapter();
target.request();
}
}
九. 外观模式
要求子系统的外部与其内部的通信必须通过一个统一的对象进行,外观模式提供一个高层次的接口,使得子系统容易使用。
public class ClassA {
public void methodA() {
}
}
public class ClassB {
public void methodB() {
}
}
public class ClassC {
public void methodC() {
}
}
public class Facade {
//被委托的对象
private ClassA a = new ClassA();
private ClassB b = new ClassB();
private ClassC c = new ClassC();
//提供临界的方法
public void methodA() {
a.methodA();
}
public void methodB() {
b.methodB();
}
public void methodC() {
c.methodC();
}
}
十. 模板方法
定义一个操作中的算法的框架,而将一些步骤延迟到子类中,使得子类可以改变一个算法的结构,即可定义该算法的某些特定步骤。
public abstract class AbstractClass {
//基本方法
protected abstract void operation();
//模板方法
public void templateMethod() {
//调用基本方法,完成相关逻辑
this.operation();
}
}
public class ConcreteClass extends AbstractClass {
//实现基本业务方法
protected void operation() {
//业务逻辑
}
}
public class Client {
public static void main(String[] args) {
AbstractClass abstractClass = new ConcreteClass();
//调用模板方法
abstractClass.templateMethod();
}
}
十一. 策略模式
定义一组算法,将每个方法都封装起来,并且使他们之间可以互换。
其用意是针对一组算法,将每一个算法封装到具有共同接口的独立的类中,从而使得它们可以相互替换,使得算法可以在不影响客户端的情况下发生变化。
public abstract class Strategy {
//策略方法
public abstract void strategyInterface();
}
//具体策略类
public class ConcreteStrategy extends Strategy {
//实现策略方法
public void strategyInterface() {
//具体算法
}
}
public class Context {
private Strategy strategy = null;
//构造函数
public Context(Strategy strategy) {
this.strategy = strategy;
}
//策略方法
public void contextInterface() {
this.strategy.strategyInterface();
}
}
十二. 迭代器模式
提供一种方法访问一个容器对象中各个元素,而又不暴露该对象的内部细节。
public interface Iterator {
public Object next();
public boolean hasNext();
}
public class ConcreteIterator implements Iterator {
private ConcreteAggregate agg;
private int index = 0;
private int size = 0;
public ConcreteIterator(ConcreteAggregate agg) {
this.agg = agg;
size = agg.size();
index = 0;
}
public boolean hasNext() {
return index < size;
}
public Object next() {
if(index < size) {
return agg.getElement(index++);
} else {
return null;
}
}
}
public interface Aggregate {
public void add(Object obj);
public Iterator creatIterator();
}
public class ConcreteAggregate implements Aggregate {
private Vector vector = new Vector();
public void add(Object object) {
this.vector.add(object);
}
public Object getElement(int index) {
if(index < vector.size()) {
return vector.get(index);
} else {
return null;
}
}
public int size() {
return vector.size();
}
public Iterator creatIterator() {
return new ConcreteIterator(this);
}
}
十三. 观察者模式
定义对象间一种一对多的依赖关系,使得每当一个对象改变状态时,则所有依赖于它的对象都会得到通知并被自动更新。
public interface Subject {
public void attach(Observer observer);
public void detach(Observer observer);
public void notifyObserver();
}
public interface Observer {
public void update();
}
public class ConcreteSubject implements Subject {
private Vector<Observer> obsVector = new Vector<Observer>();
public void attach(Observer observer) {
obsVector.add(observer);
}
public void detach(Observer observer) {
obsVector.remove(observer);
}
public void notifyObserver() {
for(Observer obs : obsVector) {
obs.update();
}
}
public Enumeration<Observer> observers() {
return obsVector.elements();
}
public void change() {
this.notifyObserver();
}
}
public class ConcreteObserver implements Observer {
//实现更新方法
public void update() {
System.out.println("updated...");
}
}
public class Client {
public static void main(String[] args) {
ConcreteSubject subject = new ConcreteSubject();
Observer observer = new ConcreteObserver();
subject.attach(observer);
subject.change();
}
}