设计模式

设计模式需要遵从的原则

       开闭原则:对扩展开放,对修改关闭。其含义是说应该通过扩展来实现变化, 而不是通过修改已有的代码来实现变化。

       里氏代换原则:只有当衍生类可以替换掉基类,软件单位的功能不受到影响时,基类才能真正被复用,而衍生类也能够在基类的基础上增加新的行为。

       依赖倒转原则:这个是开闭原则的基础,对接口编程,依赖于抽象而不依赖于具体。

       接口隔离原则:使用多个隔离的借口来降低耦合度。客户端不应该依赖它不需要的接口,类间的依赖关系应该建立在最小的接口上。

       最少知道原则:一个实体应当尽量少的与其他实体之间发生相互作用,使得系统功能模块相对独立。

       合成复用原则:原则是尽量使用合成/聚合的方式,而不是使用继承。继承实际上破坏了类的封装性,超类的方法可能会被子类修改。

总结:

  • 单一职责原则要求实现类要职责单一;
  • 里氏替换原则要求不要去破坏继承系统;
  • 依赖倒置原则要求面向接口编程;
  • 接口隔离原则要求在设计接口的时候要精简单一;
  • 迪米特法则要求要降低耦合;
  • 开闭原则是总纲,要求对扩展开发,对修改关闭。

 

设计模式常用类型

       创建型模式:工厂方法模式,抽象工厂模式,单例模式,建造者模式,原型模式。

       结构型模式:适配器模式,装饰器模式,代理模式,外观模式,桥接模式,组合模式,享元模式。

       行为型模式:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。

 

1、工厂模式

       常用的工厂模式是静态工厂,利用static方法,作为一种类似于工具类Utils的辅助效果,一般情况下工厂类不需要实例化。

interface Type{}
class A implements Type{}
class B implements Type{}

public class StaticFactory {
    private StaticFactory(){}
    public static Type getA(){  return new A(); }
    public static Type getB(){  return new B(); }
}

class Client{
    // 客户端代码只需要将相应的参数传入即可得到对象
    // 用户不需要了解工厂类内部的逻辑。
    public static void main(String[] args){
        System.out.println(StaticFactory.getA());
        System.out.println(StaticFactory.getB());
    }
}

 

2、抽象工厂模式

       一个基础接口定义了功能,每个实现接口的子类就是产品,然后定义一个工厂接口,实现了工厂接口的就是工厂,这时候,接口编程的优点就出现了,我们可以新增产品类(只需要实现产品接口),只需要同时新增一个工厂类,客户端就可以轻松调用新产品的代码。

       抽象工厂的灵活性就体现在这里,无需改动原有的代码,毕竟对于客户端来说,静态工厂模式在不改动StaticFactory类的代码时无法新增产品,如果采用了抽象工厂模式,就可以轻松的新增拓展类。

interface Type{}
class A implements Type{}
class B implements Type{}

interface Produce{ 
    Type get();
}

class FactoryForA implements Produce{
    @Override
    public Type get() {
        return new A();
    }
}

class FactoryForB implements Produce{
    @Override
    public Type get() {
        return new B();
    }
}

public class AbstractFactory {
    public static void main(String[] args){
	System.out.println(new FactoryForA().get());
	System.out.println(new FactoryForB().get());
    }
}

 

3、单例模式

       在内部创建一个实例,构造器全部设置为private,所有方法均在该实例上改动,在创建上要注意类的实例化只能执行一次,可以采用许多种方法来实现,如Synchronized关键字,或者利用内部类等机制来实现。

       懒汉式(线程不安全,延迟初始化,严格意义上不是单例模式)

public class Singleton {  
    private static Singleton instance;  

    private Singleton (){}  
  
    public static Singleton getInstance() {  
        if (instance == null) {  
            instance = new Singleton();  
        }  
        return instance;  
    }  
}

       饿汉式(线程安全,比较常用,但容易产生垃圾,因为一开始就初始化 )

public class Singleton {  
    private static Singleton instance = new Singleton();  

    private Singleton (){}  

    public static Singleton getInstance() {  
        return instance;  
    }  
}

       双重锁模式(线程安全,延迟初始化。这种方式采用双锁机制,安全且在多线程情况下能保持高性能)

public class Singleton {  
    private volatile static Singleton instance;  

    private Singleton (){}  

    public static Singleton getSingleton() {  
        if (instance == null) {  
            synchronized (Singleton.class) {  
                if (instance == null) {  
                    instance = new Singleton();  
                }  
            }  
        }  
        return instance;  
    }  
}

 

4、建造者模式

public class Builder {
    static class Student{
        String name = null;
        int number = -1;
        String sex = null;
        int age = -1;
        String school = null;

