设计模式
设计模式是一种解决方案,用于解决软件设计中普遍存在的问题,是前辈对之前软件设计中反复出现的问题的一个总结。
我们学习设计模式,是为了学习如何合理的组织我们的代码,如何解耦,如何真正的达到对修改封闭对扩展开放的效果,而不是去背诵那些类的继承模式,然后自己记不住,回过头来就骂设计模式把你的代码搞复杂了,要反设计模式。
1.设计模式六要素
1.1单一职责原则(Single Responsibility Principle,SRP)
一个类只负责一个功能领域中的相应职责,或者可以定义为:就一个类而言,应该只有一个引起它变化的原因。
单一职责原则要求一个类不能承担过多的职责,形成“超级类”。需要根据不同职责分为不同的类,从而降低类的复杂度,提升其可读性,增加系统的稳定性。
1.2开闭原则(Open-Closed Principle,OCP)
一个软件实体应当对扩展开放,对修改关闭。即软件实体应尽量在不修改原有代码的情况下进行扩展。
很多需求都会随着时间变化而变化,因此当功能需要拓展时,应当能够很方便的进行拓展,拓展时不影响原有代码。
1.3里氏代换原则(Liskov Substitution Principle,LSP)
所有引用基类(父类)的地方必须能透明的使用 其子类的对象。
里氏代换原则要求在软件中一个基类能够替换为它的子类而不会因此任何异常。因此要求子类可以扩展父类的功能,但不能修改父类本身的非抽象方法。
1.4依赖倒置原则(Dependency Inversion Principle,DIP)
抽象不应该依赖于细节,细节应当依赖于抽象。换言之,要针对接口编程,而不是针对实现编程。
依赖倒置原则要求我们在程序代码中尽量引用层次高的抽象层类。因此我们需要针对抽象层编程,将具体类通过依赖注入的方式注入到其他对象中。
在大多数情况下,开闭原则、里氏代换原则和依赖倒置原则会同时出现,开闭原则是目标,里氏代换原则是基础,依赖倒置原则是手段。
1.5接口隔离原则(Interface Segregation Principle,ISP)
使用多个专门的接口,而不使用单一的总接口,即客户端不应该依赖那些它不需要的接口。
接口隔离原则要求我们设计接口不应太大,接口应仅仅提供客户端需要的行为。
在使用此原则时应注意接口的粒度,接口太小会导致接口泛滥,不利于维护,接口太大灵活性较差,使用不便。
1.6迪米特法则(Law of Demeter,LOD)
一个软件实体应当尽可能少地与其他实体发生相互作用。
迪米特法则要求我们应该减少对象之间的交互,如果两个对象之间不必彼此之间直接通信,那么这两个对象就不应该发送任何直接的相互作用,当需要调用另一个对象的某一方法时,可以通过第三者来转发此调用。
2.常见模式
2.1工厂模式(Factory Pattern)[创建型模式]
2.1.1 作用
用于创建复制对象,明确的计划不同条件下创建不同的实例。
2.1.2 优点
使代码结构清晰,能够更加有效的进行封装。对调用者屏蔽具体的产品实现。 降低代码耦合度。
2.1.3 缺点
对于简单对象,使用工厂模式会增加其系统的复杂度。
//产品类接口
interface IProduct {
public void productMethod();
}
//产品类实体
class Product implements IProduct {
public void productMethod() {
System.out.println("产品");
}
}
//工厂类接口
interface IFactory {
public IProduct createProduct();
}
//工厂类实体
class Factory implements IFactory {
public IProduct createProduct() {
return new Product();
}
}
//用户
public class Client {
public static void main(String[] args) {
IFactory factory = new Factory();
IProduct prodect = factory.createProduct();
prodect.productMethod();
}
}
2.2装饰器模式(Decorator Pattern)【结构型模式】
2.2.1 作用
通过一个更加灵活的方式动态的为某一个对象添加一些额外的职责。
2.2.2 优点
可以再不添加很多子类的情况下拓展类,且装饰类和被装饰类可以独立方法。
2.2.3 缺点
多层装饰较为复杂。
//需被拓展的类的接口
public interface Shape {
void draw();
}
//需被拓展的类
public class Rectangle implements Shape {
@Override
public void draw() {
System.out.println("Shape: Rectangle");
}
}
//创建实现了 Shape 接口的抽象装饰类。
public abstract class ShapeDecorator implements Shape {
protected Shape decoratedShape;
public ShapeDecorator(Shape decoratedShape){
this.decoratedShape = decoratedShape;
}
public void draw(){
decoratedShape.draw();
}
}
//扩展了 ShapeDecorator 类的实体装饰类
public class RedShapeDecorator extends ShapeDecorator {
public RedShapeDecorator(Shape decoratedShape) {
super(decoratedShape);
}
@Override
public void draw() {
decoratedShape.draw();
setRedBorder(decoratedShape);
}
private void setRedBorder(Shape decoratedShape){
System.out.println("Border Color: Red");
}
}
2.3 适配器模式
2.3.1 作用
将一个类的接口转换成客户希望的另外一个接口,使得原本接口不兼容的而不能一起工作的类一起工作。
package designMode.adapter;
public interface Window {//定义接口,,定义了很多的方法,但是只需要使用其中个别的方法,就需要使用代理模式了
void open();
void close();
void activated();
void iconified();
void deiconified();
}
package designMode.adapter;
public abstract class WindowAdapter implements Window {//用抽象类实现接口,方法体为空
@Override
public void activated() {
// TODO Auto-generated method stub
}
@Override
public void close() {
// TODO Auto-generated method stub
}
@Override
public void deiconified() {
// TODO Auto-generated method stub
}
@Override
public void iconified() {
// TODO Auto-generated method stub
}
@Override
public void open() {
// TODO Auto-generated method stub
}
}
package designMode.adapter;
import java.awt.event.WindowAdapter;
public class WindowImpl extends WindowAdapter { //实例体继承 抽象类。重写需要的方法
public void open(){
System.out.println("窗口打开");
}
public void close(){
System.out.println("窗口关闭");
}
}
package designMode.adapter;
public class AdapterDemo {
public static void main(String[] args) { //调用接口父类,执行需要的方法,其他的方法没有结果,在公司的eclipse上运行成功了,可是我自己的却不行,不知道是什么原因
Window window = (Window) new WindowImpl();
window.open();
window.close();
window.activated();
System.out.println();
window.iconified();
System.out.println();
window.deiconified();
}
}