开闭原则就是说对扩展开放,对修改关闭。在程序需要进行拓展的时候,不能去修改原有的代码,实现一个热插拔的效果。
可以这样理解:(1)子类的能力必须大于等于父类,即父类可以使用的方法,子类都可以使用。(2)返回值也是同样的道理。假设一个父类方法返回一个List,子类返回一个ArrayList,这当然可以。如果父类方法返回一个ArrayList,子类返回一个List,就说不通了。这里子类返回值的能力是比父类小的。(3)还有抛出异常的情况。任何子类方法可以声明抛出父类方法声明异常的子类。
而不能声明抛出父类没有声明的异常。
这个是开闭原则的基础,具体内容:面向接口编程,依赖于抽象而不依赖于具体。
这个原则的意思是:使用多个隔离的接口,比使用单个接口要好。还是一个降低类之间的耦合度的意思,从这儿我们看出,其实设计模式就是一个软件的设计思想,从大型软件架构出发,为了升级和维护方便。所以上文中多次出现:降低依赖,降低耦合。
为什么叫最少知道原则,就是说:一个实体应当尽量少的与其他实体之间发生相互作用,使得系统功能模块相对独立。
原则是尽量使用合成/聚合的方式,而不是使用继承。
保证一个类只有一个实例,并提供一个访问它的全局访问点。
使用场景:如提供一个唯一的序列生成器或者资源管理器,或者考虑资源消耗太大仅需一个对象。
单例模式类型:饿汉式单例,懒汉式单例
特点:private构造方法 + public getInstance方法
Singleton(饿汉模式):特点是程序加载类的时候比较慢,但运行时获得对象的速度比较快,它从加载到应用结束会一直占用资源
Singleton(懒汉模式):程序是运行时获得对象的速度比较慢,但加载类的时候比较快
它在整个应用的生命周期只有一部分时间在占用资源
// 饿汉式
class Singleton1{
private static final Singleton1 instance = new Singleton1(); //在内部准备好一个对象
public static Singleton1 getInstance(){
return instance;
}
private Singleton1(){}
public void show(){
System.out.println("Singleton1");
}
}
// 懒汉式
class Singleton2 {
private static Singleton2 instance; //将instance传递到外部去
public static Singleton2 getInstance(){
if(instance == null){
instance = new Singleton2();
}
return instance;
}
private Singleton2(){}
}
public class Main {
public static void main(String[] args) {
Singleton1 s1 = Singleton1.getInstance();
Singleton1 s2 = Singleton1.getInstance();
System.out.println(s1==s2); //true
Singleton2 s3 = Singleton2.getInstance();
Singleton2 s4 = Singleton2.getInstance();
System.out.println(s3==s4); //true
}
}
优点:
1, 解耦:对象的创建和使用分开。class A想调用class B的方法,无需感知B如何实例化,创建的工作交给工厂类。
2,代码复用。对象B的创建在工厂类里统一管理,也方便后续修改和维护
3,符合迪米特法则和单一职责。使用者只负责使用产品,无需感知创建逻辑
如我们设计一个Shape工厂类,让子类决定实例化圆形或者矩形类。
// Shape.java
public interface Shape {
void draw();
}
//Circle.java
public class Circle implements Shape {
@Override
public void draw() {
System.out.println("Inside Circle::draw() method.");
}
}
//Rectangle.java
public class Rectangle implements Shape {
@Override
public void draw() {
System.out.println("Inside Rectangle::draw() method.");
}
}
// ShapeFactory.java
public class ShapeFactory {
//use getShape method to get object of type shape
public Shape getShape(String shapeType){
if(shapeType == null){
return null;
}
if(shapeType.equalsIgnoreCase("CIRCLE")){
return new Circle();
} else if(shapeType.equalsIgnoreCase("RECTANGLE")){
return new Rectangle();
}
return null;
}
}
public class Main {
public static void main(String[] args) {
ShapeFactory shapeFactory = new ShapeFactory();
//get an object of Circle and call its draw method.
Shape shape1 = shapeFactory.getShape("CIRCLE");
shape1.draw();
//get an object of Rectangle and call its draw method.
Shape shape2 = shapeFactory.getShape("RECTANGLE");
shape2.draw();
}
}
提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们的具体类.
抽象工厂模式,也称为工厂的工厂,有一个工厂创建其他工厂。当使用抽象工厂模式时,我们首先使用超级工厂创建工厂,然后使用创建的工厂创建对象。下面我们将要创建形状和打印机。对于形状,我们会有圆形,和矩形。对于打印机,我们将有纸张打印机和网络打印机
abstract class AbstractFactory {
abstract Shape getShape(String shape) ;
abstract Printer getPrinter(String type);
}
class ShapeFactory extends AbstractFactory {
@Override
public Shape getShape(String shapeType){
if(shapeType == null){
return null;
}
if(shapeType.equalsIgnoreCase("CIRCLE")){
return new Circle();
} else if(shapeType.equalsIgnoreCase("RECTANGLE")){
return new Rectangle();
}
return null;
}
@Override
public Printer getPrinter(String type) {
return null;
}
}
class PrinterFactory extends AbstractFactory {
@Override
public Shape getShape(String shapeType){
return null;
}
@Override
public Printer getPrinter(String type) {
if(type == null){
return null;
}
if(type.equalsIgnoreCase("paper")){
return new PaperPrinter();
} else if(type.equalsIgnoreCase("web")){
return new WebPrinter();
}
return null;
}
}
class FactoryProducer {
public static AbstractFactory getFactory(String choice){
if(choice.equalsIgnoreCase("SHAPE")){
return new ShapeFactory();
} else if(choice.equalsIgnoreCase("Printer")){
return new PrinterFactory();
}
return null;
}
}
public class Main {
public static void main(String[] args) {
//get shape factory
AbstractFactory shapeFactory = FactoryProducer.getFactory("SHAPE");
//get an object of Shape Circle
Shape shape1 = shapeFactory.getShape("CIRCLE");
shape1.draw();
Shape shape2 = shapeFactory.getShape("RECTANGLE");
shape2.draw();
//get printer factory
AbstractFactory printerFactory = FactoryProducer.getFactory("printer");
Printer printer1 = printerFactory.getPrinter("Paper");
printer1.print();
Printer printer2 = printerFactory.getPrinter("Web");
printer2.print();
}
}
生成器模式用于使用简单对象创建复杂对象。它从小而简单的对象逐步创建更大的对象。
例如,当创建一个图形,我们需要创建一个圆,一个矩形,然后添加圆和矩形到图形。
我们可以使用构建器模式来隐藏如何创建图形的实现。
class MainPicture {
Circle circle;
Rectangle rectangle;
public void getCircle() {
circle.draw();
}
public void setCircle(Circle circle) {
this.circle = circle;
}
public void getRectangle() {
rectangle.draw();
}
public void setRectangle(Rectangle rectangle) {
this.rectangle = rectangle;
}
}
class PictureBuilder{
public static MainPicture createPicture(){
MainPicture picture = new MainPicture();
Circle circle = new Circle();
Rectangle rectangle = new Rectangle();
picture.setCircle(circle);
picture.setRectangle(rectangle);
return picture;
}
}
public class Main {
public static void main(String[] args) {
MainPicture object = PictureBuilder.createPicture();
object.getCircle();
object.getRectangle();
}
}
在原型模式中,将返回一个现有对象的克隆,而不是创建新的对象。
原型模式有助于创建具有更好性能的重复对象。
import java.util.*;
// 首先创建一个Shape抽象类,实现Cloneable接口
abstract class Shape implements Cloneable {
protected String type;
abstract void draw();
public String getType(){
return type;
}
public Object clone() {
Object clone = null;
try {
clone = super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return clone;
}
}
// 然后创建2个具体的类扩展Shape类
class Circle extends Shape {
public Circle(){
type = "Circle";
}
@Override
public void draw() {
System.out.println("Inside Circle::draw() method.");
}
}
class Rectangle extends Shape {
public Rectangle(){
type = "Rectangle";
}
@Override
public void draw() {
System.out.println("Inside Rectangle::draw() method.");
}
}
class ShapeProtoType{
private static Hashtable<String, Shape> shapeMap
= new Hashtable<String, Shape>();
public static void loadCache() {
Circle circle = new Circle();
shapeMap.put("1", circle);
Rectangle rectangle = new Rectangle();
shapeMap.put("2", rectangle);
}
public static Shape getShape(String shapeId) {
Shape cachedShape = shapeMap.get(shapeId);
return (Shape) cachedShape.clone();
}
}
public class Main{
public static void main(String[] args) {
ShapeProtoType.loadCache();
Shape clonedShape = (Shape) ShapeProtoType.getShape("1");
System.out.println("Shape : " + clonedShape.getType());
clonedShape.draw();
Shape clonedShape2 = (Shape) ShapeProtoType.getShape("2");
System.out.println("Shape : " + clonedShape2.getType());
clonedShape2.draw();
}
}
提供一个方法顺序访问一个聚合对象的各个元素,而又不需要暴露该对象的内部表示。
定义对象间一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知自动更新。
定义一个操作中的算法的骨架,而将一些步骤延迟到子类中,TemplateMethod使得子类可以不改变一个算法的结构即可以重定义该算法得某些特定步骤。
将一个请求封装为一个对象,从而使你可以用不同的请求对客户进行参数化,对请求排队和记录请求日志,以及支持可撤销的操作。
允许对象在其内部状态改变时改变他的行为。对象看起来似乎改变了他的类。
定义一系列的算法,把他们一个个封装起来,并使他们可以互相替换,本模式使得算法可以独立于使用它们的客户。
使多个对象都有机会处理请求,从而避免请求的送发者和接收者之间的耦合关系
用一个中介对象封装一些列的对象交互。
表示一个作用于某对象结构中的各元素的操作,它使你可以在不改变各元素类的前提下定义作用于这个元素的新操作。
给定一个语言,定义他的文法的一个表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。
在不破坏对象的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。
将对象组合成树形结构以表示部分整体的关系,Composite使得用户对单个对象和组合对象的使用具有一致性。
为子系统中的一组接口提供一致的界面,fa?ade提供了一高层接口,这个接口使得子系统更容易使用。
为其他对象提供一种代理以控制对这个对象的访问
将一类的接口转换成客户希望的另外一个接口,Adapter模式使得原本由于接口不兼容而不能一起工作那些类可以一起工作。
动态地给一个对象增加一些额外的职责,就增加的功能来说,Decorator模式相比生成子类更加灵活。
将抽象部分与它的实现部分相分离,使他们可以独立的变化。