     // 构建器,利用构建器作为参数来构建Student对象
        static class StudentBuilder{
            String name = null;
            int number = -1;
            String sex = null;
            int age = -1;
            String school = null;
            public StudentBuilder setName(String name) {
                this.name = name;
                return  this;
            }
            public StudentBuilder setNumber(int number) {
                this.number = number;
                return  this;
            }
            public StudentBuilder setSex(String sex) {
                this.sex = sex;
                return  this;
            }
            public StudentBuilder setAge(int age) {
                this.age = age;
                return  this;
            }
            public StudentBuilder setSchool(String school) {
                this.school = school;
                return  this;
            }
            public Student build() {
                return new Student(this);
            }
        }

        public Student(StudentBuilder builder){
            this.age = builder.age;
            this.name = builder.name;
            this.number = builder.number;
            this.school = builder.school;
            this.sex = builder.sex;
        }
    }

    public static void main( String[] args ){
        Student a = new Student.StudentBuilder().setAge(13).setName("LiHua").build();
        Student b = new Student.StudentBuilder().setSchool("sc").setSex("Male").setName("ZhangSan").build();
    }
}

 

5、原型模式

       原型模式就是讲一个对象作为原型,使用clone()方法来创建新的实例。

public class Prototype implements Cloneable{
    private String name;

    public String getName() { 
        return name; 
    }

    public void setName(String name) { 
        this.name = name; 
    }

    @Override
    protected Object clone()   {
        try {
            return super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
            return null;
        }
    }

    public static void main ( String[] args){
        Prototype pro = new Prototype();
	Prototype pro_copy = (Prototype)pro.clone();
	System.out.println(pro_copy);
    }
}

 

6、观察者模式

      定义对象间一种一对多的依赖关系,使得每当一个对象改变状态,则所有依赖它的对象都会得到通知并自动更新。

// 实现了维护装有观察者引用集合的功能。
public class Subject {
    // 保存注册的观察者对象
    private List<Observer> mObervers = new ArrayList<>();

    // 注册观察者对象
    public void attach(Observer observer) {
        mObervers.add(observer);
    }

    // 注销观察者对象
    public void detach(Observer observer) {
        mObervers.remove(observer);
    }

    // 通知所有注册的观察者对象
    public void notifyEveryOne(String newState) {
        for (Observer observer : mObervers) {
            observer.update(newState);
        }
    }
}


// 观察者
public class ConcreteSubject extends Subject {
    private String state;

    public String getState() {
        return state;
    }

    public void change(String newState) {
        state = newState;

        // 状态发生改变,通知观察者
        notifyEveryOne(newState);
    }
}

// 抽象出了一个及时更新的方法
interface Observer {
    void update(String newState);
}

// 观察者
public class ObserverA implements Observer {
    // 观察者状态
    private String observerState;

    @Override
    public void update(String newState) {
        // 更新观察者状态,让它与目标状态一致
        observerState = newState;
    }
}

// 观察者
public class ObserverB implements Observer {
    // 观察者状态
    private String observerState;

    @Override
    public void update(String newState) {
        // 更新观察者状态,让它与目标状态一致
        observerState = newState;
    }
}

 

7、装饰模式

       给一类对象增加新的功能,装饰方法与具体的内部逻辑无关。

interface Source{ 
    void method();
}

public class Decorator implements Source{
    private Source source;

    public void decotate1(){
        System.out.println("decorate");
    }

    @Override
    public void method() {
        decotate1();
        source.method();
    }
}

 

8、代理模式

       客户端通过代理类访问,代理类实现具体的实现细节,客户只需要使用代理类即可实现操作。

       这种模式可以对旧功能进行代理,用一个代理类调用原有的方法,且对产生的结果进行控制。

interface Source{ 
    void method();
}

class OldClass implements Source{
    @Override
    public void method() {}
}

class Proxy implements Source{
    private Source source = new OldClass();
    void doSomething(){}
    @Override
    public void method() {
        new Class1().Func1();
        source.method();
        new Class2().Func2();
        doSomething();
    }
}

 

9、外观模式

       为子系统中的一组接口提供一个一致的界面,定义一个高层接口,这个接口使得这一子系统更加容易使用。这句话是百度百科的解释,有点难懂,但是没事,看下面的例子,我们在启动停止所有子系统的时候,为它们设计一个外观类,这样就可以实现统一的接口,这样即使有新增的子系统subSystem4,也可以在不修改客户端代码的情况下轻松完成。

public class Facade {
    private subSystem1 subSystem1 = new subSystem1();
    private subSystem2 subSystem2 = new subSystem2();
    private subSystem3 subSystem3 = new subSystem3();
    
