精华内容
下载资源
问答
  • 常用设计模式及实现
    千次阅读
    2022-07-05 08:54:20

    常用的七种设计模式:单例模式、工厂方法模式、抽象工厂模式、代理模式、装饰器模式、观察者模式和责任链模式。

    设计模式分类

    设计模式根据工作的目的,分为创建型模式、结构型模式和行为型模式三类。

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

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

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

    软件设计七大原则(OOP原则)

    开闭原则:对扩展开放,对修改关闭。
    里氏替换原则:不要破坏继承体系,子类重写方法功能发生改变,不应该影响父类方法的含义。
    依赖倒置原则:要面向接口编程,不要面向实现编程。
    单一职责原则:控制类的粒度大小、将对象解耦、提高其内聚性。
    接口隔离原则:要为各个类建立它们需要的专用接口。
    迪米特法则:一个类应该保持对其它对象最少的了解,降低耦合度。
    合成复用原则:尽量先使用组合或者聚合等关联关系来实现,其次才考虑使用继承关系来实现。

    实际上,七大原则的目的只有一个:降低对象之间的耦合,增加程序的可复用性、可扩展性和可维护性。

    1、单例模式:一个类只有一个实例,且该类能自行创建这个实例的一种模式
            ①单例类只有一个实例对象

            ②该单例对象必须由单例类自行创建

            ③单例类对外提供一个访问该单例的全局访问点

           ④、优点
                    单例模式可以保证内存里只有一个实例,减少了内存的开销。
                    可以避免对资源的多重占用。
                    单例模式设置全局访问点,可以优化和共享资源的访问。
            ⑤、缺点
                    单例模式一般没有接口,扩展困难。
                    单例模式的功能代码通常写在一个类中,如果功能设计不合理,则很容易违背单一职责原则

            饿汉式单例:类一旦加载就创建一个单例,保证在调用getInstance方法之前单例已经存在,这种饿汉式单例会造成空间浪费。

    public class Hungry {
        private Hungry(){}
        private final static Hungry HUNGRY = new Hungry();
        public static Hungry getInstance(){
            return HUNGRY;
        }
    }
    

            懒汉式单例:为了避免内存空间浪费,采用懒汉式单例,即用到该单例对象的时候再创建。

    public class LazyMan {
        private LazyMan(){};
    
        public static LazyMan lazyMan;
    
        public static LazyMan getInstance(){
            if (lazyMan==null){
                lazyMan = new LazyMan();
            }
            return lazyMan;
        }
    }

    这是最简单的懒汉式,但是,存在很大问题,单线程下这段代码没有问题,但是在多线程下有很大问题。

    public class LazyMan {
        private LazyMan(){
            System.out.println(Thread.currentThread().getName()+"");
        }
    
        public static LazyMan lazyMan;
    
        public static LazyMan getInstance(){
            if (lazyMan==null){
                lazyMan = new LazyMan();
            }
            return lazyMan;
        }
    
        public static void main(String[] args) {
            for(int i=0;i<10;i++){
                new Thread(()->{
                    lazyMan.getInstance();
                }).start();
            }
        }
    }

     会发现结果都不一样,因此,并发情况下,这段代码是有问题的。我们需要进行两端检测,进行“加锁”:synchronized (Singleton.class)。

    public class LazyMan {
        private LazyMan(){
            System.out.println(Thread.currentThread().getName()+"");
        }
    
        public static LazyMan lazyMan;
    
        public static LazyMan getInstance(){
            if (lazyMan==null){        //第一层检查,检查是否有引用指向对象,高并发情况下会有多个线程同时进入
                synchronized (LazyMan.class){    //第一层锁,保证只有一个线程进入
                    //双重检查,防止多个线程同时进入第一层检查(因单例模式只允许存在一个对象,故在创建对象之前无引用指向对象,所有线程均可进入第一层检查)
                    //当某一线程获得锁创建一个LazyMan对象时,即已有引用指向对象,lazyMan不为空,从而保证只会创建一个对象
                    //假设没有第二层检查,那么第一个线程创建完对象释放锁后,后面进入对象也会创建对象,会产生多个对象
                    if(lazyMan==null){    //第二层检查
                        //synchronized关键字作用为禁止指令重排,保证返回Singleton对象一定在创建对象后
                        lazyMan = new LazyMan();        //这行代码存在的问题,不能保证原子性
    实际上会执行以下内容:
                        //(1)在堆上开辟空间;(2)属性初始化;(3)引用指向对象
                        //假设以上三个内容为三条单独指令,因指令重排可能会导致执行顺序为1->3->2(正常为1->2->3),当单例模式中存在普通变量需要在构造方法中进行初始化操作时,单线程情况下,顺序重排没有影响;但在多线程情况下,假如线程1执行lazyMan = new LazyMan()语句时先1再3,由于系统调度线程2的原因没来得及执行步骤2,但此时已有引用指向对象也就是lazyMan!=null,故线程2在第一次检查时不满足条件直接返回lazyMan,此时lazyMan为null
                        //synchronized关键字可保证lazyMan = new LazyMan()语句执行顺序为123,因其为非原子性依旧可能存在系统调度问题(即执行步骤时被打断),但能确保的是只要lazyMan!=0,就表明一定执行了属性初始化操作;而若在步骤3之前被打断,此时lazyMan依旧为null,其他线程可进入第一层检查向下执行创建对象
                    }
                }
            }
            return lazyMan;
        }
    
        public static void main(String[] args) {
            for(int i=0;i<10;i++){
                new Thread(()->{
                    lazyMan.getInstance();
                }).start();
            }
        }
    }

     可以看到结果都是只有一个,按理来说是没有问题,实际上不是,上述标注行代码存在问题的,不是一个原子性操作。

            静态内部类单例:是不安全,存在问题的,是不安全,存在问题的(修改过的懒汉式单例也是如此)。

    public class Inner {
        private Inner(){}
        public static Inner getInstance(){
            return InnerClass.INNER;
        }
        public static class InnerClass{
            private static final Inner INNER = new Inner();
        }
    }

    2、工厂方法模式:实例化对象不是用new,用工厂方法替代。将选择实现类,创建对象统一管理和控制。从而将调用者跟我们的实现类解耦。

            简单工厂模式:用来生产同一等级架构中的任意产品(对于增加新的产品,需要修改已有代码)
    在简单工厂模式中,可以根据参数的不同返回不同类的实例。简单工厂模式专门定义一个类来负责创建其他类的实例。

    接下来创建一个接口,两个实现类,一个工厂,一个测试类

    //创建手机接口
    public interface Phone {
        void name();
    }
    //创建华为实现类
    public class HuaWei implements Phone{
        @Override
        public void name() {
            System.out.println("华为手机");
        }
    }
    //创建小米实现类
    public class XiaoMi implements Phone{
        @Override
        public void name() {
            System.out.println("小米手机");
        }
    }
    //创建工厂
    public class PhoneFactory {
        public static Phone getPhone(String phone){
            if(phone.equals("华为")){
                return new HuaWei();
            }else if(phone.equals("小米")){
                return  new XiaoMi();
            }else {
                return null;
            }
        }
    }
    //测试类
    public class Consumer {
        public static void main(String[] args) {
            Phone p1= PhoneFactory.getPhone("华为");
            Phone p2= PhoneFactory.getPhone("小米");
            p1.name();
            p2.name();
        }
    }

    得到测试结果

            华为手机
            小米手机

    我们通过创建一个PhoneFactory类,成功的完成工厂的创建。我们在创建对象时,也就不需要直接创建对象,而是可以通过创建工厂,这样大大的降低了代码的耦合性。但是,静态工厂模式是不能添加数据的。比如说,我们想添加一个“Oppo”手机类,你不直接修改PhoneFactory工厂代码,是不能实现的。所以,就有了第二种的工厂方法模式。

            工厂方法模式:用来生产同一等级架构中的固定产品,一个工厂等级结构可以负责多个不同产品等级结构中的产品对象的创建 。(支持增加任意产品)

    //创建手机接口
    public interface Phone {
        void name();
    }
    //创建华为实现类
    public class HuaWei implements Phone{
        @Override
        public void name() {
            System.out.println("华为手机");
        }
    }
    //创建手机工厂接口
    public interface PhoneFactory {
        Phone getPhone();
    }
    //创建华为工厂
    public class HuaWeiFactory implements PhoneFactory{
        @Override
        public Phone getPhone() {
            return new HuaWei();
        }
    }
    //测试类
    public class Consumer {
        public static void main(String[] args) {
            Phone phone = new HuaWeiFactory().getPhone();
            phone.name();
        }
    }

    得到测试结果

            华为手机

    我们创建了手机工厂接口PhoneFactory,再创建华为工厂HuaWeiFactory实现工厂,这样就可以通过HuaWeiFactory创建对象。增加新的具体工厂和产品族很方便,比如说,我们想要增加小米,只需要创建一个小米工厂XiaoMiFactory实现手机工厂接口PhoneFactory,合理的解决的简单工厂模式不能修改代码的缺点。但是,在现实使用中,简单工厂模式占绝大多数。

    简单工厂模式与工厂方法模式比较:

    结构的复杂度:简单工厂模式占优。
    代码的复杂度:简单工厂模式占优。
    编程的复杂度:简单工厂模式占优。
    管理的复杂的:简单工厂模式占优。
    因此,虽然简单工厂模式不符合设计模式,但是实际使用远大于工厂方法模式

    3、抽象工厂模式:抽象工厂模式提供了一个创建一系列相关或者相互依赖对象的接口,无需指定它们具体的类(围绕一个超级工厂创建其他工厂,该超级工厂称为工厂的工厂)

    抽象工厂模式得主要角色:

            1、抽象工厂(Abstract Factory)提供了创建产品的接口,它包含多个创建产品的方法 newProduct(),可以创建多个不同等级的产品。
    2具体工厂(Concrete Factory)主要是实现抽象工厂中的多个抽象方法,完成具体产品的创建。
    3抽象产品(Product)定义了产品的规范,描述了产品的主要特性和功能,抽象工厂模式有多个抽象产品。
    4具体产品(ConcreteProduct)实现了抽象产品角色所定义的接口,由具体工厂来创建,它同具体工厂之间是多对一的关系。

    //电脑接口
    public interface Computer {
        void play();
        void watch();
    }
    //创建华为电脑对象
    public class HuaWeiComputer implements Computer{
        @Override
        public void play() {
            System.out.println("HuaWei's play!");
        }
    
        @Override
        public void watch() {
            System.out.println("HuaWei's watch!");
        }
    }
    //手机接口
    public interface Phone {
        void send();
        void call();
    }
    //创建华为手机对象
    public class HuaWeiPhone implements Phone{
        @Override
        public void send() {
            System.out.println("HuaWei's send");
        }
    
        @Override
        public void call() {
            System.out.println("HuaWei's call");
        }
    }
    //抽象工厂
    public interface IProductFactory {
        //生产手机
        Phone phone();
        //生产电脑
        Computer computer();
    }
    //创建华为工厂
    public class HuaWeiFactory implements IProductFactory{
        @Override
        public Phone phone() {
            return new HuaWeiPhone();
        }
    
        @Override
        public Computer computer() {
            return new HuaWeiComputer();
        }
    }
    //测试类
    public class Consumer {
        public static void main(String[] args) {
            HuaWeiFactory huaWeiFactory = new HuaWeiFactory();
            Phone phone = huaWeiFactory.phone();
            phone.call();
            phone.send();
            Computer computer = huaWeiFactory.computer();
            computer.play();
            computer.watch();
        }
    }

    得到测试结果

            HuaWei's call
            HuaWei's send
            HuaWei's play!
            HuaWei's watch!

    我们通过创建一个抽象工厂完成了对具体工厂的创建,只需要传入参数就可以实例化对象。具体产品在应用层的代码隔离,无需关心创建的细节将一个系列的产品统一到一起创建。将一系列产品规划到一起创建。但是,抽象工厂模式也存在着缺点。规定了所有可能被创建的产品集合,产品簇中扩展新的产品困难,不可以增加产品,只能增加品牌。

    4、代理模式:由于某些原因需要给某对象提供一个代理以控制对该对象的访问。这时,访问对象不适合或者不能直接引用目标对象,代理对象作为访问对象和目标对象之间的中介。

            静态代理模式:

            角色分析:           

            1、抽象角色:一般会使用接口或抽象类来解决

            2、真实角色:被代理的角色

            3、代理角色:代理真实角色,代理真实角色后我们会进行一些附属操作

            4、访问角色:访问代理对象的人

    //租房
    public interface Rent {
        void rent();
    }
    //房东
    public class Master implements Rent{
        @Override
        public void rent() {
            System.out.println("Master rent");
        }
    }
    //中介
    public class Proxy implements Rent{
        private Master master;
    
        public Proxy() {
        }
    
        public Proxy(Master master) {
            this.master = master;
        }
    
        @Override
        public void rent() {
            see();
            master.rent();
            fare();
        }
        //看房
        public void see(){
            System.out.println("see");
        }
        //收费
        public void fare(){
            System.out.println("fare");
        }
    }
    //测试类
    public class Consumer {
        public static void main(String[] args) {
            Master master = new Master();
            //进行代理
            Proxy proxy = new Proxy(master);
            //不需要通过对象,直接通过代理完成响应业务
            proxy.rent();
        }
    }
    

    得到测试结果

            see
            Master rent
            fare

    可以从上述代码看出,我们通过创建中介这一代理完成了租房,并且还有看房、收费的附属操作。我们不需要使用房东对象,通过使用代理中介就可以完成操作。 

    代理模式优点:可以使真实角色的操作更加纯粹!不用去关注一些公共的业务,公共也就可以交给代理角色,实现了业务的分工,公共业务发生扩展的时候,方便集中管理!
    代理模式缺点:一个真实角色就会产生一个代理角色;代码量会翻倍开发效率会变低,也许,这样无法理解到代理模式的好处。举个例子也许能更好理解,比如说我们想要在原有固定功能上新增业务,按照开闭原则我们是不能对原有代码进行修改的。但是我们可以通过代理模式,增加代理,在实现原有功能的情况下写入新的功能,创建对象时也就可以使用代理,完成操作。

     动态代理模式:虽然静态代理模式可以很好的解决开闭原则,但是每有一个真实角色就会产生一个代理,代码量翻倍过于臃肿,开发效率较低。因此,我们就使用动态代理模式进行设计。

    //接口
    public interface IUserService {
        void add();
        void delete();
        void update();
        void query();
    
    }
    //实现类
    public class UserServiceImpl implements IUserService {
        @Override
        public void add() {
            System.out.println("add");
        }
    
        @Override
        public void delete() {
            System.out.println("delete");
        }
    
        @Override
        public void update() {
            System.out.println("update");
        }
    
        @Override
        public void query() {
            System.out.println("query");
        }
    }
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    //自动生成动态代理类模板
    public class ProxyInvocationHandler implements InvocationHandler {
        //被代理接口
        private Object target;
       
        public void setTarget(Object target) {
            this.target = target;
        }
         //得到代理类
        public Object getProxy() {
            return Proxy.newProxyInstance(getClass().getClassLoader(), target.getClass().getInterfaces(), this);
        }
        public void log(String s) {
            System.out.println("[debug]:" + s);
        }
        //得到代理类
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            log(method.getName());
            Object result = method.invoke(target, args);
            return result;
        }
    }
    //测试类
    public class Consumer {
        public static void main(String[] args) {
            UserServiceImpl userService = new UserServiceImpl();
            ProxyInvocationHandler handler = new ProxyInvocationHandler();
            //设置代理对象
            handler.setTarget(userService);
            //生成代理类
            IUserService proxy = (IUserService)handler.getProxy();
            proxy.add();
            proxy.query();
        }
    }

    得到测试结果

            [debug]:add
            add
            [debug]:query
            query

    通过测试我们可以顺利的使用动态代理模式完成一系列操作,当我们想要添加附属操作时,我们只需要在模板中进行添加。优点:①可以使真实角色的操作更加纯粹!不用去关注一些公共的业务。②公共也就可以交给代理角色!实现了业务的分工。③公共业务发生扩展的时候,方便集中管理。④一个动态代理类代理的是一个接口,一般就是对应的一类业务。⑤一个动态代理类可以代理多个类,只要是实现了同一个接口即可!

    5、装饰者模式:动态的将新功能附加到对象上。在对象功能的拓展方面,比继承更有弹性。同时装饰者模式也体现了开闭原则。

            角色分析:

            1、抽象构件(Component)角色:定义一个抽象接口以规范准备接收附加责任的对象。
            2、具体构件(ConcreteComponent)角色:实现抽象构件,通过装饰角色为其添加一些职责。
            3、抽象装饰(Decorator)角色:继承抽象构件,并包含具体构件的实例,可以通过其子类扩展具体构件的功能。
            4、具体装饰(ConcreteDecorator)角色:实现抽象装饰的相关方法,并给具体构件对象添加附加的责任。

    //定义抽象类
    public abstract class Drink {
        public abstract double cost();
    }
    //定义两个抽象类的实现类
    public class Juice extends Drink{
        @Override
        public double cost() {
            System.out.println("juice: "+16);
            return 16;
        }
    }
    public class Milk extends Drink{
        @Override
        public double cost() {
            System.out.println("milk: "+12);
            return 12;
        }
    }
    //定义装饰抽象类
    public abstract class Decorator extends Drink {
        public abstract double cost();
    }
    //定义两个装饰具体实现类
    public class Chocolate extends Decorator{
        private final static double COST = 4;
        private Drink drink;
    
        public Chocolate(Drink drink) {
            this.drink = drink;
        }
    
        @Override
        public double cost() {
            System.out.println("chocolate:"+4);
            return COST+drink.cost();
        }
    }
    public class Pudding extends Decorator{
        private final static double COST = 5;
        private Drink drink;
    
        public Pudding(Drink drink) {
            this.drink = drink;
        }
    
        @Override
        public double cost() {
            System.out.println("pudding:"+5);
            return COST+drink.cost();
        }
    }
    //测试类
    public class Test {
        public static void main(String[] args) {
            Drink milk = new Milk();
            milk = new Pudding(milk);
            milk = new Chocolate(milk);
            System.out.println(milk.cost());
        }
    }
    

    得到测试结果

            chocolate:4
            pudding:5
            milk: 12
            21.0

     

    可以看到非常简单的就能够完成具体构件和具体装饰的组合。也可以看到结构也非常简洁明,具体构件在自己的package中,具体装饰也在自己的package中。我们不管是想要增加具体构件还是具体配饰,都可以在各自的package中添加。对已有的代码不需要进行任何操作,就算新加的有bug也不会影响原有代码的操作。

    6、观察者模式:对象间的一种一对多依赖关系,使得每当一个对象状态发生改变时,其相关依赖对象皆得到通知并被自动更新。这种模式有时又称作发布-订阅模式、模型-视图模式,它是对象行为型模式。

            观察者模式有点:

            1、降低了目标与观察者之间的耦合关系,两者之间是抽象耦合关系。符合依赖倒置原则。

            2、目标与观察者之间建立了一套触发机制。

    //定义观察者接口
    public interface Observer {
        void response();
    }
    //具体化观察者1
    public class Observer1 implements Observer{
        @Override
        public void response() {
            System.out.println("Observer1 action");
        }
    }
    //具体化观察者2
    public class Observer2 implements Observer{
        @Override
        public void response() {
            System.out.println("Observer2 action");
        }
    }
    //抽象目标
    public abstract class Subject {
        //创建观察者集合
        protected ArrayList<Observer> array = new ArrayList<Observer>();
        //增加观察者
        public void add(Observer observer){
            array.add(observer);
        }
        //删除观察者
        public void remove(Observer observer){
            array.remove(observer);
        }
        //通知观察者方法
        public abstract void notifyObserver();
    }
    //具体化目标
    public class Subject1 extends Subject{
        @Override
        public void notifyObserver() {
            for (Observer observer :array){
                observer.response();
            }
        }
    }
    //测试类
    public class Test {
        public static void main(String[] args) {
            Subject subject = new Subject1();
            Observer obs1 = new Observer1();
            Observer obs2 = new Observer2();
            subject.add(obs1);
            subject.add(obs2);
            subject.notifyObserver();
        }
    }

    得到测试结果:

            Observer1 action
            Observer2 action

    通过测试我们可以看到,我们不需要建立太多观察者和具体目标之间的联系,大大降低了目标与观察者之间的耦合关系。并且结构也十分简单明了,观察者和目标分别在各自的package包下。当我们想要添加观察者时,只需要在观察者包下进行添加,实现Observer接口就可以了。

    7、责任链模式:一种处理请求的模式,它让多个处理器都有机会处理该诘求,直到其中某个处理成功为止。责任链模式把多个处理器串成链,然后让请求在链上传递。
            责任链模式的主要角色
            抽象处理者(Handler)角色:定义一个处理请求的接口,包含抽象处理方法和一个后继连接。
            具体处理者(Concrete Handler)角色:实现抽象处理者的处理方法,判断能否处理本次请求,如果可以处理请求则处理,否则将该请求转给它的后继者。
            客户类(Client)角色:创建处理链,并向链头的具体处理者对象提交请求,它不关心处理细节和请求的传递过程。
            责任链模式优点
                    降低了对象之间的耦合度。处理者不需要知道客户的任何信息,客户也不要知道处理者是如何实现方法的。
                    提高了系统的灵活性。当我们想要新增处理器到整个链条中时,所付出的代价是非常小的
            责任链模式缺点
                    降低了系统的性能。对比较长的职责链,请求的处理可能涉及多个处理对象
                    不能保证每个请求一定被处理。由于一个请求没有明确的接收者,所以不能保证它一定会被处理,该请求可能一直传到链的末端都得不到处理。

    //抽象处理者
    public abstract class Handler {
        private Handler next;
        public void setNext(Handler next) { this.next = next; }
        public Handler getNext() { return next; }
    
        //处理请求
        public abstract void handleRequest(int info);
    }
    //具体处理者1
    public class Handler1 extends Handler{
        @Override
        public void handleRequest(int info) {
            if (info <10){
                System.out.println("Handler1完成处理");
            }else {
                if (getNext()!=null){
                    getNext().handleRequest(info);
                }else {
                    System.out.println("没有处理者进行处理");
                }
            }
        }
    }
    //具体处理者2
    public class Handler2 extends Handler{
        @Override
        public void handleRequest(int info) {
            if (info <20&&info>10){
                System.out.println("Handler2完成处理");
            }else {
                if (getNext()!=null){
                    getNext().handleRequest(info);
                }else {
                    System.out.println("没有处理者进行处理");
                }
            }
        }
    }
    测试类
    public class Test {
        public static void main(String[] args) {
            Handler handler1 = new Handler1();
            Handler handler2 = new Handler2();
            handler1.setNext(handler2);
            handler1.handleRequest(5);
            handler1.handleRequest(15);
            handler1.handleRequest(25);
        }
    }

    得到测试结果:

    Handler1完成处理
    Handler2完成处理
    没有处理者进行处理

    通过测试结果我们看到,5交给了Handler1处理,15交给了Handler2处理,而25则没有处理者处理。请求者根本不需要参与处理,只需要提交数据就可以完成功能的处理,完全不需要管是哪个处理者进行处理的。当我们想要继续添加处理者时,这只需要再次添加就可以了,也不会对之前的代码造成影响。

    更多相关内容
  • 常用设计模式Python实现

    千次阅读 2019-04-24 13:00:27
    设计模式(Design pattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性。 代码查看:...

    设计模式(Design pattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性。

    代码查看:https://github.com/nonpricklycactus/Design-Pattern

    一、设计模式分类

                经典的《设计模式》一书归纳出23种设计模式,这23种模式又可归为,创建型、结构型和行为型3大类

                1.创建型模式分类

                   社会化的分工越来越细,自然在软件设计方面也是如此,因此对象的创建和对象的使用分开也就成为了必然趋势。因为对象的创建会消耗掉系统的很多资源,所以单独对对象的创建进行研究,从而能够高效地创建对象就是创建型模式要探讨的问题。这里有6个具体的创建型模式可供研究,它们分别是:

    • 简单工厂模式(Simple Factory);
    • 工厂方法模式(Factory Method);
    • 抽象工厂模式(Abstract Factory);
    • 创建者模式(Builder);
    • 原型模式(Prototype);
    • 单例模式(Singleton)。

    说明:严格来说,简单工厂模式不是GoF总结出来的23种设计模式之一。

               2. 结构型模式分类

                   在解决了对象的创建问题之后,对象的组成以及对象之间的依赖关系就成了开发人员关注的焦点,因为如何设计对象的结构、继承和依赖关系会影响到后续程序的维护性、代码的健壮性、耦合性等。对象结构的设计很容易体现出设计人员水平的高低,这里有7个具体的结构型模式可供研究,它们分别是:

    • 外观模式(Facade);
    • 适配器模式(Adapter);
    • 代理模式(Proxy);
    • 装饰模式(Decorator);
    • 桥模式(Bridge);
    • 组合模式(Composite);
    • 享元模式(Flyweight

               3. 行为型模式分类

                    在对象的结构和对象的创建问题都解决了之后,就剩下对象的行为问题了,如果对象的行为设计的好,那么对象的行为就会更清晰,它们之间的协作效率就会提高,这里有11个具体的行为型模式可供研究,它们分别是:

    • 模板方法模式(Template Method);
    • 观察者模式(Observer);
    • 状态模式(State);
    • 策略模式(Strategy);
    • 职责链模式(Chain of Responsibility);
    • 命令模式(Command);
    • 访问者模式(Visitor);
    • 调停者模式(Mediator);
    • 备忘录模式(Memento);
    • 迭代器模式(Iterator);
    • 解释器模式(Interpreter)

    二、设计模式的六大原则

               1、开闭原则(Open Close Principle)

                     开闭原则就是说对扩展开放,对修改关闭。在程序需要进行拓展的时候,不能去修改原有的代码,实现一个热插拔的效果。所以一句话概括就是:为了使程序的扩展性好,易于维护和升级。想要达到这样的效果,我们需要使用接口和抽象类,后面的具体设计中我们会提到这点。

               2、里氏代换原则(Liskov Substitution Principle)

                     里氏代换原则(Liskov Substitution Principle LSP)面向对象设计的基本原则之一。 里氏代换原则中说,任何基类可以出现的地方,子类一定可以出现。 LSP是继承复用的基石,只有当衍生类可以替换掉基类,软件单位的功能不受到影响时,基类才能真正被复用,而衍生类也能够在基类的基础上增加新的行为。里氏代换原则是对“开-闭”原则的补充。实现“开-闭”原则的关键步骤就是抽象化。而基类与子类的继承关系就是抽象化的具体实现,所以里氏代换原则是对实现抽象化的具体步骤的规范。

                3、依赖倒转原则(Dependence Inversion Principle)

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

                 4、接口隔离原则(Interface Segregation Principle)

                        这个原则的意思是:使用多个隔离的接口,比使用单个接口要好。还是一个降低类之间的耦合度的意思,从这儿我们看出,其实设计模式就是一个软件的设计思想,从大型软件架构出发,为了升级和维护方便。所以上文中多次出现:降低依赖,降低耦合。

                  5、迪米特法则(最少知道原则)(Demeter Principle)

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

                  6、合成复用原则(Composite Reuse Principle)

                         原则是尽量使用合成/聚合的方式,而不是使用继承。

    三、常用创建型模式实现

               1.工厂模式

                  在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。

    简单工厂模式

                  

                 该例子为通过ShapeFactory对象调用Shape接口实现图形的画出

                 python代码实现:简单工厂.py

    工厂方法模式

                 

                    简单工厂模式只有一个工厂,工厂方法模式对每一个产品都有相应的工厂

                    该例子为通过提供的接口基类创建要调用运算类的运算工厂,对运算类的子类进行调用,通过该方法增加一个运算类(例如N次方类),只需要增加运算类和相对应的工厂,两个类,不需要修改工厂类。

                    python代码实现:工厂模式.py

    抽象工厂模式

                      抽象工厂模式与工厂方法模式的最大区别就在于,工厂方法模式针对的是一个产品等级结构;而抽象工厂模式则需要面对多个产品等级结构。

                      所谓产品族,是指位于不同产品等级结构中,功能相关联的产品组成的家族。比如AMD的主板、芯片组、CPU组成一个家族,Intel的主板、芯片组、CPU组成一个家族。而这两个家族都来自于三个产品等级:主板、芯片组、CPU。一个等级结构是由相同的结构的产品组成,示意图如下:

                   通过使用抽象工厂模式,可以处理具有相同(或者相似)等级结构中的多个产品族中的产品对象的创建问题。如下图所示:

                 由于这两个产品族的等级结构相同,因此使用同一个工厂族也可以处理这两个产品族的创建问题,这就是抽象工厂模式。

                 抽象工厂的功能是为一系列相关对象或相互依赖的对象创建一个接口。一定要注意,这个接口内的方法不是任意堆砌的,而是一系列相关或相互依赖的方法。

    在什么情况下应当使用抽象工厂模式

    •  一个系统不应当依赖于产品类实例如何被创建、组合和表达的细节,这对于所有形态的工厂模式都是重要的。
    •  这个系统的产品有多于一个的产品族,而系统只消费其中某一族的产品。
    •  同属于同一个产品族的产品是在一起使用的,这一约束必须在系统的设计中体现出来。(比如:Intel主板必须使用Intel CPU、Intel芯片组)
    •  系统提供一个产品类的库,所有的产品以同样的接口出现,从而使客户端不依赖于实现。

               python代码实现:抽象工厂模式.py

          2.建造者模式

              将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。

              python代码实现:建造者模式 

        3.单例模式

             保证一个类仅有一个实例,并提供一个访问它的全局访问点。

    #实现__new__方法
    #并在将一个类的实例绑定到类变量_instance上,
    #如果cls._instance为None说明该类还没有实例化过,实例化该类,并返回
    #如果cls._instance不为None,直接返回cls._instance
    class Singleton(object):
        def __new__(cls, *args, **kwargs):
            if not hasattr(cls,'_instance'):
                orig = super(Singleton,cls)
                cls._instance =  orig.__new__(cls)
            return cls._instance
     
    class MyClass(Singleton):
        def __init__(self,name):
            self.name = name
     
     
    a = MyClass("Alex")
    b = MyClass("Jack")
     
     
    print(a.name)
    print(b.name)

     四、常用结构型模式实现

                1.适配器模式

                   将一个类的接口转换成客户希望的另外一个接口。Adapter 模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。 

                   python代码实现:适配器模式.py

                2.桥接模式

                     将抽象部分与实现部分分离,使它们都可以独立的变化。 

                 python代码实现:桥接模式.py

                 深入讲解请参考:http://www.cnblogs.com/houleixx/archive/2008/02/23/1078877.html

               3.组合模式

                  将对象组合成树形结构以表示“部分-整体”的层次结构。C o m p o s i t e 使得用户对单个对象和组合对象的使用具有一致性。 

                  

                    python代码实现:组合模式.py

               4.外观模式

                   为子系统中的一组接口提供一个一致的界面,Facade模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。

                    python代码实现:外观模式.py

               5.享元模式

                    运用共享技术有效地支持大量细粒度的对象。

                    python代码实现:享元模式.py

               6.代理模式

                    为其他对象提供一种代理以控制对这个对象的访问。

                    主要解决:在直接访问对象时带来的问题,比如说:要访问的对象在远程的机器上。在面向对象系统中,有些对象由于某些原因(比如对象创建开销很大,或者某些操作需要安全控制,或者需要进程外的访问),直接访问会给使用者或者系统结构带来很多麻烦,我们可以在访问此对象时加上一个对此对象的访问层。

                     python代码实现:代理模式.py​​​​​​​

    五、常用行为型模式实现

               1.模板方法模式

                    定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。

                    主要解决:一些方法通用,却在每一个子类都重新写了这一方法。

                   python代码实现:模板模式.py​​​​​​​

               2.责任链模式

                     使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。

                    python代码实现:责任链.py​​​​​​​

               3.观察者模式

                   定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时, 所有依赖于它的对象都得到通知并被自动更新。

                    python代码实现:观察者模式.py​​​​​​​

               4.策略模式

                   定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换。

                   主要解决:在有多种算法相似的情况下,使用 if...else 所带来的复杂和难以维护。

                     python代码实现:策略模式.py

     

     

     

     

    展开全文
  • Java常用设计模式总结应用场景分析

    万次阅读 多人点赞 2019-03-12 16:24:00
    原 java常用设计模式总结 2017年11月23日 21:30:54 qq_14827935 阅读数:3284 ...

    掌握常用的几种(最起码单例模式、工厂模式),了解其他的设计模式即可,做到手里有粮,心里不慌。首先,掌握每种模式的定义及使用场景。其次,掌握一个形象的例子,简单的过一遍代码。
    学习设计模式的真正目的:编程时,有意识地面向接口编程,多用封装、继承、组合、多态等OOP思想,而不仅仅是死记几类设计模式。

    常用的设计模式分类:
    创建型(创建一个对象):单例模式、工厂模式、抽象工厂模式
    结构型(将几个对象组织成一个结构):桥接模式、外观模式、代理模式
    行为型(多个对象间的通信):观察者模式、策略模式
    其中,工厂模式、桥接模式、策略模式有点像,放在一起理解(几个对象具有共同特征,因此继承共同的接口,然后通过工厂、桥去访问)。另外,工厂模式和外观模式(几个对象间有先后关系,是串行的,而非工厂模式中的并行,因此几个对象组合成一个外观类,通过这个外观类来访问)区别很明显,也因此放在一起理解。

    参考引用:

    http://www.runoob.com/design-pattern/proxy-pattern.html
    https://www.cnblogs.com/maowang1991/archive/2013/04/15/3023236.html
    https://www.cnblogs.com/chinajava/p/5880870.html

    设计模式定义

    被反复使用的,代码设计经验的总结。

    设计模式的原则

    总结起来,就是多用接口/抽象类,从而增加代码的可扩展性(减少修改代码)。降低模块间的依赖和联系。
    体现了OOP的模块化、可扩展性等特征。

    工厂模式

    定义与使用场合:现在需要创建几个对象,且这几个对象有共同特征,则不需要具体创建各个对象,而是创建对象工厂类即可。
    一般常用静态工厂模式。
    例子:发送邮件和短信(共同特征:发送的消息)
    这里写图片描述

    public interface Sender {  
        public void Send();  
    }  
     
    • 1
    • 2
    • 3
    public class MailSender implements Sender {  
        @Override  
        public void Send() {  
            System.out.println("this is mailsender!");  
        }  
    }  
     
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    public class SmsSender implements Sender {  
    
        @Override  
        public void Send() {  
            System.out.println("this is sms sender!");  
        }  
    }  
     
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    public class SendFactory {  
    
        public static Sender produceMail(){  
            return new MailSender();  
        }  
    
        public static Sender produceSms(){  
            return new SmsSender();  
        }  
    }  
     
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    public class FactoryTest {  
    
        public static void main(String[] args) {      
            Sender sender = SendFactory.produceMail();  
            sender.Send();  
        }  
    }  
     
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    抽象工厂模式

    工厂方法模式有一个问题就是,类的创建依赖工厂类,也就是说,如果想要拓展程序,必须对工厂类进行修改,这违背了闭包原则
    定义与使用场景:同上。
    例子:同上。
    这里写图片描述

    public interface Provider {  
        public Sender produce();  
    }  
     
    • 1
    • 2
    • 3
    public class SendMailFactory implements Provider {  
    
        @Override  
        public Sender produce(){  
            return new MailSender();  
        }  
    }  
     
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    public class SendSmsFactory implements Provider{  
    
        @Override  
        public Sender produce() {  
            return new SmsSender();  
        }  
    }  
     
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    public class Test {  
    
        public static void main(String[] args) {  
            Provider provider = new SendMailFactory();  
            Sender sender = provider.produce();  
            sender.Send();  
        }  
    }  
     
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    总结:如果要新增发送微信,则只需做一个实现类,实现Sender接口,同时做一个工厂类,实现Provider接口,就OK了,无需去改动现成的代码。这样做,拓展性较好!
    所有工厂模式中,抽象工厂模式最先进。

    策略模式及与工厂模式的区别

    定义与使用场合:一个系统需要动态地在几种类似的算法中选择一种。
    与工厂模式异同:实例化一个对象的位置不同。对工厂模式而言,实例化对象是放在了工厂类里面。而策略模式实例化对象的操作在调用的地方。本质都是继承与多态。
    例子: 现有 加/减/乘 几种算法,输入参数返回值都一样(可以理解成类似的算法)。现在需要在调用时动态配置算法策略,实现对不同算法的调用。
    这里写图片描述

    public interface Strategy {
       public int doOperation(int num1, int num2);
    }
     
    • 1
    • 2
    • 3
    public class OperationAdd implements Strategy{
       @Override
       public int doOperation(int num1, int num2) {
          return num1 + num2;
       }
    }
     
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    public class OperationSubstract implements Strategy{
       @Override
       public int doOperation(int num1, int num2) {
          return num1 - num2;
       }
    }
     
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    public class OperationMultiply implements Strategy{
       @Override
       public int doOperation(int num1, int num2) {
          return num1 * num2;
       }
    }
     
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    public class Context {
       private Strategy strategy;
    
       public Context(Strategy strategy){
          this.strategy = strategy;
       }
    
       public int executeStrategy(int num1, int num2){
          return strategy.doOperation(num1, num2);
       }
    }
     
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    public class StrategyPatternDemo {
       public static void main(String[] args) {
           //实例化对象的位置在调用处
          Context context = new Context(new OperationAdd());        
          System.out.println("10 + 5 = " + context.executeStrategy(10, 5));
    
          context = new Context(new OperationSubstract());        
          System.out.println("10 - 5 = " + context.executeStrategy(10, 5));
    
          context = new Context(new OperationMultiply());        
          System.out.println("10 * 5 = " + context.executeStrategy(10, 5));
       }
    }
     
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    单例模式

    定义及使用场合:只有一个对象被创建。
    例子:
    建议采用 饿汉式 创建方法。线程安全,容易实现。初始化慢一点。

    public class SingleObject {
    
       //创建 SingleObject 的一个对象
       private static SingleObject instance = new SingleObject();
    
       //让构造函数为 private,这样该类就不会被实例化
       private SingleObject(){}
    
       //获取唯一可用的对象
       public static SingleObject getInstance(){
          return instance;
       }
    
    }
     
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    观察者模式

    定义与使用场景:一个对象(subject)被其他多个对象(observer)所依赖。则当一个对象变化时,发出通知,其它依赖该对象的对象都会收到通知,并且随着变化。
    比如 声音报警器和闪光灯报警器分别订阅热水器温度,热水器温度过高时,发出通知,两个报警器分别发声、闪光以实现报警。
    又比如很多人订阅微信公众号,该公众号有更新文章时,自动通知每个订阅的用户。
    **实现:**1,多个观察者要订阅这个对象 2,这个对象要发出通知

    例子:
    这里写图片描述

    public interface Observer {  
        public void update();  
    }  
     
    • 1
    • 2
    • 3
    public class Observer1 implements Observer {  
    
        @Override  
        public void update() {  
            System.out.println("observer1 has received!");  
        }  
    }  
     
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    public class Observer2 implements Observer {  
    
        @Override  
        public void update() {  
            System.out.println("observer2 has received!");  
        }  
    
    }  
     
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    public interface Subject {  
    
        /*增加观察者*/  
        public void add(Observer observer);  
    
        /*删除观察者*/  
        public void del(Observer observer);  
    
        /*通知所有的观察者*/  
        public void notifyObservers();  
    
        /*自身的操作*/  
        public void operation();  
    }  
     
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    public abstract class AbstractSubject implements Subject {  
    
        private Vector<Observer> vector = new Vector<Observer>();  
        @Override  
        public void add(Observer observer) {  
            vector.add(observer);  
        }  
    
        @Override  
        public void del(Observer observer) {  
            vector.remove(observer);  
        }  
    
        @Override  
        public void notifyObservers() {  
            Enumeration<Observer> enumo = vector.elements();  
            while(enumo.hasMoreElements()){  
                enumo.nextElement().update();  
            }  
        }  
    
     
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    public class MySubject extends AbstractSubject {  
    
        @Override  
        public void operation() {  
            System.out.println("update self!");  
            notifyObservers();  
        }  
    
    }  
     
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    public class ObserverTest {  
    
        public static void main(String[] args) {  
            Subject sub = new MySubject();  
            sub.add(new Observer1());  //订阅这个对象
            sub.add(new Observer2());  
    
            sub.operation();  //发出改变的一个通知
        }  
    
    }  
     
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    代理模式

    定义与使用场景:一个代理类代表一个真实类的功能,通过访问代理类来实现对真实类的访问。
    比如买火车票这件小事:黄牛相当于是火车站的代理,我们可以通过黄牛买票,但只能去火车站进行改签和退票。
    又比如需要对原有的方法进行修改,就是采用一个代理类调用原有的方法,以避免修改原有代码。
    例子:
    这里写图片描述
    一个真实对象realSubject提供一个代理对象proxy。通过proxy可以调用realSubject的部分功能*,并添加一些额外的业务处理*,同时可以屏蔽realSubject中未开放的接口。
    1、RealSubject 是委托类,Proxy 是代理类;
    2、Subject 是委托类和代理类的接口;
    3、request() 是委托类和代理类的共同方法;

    interface Subject {
        void request();
    }
    
    class RealSubject implements Subject {
        public void request(){
            System.out.println("RealSubject");
        }
    }
    
    class Proxy implements Subject {
        private Subject subject;
    
        public Proxy(Subject subject){
            this.subject = subject;
        }
        public void request(){
            System.out.println("begin");
            subject.request();
            System.out.println("end");
        }
    }
    
    public class ProxyTest {
        public static void main(String args[]) {
            RealSubject subject = new RealSubject();
            Proxy p = new Proxy(subject);
            p.request();
        }
    }
     
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    桥接模式及与策略模式的区别

    定义与使用场景:访问多种数据库驱动(多个具有共同特征的数据库驱动),不是直接访问,而是通过DriverManager桥来访问。

    这里写图片描述
    例子: 不再具体实现了。
    这里写图片描述
    与策略模式的区别:(个人觉得较复杂,了解即可。本质都是面向接口编程,体现继承与多态)
    策略模式:我要画圆,要实心圆,我可以用solidPen来配置,画虚线圆可以用dashedPen来配置。这是strategy模式。
    桥接模式:同样是画圆,我是在windows下来画实心圆,就用windowPen+solidPen来配置,在unix下画实心圆就用unixPen+solidPen来配置。如果要再windows下画虚线圆,就用windowsPen+dashedPen来配置,要在unix下画虚线圆,就用unixPen+dashedPen来配置。
    所以相对策略模式,桥接模式要表达的内容要更多,结构也更加复杂。

    外观模式

    定义与使用场景:见例子。又比如,去医院看病,可能要去挂号、门诊、划价、取药,让患者或患者家属觉得很复杂,如果有提供接待人员,只让接待人员来处理,就很方便。
    例子:计算机启动,需要先启动CPU,再启动memory,最后启动disk。这三个类之间具有先后关系(依赖关系)。
    这里写图片描述
    与工厂模式的区别:工程模式多个类具有共同特征(继承一个共同的接口),是并列的。而外观模式多个类是有先后关系,是串行的,用组合。

    贴部分代码:

    public class Computer {  
    //是组合,而非继承。这是与工程模式的显著区别。
        private CPU cpu;  
        private Memory memory;  
        private Disk disk;  
    
        public Computer(){  
            cpu = new CPU();  
            memory = new Memory();  
            disk = new Disk();  
        }  
    
        public void startup(){  
            System.out.println("start the computer!");  
            cpu.startup();  
            memory.startup();  
            disk.startup();  
            System.out.println("start computer finished!");  
        }  
    
        public void shutdown(){  
            System.out.println("begin to close the computer!");  
            cpu.shutdown();  
            memory.shutdown();  
            disk.shutdown();  
            System.out.println("computer closed!");  
        }  
    }  
     
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    public class User {  
    
        public static void main(String[] args) {  
            Computer computer = new Computer();  
            //将计算机的启动过程封装成一个类
            computer.startup();  
            computer.shutdown();  
        }  
    }  
     
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    生产者-消费者模式

    定义与使用场景:生产者把数据放入缓冲区,而消费者从缓冲区取出数据。
    例子:缓冲区一般为队列(FIFO),但在生产消费较为频繁时,队列push,pop内存消耗较大,此时可以考虑环形缓冲区(以数组、链表方式实现)。
    通过互斥锁防止缓冲区同时读写。通过信号量控制缓冲区大小(满的时候不允许写,空的时候不允许读)


    作者:qq_14827935
    来源:CSDN
    原文:https://blog.csdn.net/qq_14827935/article/details/78618652

    展开全文
  • java常用设计模式详解应用

    千次阅读 多人点赞 2019-01-18 10:10:31
    java常用设计模式详解应用 java有23种设计模式,用于解决在编程当中遇到的实际问题。本文主要讲解单例模式、工厂模式、适配器模式、装饰模式、代理模式、模板模式、策略模式、观察者模式。 ...

    java常用设计模式详解及应用
    java有23种设计模式,用于解决在编程当中遇到的实际问题。本文主要讲解单例模式、工厂模式、适配器模式、装饰模式、代理模式、模板模式、策略模式、观察者模式、委托模式。
    (1)单例模式
    定义:确保一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。
    类图:
    在这里插入图片描述
    Singleton 是一个自关联的类。
    单例模式实例化对象的机制分两种一种是懒汉式,一种是饿汉式模式。懒汉式就是在调用的时候才实例化对象,而饿汉模式是在加载类的时候就已经实例化对象了。
    1、懒汉式单例

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

    这里将Singleton类的构造函数限定为private,来避免外部对象直接创建Singleton的对象 ,只能通过getInstance()方法来实例化对象。
    上面这种情况在多线程是也有可能创建出多个对象,
    下面是多线程时的改进。

    public class Singleton {
        private Singleton(){}
        private static Singleton singleton=null;
        public static Singleton getInstance(){
                if (singleton ==null){
                    synchronized (Singleton.class){
                        if (singleton ==null){
                            singleton= new Singleton();
                        }
                    }
                }
           return singleton;
        }
    }
    

    这里利用synchronized 同步锁,并进行非空双重校验。
    2、饿汉式单例
    饿汉式单例模式,初始化时就已经实例化对象。

    public class Singleton {
        private Singleton(){}
        private static final Singleton singleton=new Singleton();
        public static Singleton getInstance(){
           return singleton;
        }
    }
    

    饿汉式在类创建的同时就已经创建好一个静态对象供系统使用,以后就不会变化,所以始终是线程安全的。
    饿汉式和懒汉式区别
    饿汉式就是类一旦加载,单例初始化就完成了,保证在调用getInstance方法的时候,单例已经存在了;而懒汉式,只在调用getInstance方法的时候才去实例化对象。
    实际项目中的应用
    例如A系统要通过接口去访问B系统进行数据交互,但是在访问B系统之前要先登录,为了避免在A项目中出现多个登录对象,这个时候就可以使用单例模式将B的登录对象设置成单例。这样可以保证一个应用上面有一个登录实例,但是在集群的环境下,还是会出现多个登录对象。
    (2)工厂模式
    定义:定义一个创建对象的接口,让其子类自己决定实例化哪一个工厂类,工厂模式使其创建过程延迟到子类进行。
    类图:
    在这里插入图片描述
    (1)新建Shape接口

    public interface Shape {
    	public void draw();
    }
    

    (2)新建Circle类

    public class Circle implements Shape{
    	@Override
    	public void draw() {
    		System.out.println("I am Circle");
    	}
    }
    

    (3)新建Square类

    public class Square implements Shape{
    	@Override
    	public void draw() {
    		System.out.println("I am Square");
    	}
    }
    

    (4)新建Rectangle

    public class Rectangle implements Shape {
    	@Override
    	public void draw() {
    		System.out.println("I am Rectangle");
    	}
    }
    

    (5)新建ShapeFactory类

    public class ShapeFactory{
    	public Shape getShape(String shapeType){
    		if ("CIRCLE".equals(shapeType)) {
    			return new Circle();
    		}else if ("SQUARE".equals(shapeType)) {
    			return new Square();
    		}else if ("RECTANGLE".equals(shapeType)) {
    			return new Rectangle();
    		}
    		return null;
    	}
    }
    

    然后调用写一个test类来测试一下

    public class factoryTest {
    public static void main(String[] args) {
    	ShapeFactory shapeFactory=new ShapeFactory();
    	Shape shape= shapeFactory.getShape("CIRCLE");
    	shape.draw();
    }
    }
    

    打印的结果是I am Circle。
    还有抽象工厂模式,实际是就是对ShapeFactory进行了抽象,这里就不在介绍。
    实际项目中的应用
    工厂模式在实际项目中的应用会结合后面的策略模式和模板模式一起比较着来介绍。
    (3)适配器模式
    定义:是作为两个不兼容的接口之间的桥梁。
    类图:在这里插入图片描述上图为对象型适配器模式的类图,
    1、Client(客户端):外部使用程序;
    2、Target(目标抽象类):定义用户需要的相关接口,作为接口或者抽象类存在;
    3、Adaptee(适配者):要被适配的角色,定义类一系列的接口,实现用户需要的一些业务功能;
    4、Adapter(适配器):将Adaptee适配到Target上,适配器通常继承目标抽象类,并通过组合(本实例)或者实现适配者接口,从而实现了目标类和适配者之间形成关联关系。
    实际项目中的应用
    适配器模式在对一些老的项目进行改造升级时很有用,之前在做项目时要对用户登录验证方式进行改造,以前用户登录都是通过CAS,改造后要通过统一用户管理系统对用户进行验证和管理,在这个过程中有本系统的LocalRedisServer和统一用户管理系统的RemoteRedisServer,为了将这二种结合起来使用,就采用了适配器模式,使用新的AdapterRedisServer从而将问题解决。
    (4)装饰模式
    定义:动态地给一个对象添加一些额外的职责。
    类图:在这里插入图片描述
    装饰者模式中的角色有:
    1、抽象构建(Component)角色:抽象接口,被装饰对象的接口;
    2、具体构建(ConcreateComponent)角色:被装饰的实际对象;
    3、装饰(Decorator)角色:装饰者接口;
    4、具体装饰(ConcreateComponent)角色:装饰者对象;
    (1)新建Component

    public interface Component {
    	void sampleOperation();
    }
    

    (2)新建ConcreateComponent

    public class ConcreateComponent implements Component {
    	@Override
    	public void sampleOperation() {
    		System.out.println("I am Component object");
    	}
    }
    

    (3)新建Decorator

    public class Decorator implements Component {
    	private Component component;
    
    	public Decorator(Component component) {
    		this.component = component;
    	}
    
    	@Override
    	public void sampleOperation() {
    		component.sampleOperation();
    	}
    }
    

    (4)新建ConcreateDecoratorA

    public class ConcreateDecoratorA extends Decorator {
    	public ConcreateDecoratorA(Component component) {
    		super(component);
    	}
    	@Override
    	public void sampleOperation() {
    		super.sampleOperation();
    		System.out.println("装饰附加业务功能!");
    	}
    }
    

    (5)新建test

    public class test {
    	public static void main(String[] args) {
    		Component component = new ConcreateComponent();
    		ConcreateDecoratorA concreateDecoratorA = new ConcreateDecoratorA(component);
    		concreateDecoratorA.sampleOperation();
    	}
    }
    

    测试结果为:

    I am Component object
    装饰附加业务功能!
    

    装饰器模式就是在不改变原结构的基础之上,对原结构添加新的功能,这种设计模式在对项目升级改造或者需求变更的时候很有用处。
    (5)代理模式
    定义:代理模式给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用。通俗的来讲代理模式就是我们生活中常见的中介。
    1、静态代理
    静态代理是指预先确定了代理与被代理者的关系。那映射到编程领域的话,就是指代理类与被代理类的依赖关系在编译期间就确定了。
    类图:在这里插入图片描述
    (1)新建一个subject接口

    public interface subject {
    	public void method();
    }
    

    (2)新建realSubject

    public class realSubject implements subject {
    	@Override
    	public void method() {
    		System.out.println("realSubject");
    	}
    }
    

    (3)新建proxySubject

    public class proxySubject implements subject {
    	private subject subject;
    
    	@Override
    	public void method() {
    		if (subject == null) {
    			subject = new realSubject();
    		}
    		subject.method();
    	}
    }
    

    (4)新建测试类

    public class staticProxyTest {
    	public static void main(String[] args) {
    		proxySubject proxySubject = new proxySubject();
    		proxySubject.method();
    	}
    }
    

    这样就可以通过代理类proxySubject 来调用实际类realSubject。
    2、动态代理
    动态代理:代理类并不是在java代码中定义的,而是在运行时动态创建的。
    动态代理简单实现
    在java的java.lang.reflect包下面提供了一个Proxy类和一个InvocationHandler接口,通过这个类和接口可以生成JDK动态代理类和动态代理对象。
    InvocationHandler接口是给动态代理类实现的,负责处理被代理对象的操作的,而proxy是用来创建动态代理类实例对象的,因为只有得到了这个对象我们才能调用哪些需要代理的方法。
    动态代理的实现以诉讼代理为例。
    (1)创建一个诉讼接口ILawSuit

    public interface ILawSuit {
     void submit(String proof);//提起诉讼
     void defend();//法庭辩护
    }
    

    (2)新建代理类LitigationCategory

    public class LitigationCategory implements ILawSuit{
    	@Override
    	public void submit(String proof) {
    		System.out.println("提起诉讼!"+proof);
    	}
    	@Override
    	public void defend() {
    		System.out.println("辩护");	
    	}
    }
    

    (3)新建动态代理类DynProxyLawyer

    public class DynProxyLawyer implements InvocationHandler{
    	private Object target;
    	public DynProxyLawyer(Object obj) {
           this.target=obj;
    	}
    	
    	@Override
    	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    		System.out.println("案件进展"+method.getName());
    		Object res=method.invoke(target, args);
    		return res;
    	}
    }
    

    (4)新建动态代理工厂类

    public class ProxyFactory {
    	public static Object getDynProxy(Object target){
    		InvocationHandler handler=new DynProxyLawyer(target);
    		return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(),handler);
    	}
    }
    

    (5)新建测试类

    public class DynTest {
    public static void main(String[] args) {
    	ILawSuit proxy=(ILawSuit) ProxyFactory.getDynProxy(new LitigationCategory());
    	proxy.submit("动态代理");
    	proxy.defend();
    }
    }
    

    测试结果:

    案件进展submit
    提起诉讼!动态代理
    案件进展defend
    辩护
    

    以上是jdk的动态代理,jdk提供的动态代理伊依赖接口,首先使用接口定义好操作规范。然后通过Proxy类产生的代理对象调用被代理对象的操作,而这个操作又被分发给InvocationHandler接口的invoke方法具体执行。
    cglib的动态代理实现
    由于jdk只能针对实现了接口的类做动态代理,而不能对没有实现接口的类做动态代理,所以就有了cglib。cglib是一个强大、高性能的code生成类库,它可以在程序运行期间动态扩展类和接口,他的底层实现是使用java字节码操作SAM。这里就不在展开举例了。
    动态代理的实际运用:输出日志,账本溯源,性能监控等。
    (6)模板模式
    定义:完成一组算法,需要分多个步骤,每个步骤根据对象的不同,而实现细节不同,就可以在父类中定义一个完成该事情的总方法,按照完成事件需要的步骤去调用其每个步骤的实现。每个步骤的具体的实现,由子类完成。
    类图:
    在这里插入图片描述(1)定义Template接口

    public abstract class Template {
    	protected void dodish() {
    		this.pre();
    		this.dojob();
    		this.last();
    	}
    
    	public abstract void pre();
    
    	public abstract void dojob();
    
    	public abstract void last();
    }
    

    (2)定义Cake类

    public class Cake extends Template {
    
    	@Override
    	public void pre() {
    		System.out.println("cake pre");
    	}
    
    	@Override
    	public void dojob() {
    		System.out.println("cake dojob");
    	}
    
    	@Override
    	public void last() {
    		System.out.println("cake alst");
    	}
    
    }
    

    (3)定义Bread类

    public class Bread extends Template {
    
    	@Override
    	public void pre() {
    		System.out.println("Bread pre");
    	}
    
    	@Override
    	public void dojob() {
    		System.out.println("Bread dojob");
    	}
    
    	@Override
    	public void last() {
    		System.out.println("Bread last");
    	}
    
    }
    

    (4)定义模板模式测试类

    public class TemplateTest {
    public static void main(String[] args) {
    	Template template=new Cake();
    	template.dodish();
        Template template2=new Bread();
        template2.dodish();
    }
    

    测试结果:

    cake pre
    cake dojob
    cake alst
    Bread pre
    Bread dojob
    Bread last
    

    模板模式在实际项目运用中很容易和策略模式混淆,主要是看完成一个事情是不是分多个步骤,而且都需要延迟到子类中完成。如果只有一个步骤那么就可考虑采用策略模式。
    (7)策略模式
    定义:将一组算法封装到鞠具有共同接口的独立的类中。
    类图:
    在这里插入图片描述
    (1)实现Strategy接口

    public interface Strategy {
    	void calc(int num1,int num2);
    }
    

    (2)实现AddStrategy

    public class AddStrategy implements Strategy{
    	@Override
    	public void calc(int num1, int num2) {
    		System.out.println("和: "+(num1+num2));
    	}
    }
    

    (3)实现SubStrategy

    public class SubStrategy implements Strategy {
    	@Override
    	public void calc(int num1, int num2) {
    		System.out.println("减: "+(num1 - num2));
    	}
    }
    

    (4)新建测试类

    public class testStrategy {
    	public static void main(String[] args) {
    		Strategy strategy = new AddStrategy();
    		strategy.calc(3, 2);
    		Strategy strategy2 = new SubStrategy();
    		strategy2.calc(3, 2);
    	}
    }
    

    测试结果:

    和: 5
    减: 1
    

    策略模式的应用
    策略模式在系统中用的比较多,就个人目前的经验来看已经在2个大型系统的核心模块中使用了,一个是费用报销系统中生成凭证,这里不同的报账类型生成凭证的算法是不一样,但都可以抽象为生成凭证;另外一种是在一个考核系统中不同的考核指标计算考核分数是不一样的,但都可以抽象为绩效考核分数计算,在实际的运用中会比较复杂,就绩效考核项目中由于数据源不一致还采用了泛型。
    (8)观察者模式
    定义:观察者模式定义了一个一对多的依赖关系,让一个或多个观察者对象监听一个主题对象。这样一来,当被观察者状态发生改变时,需要通知相应的观察者,使这些观察者对象能够自动更新。
    类图:
    在这里插入图片描述观察者模式的实现:
    (1)新建一个Observer,Observer是观察者对象的接口

    public interface Observer {
    	void update(float price);
    }
    

    (2)新建一个Person,Person为观察者实际对象

    public class Person implements Observer {
    	private String name;
    
    	public Person(String name) {
    		this.name = name;
    	}
    
    	@Override
    	public void update(float price) {
    		System.out.println(name + "价格更新为:" + price);
    	}
    }
    

    (3)新建一个被观察者对象接口Observable

    public interface Observable {
    	// 注册一个观察者
    	public void registerObserver(Observer observer);
    
    	// 取消观察者
    	public void removeObserver(Observer observer);
    
    	// 通知所有观察者
    	public void notifyObservers();
    }
    

    (4)新建一个被观察者实际对象Cup

    public class Cup implements Observable {
    	// 被观察者对象
    	private Vector<Observer> vector = new Vector<>();
    	private float price;
    
    	public Cup(float price) {
    		this.price = price;
    	}
    
    	public float getPrice() {
    		return price;
    	}
    
    	public void setPrice(float price) {
    		this.price = price;
    		notifyObservers();
    	}
    
    	// 注册观察者
    	@Override
    	public void registerObserver(Observer observer) {
    		vector.add(observer);
    	}
    
    	// 删除观察者
    	@Override
    	public void removeObserver(Observer observer) {
    		vector.remove(observer);
    	}
    
    	// 通知观察者
    	@Override
    	public void notifyObservers() {
    		for (Observer observer : vector) {
    			observer.update(price);
    		}
    
    	}
    
    }
    

    (5)新建一个观察者模式测试类ObserverTest

    public class ObserverTest {
    	public static void main(String[] args) {
    		// 创建一个被观察者对象
    		Cup cup = new Cup(30);
    		// 创建2个观察者
    		Person person1 = new Person("person1");
    		Person person2 = new Person("person2");
    		// 注册观察者
    		cup.registerObserver(person1);
    		cup.registerObserver(person2);
    		// 价额变动通知观察者
    		cup.setPrice(2);
    	}
    }
    

    (9)委托模式
    定义:有两个对象参与处理同一个请求,接受请求的对象将请求委托给另一个对象来处理。
    简单委托模式实现:
    (1)新建RealPrinter

    public class RealPrinter {
    	public void print() {
    		System.out.println("RealPrinter is run");
    	}
    }
    

    (2)新建Printer类

    public class Printer {
    	RealPrinter realPrinter = new RealPrinter();
    
    	public void print() {
    		realPrinter.print();
    	}
    }
    

    (3)新建Test类

    public class Test {
    	public static void main(String[] args) {
    		Printer printer = new Printer();
    		printer.print();
    	}
    }
    

    执行结果:

    RealPrinter is run
    

    以上只是简单介绍了常用的设计模式的类图,并根据类图给出了一定的实例和应用的场景,在实际的运用中情况可能会很复杂,比如多个设计模式联合使用,例如工厂模式+策略模式一起用来解决一组算法问题等等,所以我们需要对常用的设计模式比较了解,然后才能做到在项目中灵活运用,好的代码结构是需要不停雕琢的。本次设计模式的讲解就到此为止,不足之处还请大家批评指正。本文在写作过程中借鉴了其他博客的内容,没有一一列出,在此表示感谢。
    未完待续,下一篇会重点介绍不同设计模式的比较。

    展开全文
  • 常用设计模式

    万次阅读 多人点赞 2020-06-29 21:41:01
    设计模式 从程序的结构上实现松耦合,从而可以扩大整体的类结构,用来解决更大的问题。 设计模式的本质是面向对象设计原则的实际运用,是对类的封装性、继承性和多态性以及类的关联和组合关系的充分理解。 正确使用...
  • Java常见设计模式总结

    万次阅读 多人点赞 2021-09-18 17:18:54
    设计模式是一套经过反复使用的代码设计经验,目的是为了重用代码、让代码更容易被他人理解、保证代码可靠性。设计模式于己于人于系统都是多赢的,它使得代码编写真正工程化,它是软件工程的基石,如同大厦的一块块...
  • unity 常用设计模式

    千次阅读 2020-12-23 15:59:04
    一、单例模式 ...缺点:容易形成依赖,忽略与其他设计模式的协作。 Unity的两种单例模式 继承MonoBehaviour的单例 using System.Collections; using System.Collections.Generic; using UnityEngine;
  • java常用8种 设计模式

    千次阅读 2022-02-28 21:47:09
    文章目录前言一、设计模式需遵守:7大基本原则1.单一职责原则【单一职责原则注意事项和细节】2.接口隔离原则3.依赖倒置原则【依赖传递方式】【依赖倒置原则注意事项和细节】4.里式替换原则5.开放封闭原则6.迪米特...
  • Java常用设计模式及应用场景介绍

    千次阅读 2021-07-05 09:14:19
    主要培养常用设计模式和代码抽取优化能力,可能涉及6大设计原则23种设计模式,今天简单介绍集中。 设计模式是被编程者总结出来的一套被反复使用的、多数人知晓的、经过分类编目的代码设计经验。掌握常用的设计模式...
  • spring框架中常用到的8种设计模式清单如下:设计模式使用地方备注工厂模式BeanFactory ApplicationContext单例模式Spring中的Bean代理模式Spring AOPjava反射实现动态代理模板方法模式Spring中以Template结尾的类...
  • Java中的23种设计模式:Java中的23种设计模式常见的几种设计模式:1、工厂模式2、单例模式3、代理模式4、观察者模式5、适配器模式介绍实现6、命令模式介绍实现 Java中的23种设计模式 Factory(工厂模式), Builder...
  • 常用的几种设计模式详解

    千次阅读 2021-04-09 15:01:27
    设计模式的概述 设计模式分类 创建型模式 特点是将对象的创建与使用分离(解耦),有 单例、原型、工厂方法、抽象工厂、建造者等5种。 结构型模式 用于描述如何将类或对象按某种布局组成更大的结构,代理、...
  • PHP常用六大设计模式

    千次阅读 2021-06-16 11:28:26
    介绍16个常用设计模式的基础概念和技术要点,通过UML类图帮助理解设计模式中各个类之间的关联关系,针对每种设计模式都使用PHP完成了一个代码示例,让你跟随实例轻松入门设计模式。 提示:以下是本篇文章正文内容...
  • 常用设计模式及其 Java 实现

    千次阅读 2018-08-05 14:06:05
    本文按照创建型、结构型、行为型三大类,总结了常见的 24 种设计模式的使用要点,包括适用场景、解决方案、及其相应的 Java 实现。 作者:王克锋 出处:https://kefeng.wang/2018/04/16/design-patterns/ 版权...
  • java常用设计模式及其使用场景

    千次阅读 2020-12-13 16:18:39
    设计模式的使用场景。 设计模式分为3大类型共23种: 创建型:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。 结构型:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元...
  • 常用设计模式总结

    万次阅读 多人点赞 2019-07-31 19:13:12
    设计模式(Design pattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结,是可复用面向对象软件的基础。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性。 ...
  • 一文打尽设计模式(C++实现)

    千次阅读 2020-12-25 22:54:33
    23设计模式一文打尽,每种模式包括应用场景,优缺点,模式结构,类图 以及 C++代码示例。介绍设计模式是什么,有什么作用以及由来。
  • 设计模式-单例模式(五种实现方法详解)

    千次阅读 多人点赞 2020-11-27 00:12:53
    单例模式,属于创建类型的一种常用的软件设计模式。通过单例模式的方法创建的类在当前进程中只有一个实例(根据需要,也有可能一个线程中属于单例,如:仅线程上下文内使用同一个实例)。就是采取一定的方法保证在...
  • 前端开发中常用的几种设计模式

    万次阅读 多人点赞 2021-08-17 15:05:54
    设计模式更多的是指导思想和方法论,而不是现成的代码,当然每种设计模式都有每种语言中的具体实现方式。学习设计模式更多的是理解各种模式的内在思想和解决的问题,毕竟这是前人无数经验总结成的最佳实践,而代码...
  • Java中常用设计模式

    万次阅读 多人点赞 2019-03-15 17:25:14
    一、什么是设计模式 设计模式(Design pattern)是一套被反复使用、多数人知晓的、... 毫无疑问,设计模式于己于他人于系统都是多赢的,设计模式使代码编制真正工程化,设计模式是软件工程的基石,如同大厦的一块...
  • C++各类设计模式及实现详解

    万次阅读 多人点赞 2017-08-19 10:18:46
    总结了网上一些设计模式资料。  软件领域中的设计模式为开发人员提供了一种使用专家设计经验的有效途径。设计模式中运用了面向对象编程语言的重要特性:封装、继承、多态,真正领悟设计模式的精髓是可能一个漫长的...
  • 快速梳理23种常用设计模式

    千次阅读 多人点赞 2018-11-17 22:54:34
    本文旨在快速梳理常用设计模式,了解每个模式主要针对的是哪些情况以及其基础特征,每个模式前都有列举出一个或多个可以深入阅读的参考网页,以供读者详细了解其实现。 快速回忆 一、创建型 单例(Singleton...
  • 1 代理模式 1.1 文件服务应用 1.2 分布式文件代理服务器实现 1.2.1 实现分析 1.2.2 代码实现 2 享元模式 2.1 用户信息共享实现 2.1.1 会话跟踪分析 2.1.2 代码实现 3 装饰者模式 3.1 结算价格嵌套运算 3.1.1 订单...
  • Android中常用设计模式

    千次阅读 2018-05-04 14:41:04
    Android开发中常见的设计模式Android中常见的设计模式Android设计模式之23种设计模式一览Android中常用设计模式二:然后总结一下其总结内容多根据参考文献文档而来,还请了解文档内容(一)什么是设计模式1....
  • Java设计模式 --- 七大常用设计模式示例归纳

    万次阅读 多人点赞 2018-10-07 16:35:24
    设计模式分为三种类型,共23种: 创建型模式:单例模式、抽象工厂模式、建造者模式、工厂模式、原型模式 结构型模式:适配器模式、桥接模式、装饰模式、组合模式、外观模式、享元模式、代理模式 行为型...
  • C++常用的11种设计模式

    千次阅读 多人点赞 2021-03-08 01:42:15
    这里写目录标题工厂模式单例模式(懒汉式、饿汉式)适配器模式外观模式代理模式包装模式(装饰器模式)桥接模式模板方法模式策略模式观察者模式责任链模式 工厂模式 定义:将工厂变成一个抽象类,在里面定义一个纯虚...
  • 用Python实现9种常用设计模式

    千次阅读 2019-06-27 18:45:48
    这里总结9种常见的设计模式作为参考,并用Python实现设计模式分类 点击链接跳转: 创建型设计模式 单例模式 工厂模式 结构型设计模式 门面模式 代理模式 行为型设计模式 命令模式 模板方法模式 观察者...
  • Java中常用设计模式【模板模式】

    千次阅读 2022-02-26 15:27:50
    【本专栏的代码都放在:Java中常用的几种设计模式】 在模板模式(Template Pattern)中,一个抽象类公开定义了执行它的方法的方式/模板。它的子类可以按需要重写方法实现,但调用将以抽象类中定义的方式进行。这种...
  • 前端常用几种设计模式

    千次阅读 2021-06-01 19:50:01
    工厂模式是用来创建对象的一种最常用设计模式,不暴露创建对象的具体逻辑,而是将逻辑封装在一个函数中,那么这个函数就可以被视为一个工厂,工厂模式根据抽象程度的不同可以分为:简单工厂,工厂方法和抽象工厂,...
  • Java常用10种设计模式详解

    万次阅读 多人点赞 2018-08-14 17:06:46
    一、单例模式 单例模式属于创建型模式,解决某个类频繁的创建与销毁。该模式保证了其对象在JVM中只有一个实例对象存在。必须保证私有化构造函数,只能有一个实例对象存在。 优点: 减少new关键字的使用,降低...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 492,163
精华内容 196,865
热门标签
关键字:

常用设计模式及实现