    public void startSystem(){
        subSystem1.start();
        subSystem2.start();
        subSystem3.start();
    }
    
    public void stopSystem(){
        subSystem1.stop();
        subSystem2.stop();
        subSystem3.stop();
    }
}

 

10、桥接模式

interface DrawAPI {
    public void drawCircle(int radius, int x, int y);
}

class RedCircle implements DrawAPI {
    @Override
    public void drawCircle(int radius, int x, int y) {
        System.out.println("Drawing Circle[ color: red, radius: "
                + radius +", x: " +x+", "+ y +"]");
    }
}

class GreenCircle implements DrawAPI {
    @Override
    public void drawCircle(int radius, int x, int y) {
        System.out.println("Drawing Circle[ color: green, radius: "
                + radius +", x: " +x+", "+ y +"]");
    }
}

abstract class Shape {
    protected DrawAPI drawAPI;
    protected Shape(DrawAPI drawAPI){
        this.drawAPI = drawAPI;
    }
    public abstract void draw();
}

class Circle extends Shape {
    private int x, y, radius;

    public Circle(int x, int y, int radius, DrawAPI drawAPI) {
        super(drawAPI);
        this.x = x;
        this.y = y;
        this.radius = radius;
    }

    public void draw() {
        drawAPI.drawCircle(radius,x,y);
    }
}

 

11、组合模式

       组合模式是为了表示那些层次结构,同时部分和整体也可能是一样的结构,常见的如文件夹或者树。

abstract class component{}

class File extends  component{ String filename;}

class Folder extends  component{
    // 既可以放文件File类,也可以放文件夹Folder类。Folder类下又有子文件或子文件夹。
    component[] files ;  
    String foldername ;
    public Folder(component[] source){ files = source ;}
    public void scan(){
        for (component f:files){
            if (f instanceof File){
                System.out.println("File "+((File) f).filename);
            }else if(f instanceof Folder){
                Folder e = (Folder)f ;
                System.out.println("Folder "+e.foldername);
                e.scan();
            }
        }
    }
}

 

12、享元模式

       使用共享对象的方法,用来尽可能减少内存使用量以及分享资讯。通常使用工厂类辅助,例子中使用一个HashMap类进行辅助判断,数据池中是否已经有了目标实例,如果有,则直接返回,不需要多次创建重复实例。

abstract class flywei{ }

public class Flyweight extends flywei{
    Object obj ;
    public Flyweight(Object obj){
        this.obj = obj;
    }
}

class  FlyweightFactory{
    private HashMap<Object,Flyweight> data;
    public FlyweightFactory(){ data = new HashMap<>();}
    public Flyweight getFlyweight(Object object){
        if ( data.containsKey(object)){
            return data.get(object);
        }else {
            Flyweight flyweight = new Flyweight(object);
            data.put(object,flyweight);
            return flyweight;
        }
    }
}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
目标检测(Object Detection)是计算机视觉领域的一个核心问题,其主要任务是找出图像中所有感兴趣的目标(物体),并确定它们的类别和位置。以下是对目标检测的详细阐述: 一、基本概念 目标检测的任务是解决“在哪里?是什么?”的问题,即定位出图像中目标的位置并识别出目标的类别。由于各类物体具有不同的外观、形状和姿态,加上成像时光照、遮挡等因素的干扰,目标检测一直是计算机视觉领域最具挑战性的任务之一。 二、核心问题 目标检测涉及以下几个核心问题: 分类问题:判断图像中的目标属于哪个类别。 定位问题:确定目标在图像中的具体位置。 大小问题:目标可能具有不同的大小。 形状问题:目标可能具有不同的形状。 三、算法分类 基于深度学习的目标检测算法主要分为两大类: Two-stage算法:先进行区域生成(Region Proposal),生成有可能包含待检物体的预选框(Region Proposal),再通过卷积神经网络进行样本分类。常见的Two-stage算法包括R-CNN、Fast R-CNN、Faster R-CNN等。 One-stage算法:不用生成区域提议,直接在网络中提取特征来预测物体分类和位置。常见的One-stage算法包括YOLO系列(YOLOv1、YOLOv2、YOLOv3、YOLOv4、YOLOv5等)、SSD和RetinaNet等。 四、算法原理 以YOLO系列为例,YOLO将目标检测视为回归问题,将输入图像一次性划分为多个区域,直接在输出层预测边界框和类别概率。YOLO采用卷积网络来提取特征,使用全连接层来得到预测值。其网络结构通常包含多个卷积层和全连接层,通过卷积层提取图像特征,通过全连接层输出预测结果。 五、应用领域 目标检测技术已经广泛应用于各个领域,为人们的生活带来了极大的便利。以下是一些主要的应用领域: 安全监控:在商场、银行
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值