常见设计模式(工厂模式、抽象工厂模式、代理模式、观察者模式)

设计模式
  • 设计模式(Design pattern)代表了最佳的实践,通常被有经验的面向对象的软件开发人员所采用。设计模式是软件开发人员在软件开发过程中面临的一般问题的解决方案,这些解决方案是众多软件开发人员经过相当长的一段时间的试验和错误中总结出来的。

  • 序号模式&描述包括
    1创建性模式(对象怎么来)
    这些设计模式提供了一种在创建对象的同时隐藏常见逻辑的方式,而不是使用new运算符直接实例化对象。这使得程序在判断针对某个给定示例需要创建哪些对象时更加灵活。
    工厂模式(Factory Pattern) 抽象工厂模式(Abstract Factory Pattern) 单例模式(Singleton Pattern) 建造者模式(Builder Pattern) 原型模式(Prototype Pattern)
    2结构型模式(对象和谁有关)
    这些设计模式关注类和对象的组合。继承的概念被用来组合接口和定义组合对象获得新功能的方式。
    适配器模式(Adapter Pattern) 桥接模式(Bridge Pattern) 过滤器模式(Filter、Criteria Pattern) 组合模式(Composite Pattern) 装饰器模式(Decorator Pattern) 外观模式(Facade Pattern) 享元模式(Flyweight Pattern) 代理模式(Proxy Pattern)
    3行为型模式(对象与对象在干什么)
    这些设计模式特别关注对象之间的通信。
    责任链模式(Chain of Responsibility Pattern) 命令模式(Command Pattern) 解释器模式(Interpreter Pattern) 迭代器模式(Iterator Pattern) 中介者模式(Mediator Pattern) 备忘录模式(Memento Pattern) 观察者模式(Observer Pattern) 状态模式(State Pattern) 空对象模式(Null Object Pattern) 策略模式(Strategy Pattern) 模板模式(Template Pattern) 访问者模式(Visitor Pattern)
    4J2EE 模式(对象合起来在干什么)
    这些设计模式特别关注表示层。这些模式是由 Sun Java Center 鉴定的。
    MVC 模式(MVC Pattern) 业务代表模式(Business Delegate Pattern) 组合实体模式(Composite Entity Pattern) 数据访问对象模式(Data Access Object Pattern) 前端控制器模式(Front Controller Pattern) 拦截过滤器模式(Intercepting Filter Pattern) 服务定位器模式(Service Locator Pattern) 传输对象模式(Transfer Object Pattern)
  • 设计模式的六大原则

    1. 开闭原则(Open Close Principle)(实现热插拔,提高扩展性)

      开闭原则的意思是:对扩展开放,对修改关闭。在程序需要进行拓展的时候,不要去修改原有的代码,实现一个热插拔的效果。简言之,就是为了是程序的扩展性好,易于维护和升级。想要达到这样的效果,我们需要使用接口和抽象类。

    2. 里氏代换原则(Liskov Substitution Principle)(实现抽象的规范,实现子父类互相替换)

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

    3. 依赖倒转原则(Dependence Inversion Principle)(针对接口编程,实现开闭原则的基础)

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

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

      含义:使用多个隔离的接口,比使用单个接口要好。另外一个意思是:降低类之间的耦合度。他强调降低依赖,降低耦合

    5. 迪米特原则,又称最少知道原则(Demeter Principle)

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

    6. 最少复用原则(Composite Reuse Principle)

      含义:尽量使用合成 / 聚合的方式,而不是使用继承。

工厂模式
  • 属于创建性模式,他提供了一种创建对象的最佳方式。在创建对象时不会对客户端暴露创建逻辑,并且是通过一个共同的接口来指向新创建的对象

  • 介绍:

    • 意图:定义一个创建对象的接口,让其子类自己决定实例化哪一个工厂类,会使其创建过程延迟到子类进行。
    • 主要解决:主要解决接口选择的问题。
    • 如何解决:让其子类实现工厂接口,返回的也是一个抽象的产品。
    • 关键代码:创建过程在其子类执行。
    • 优点:
      • 一个调用者想创建一个对象,只要知道器名称就可以了。
      • 扩展性高,如果想增加一个产品,只要扩展一个工厂类就可以了。
      • 屏蔽产品的具体实现,调用者只关心产品的接口。
    • 缺点:每次增加一个产品时,都需要增加一个具体类和对象实现工厂,使得系统中类的个数成倍增加,在一定程度上增加了系统的复杂度,同时也增加了系统具体类的依赖。这并不是什么好事。
    • 使用场景:
      • 日志记录器:记录可能记录到本地硬盘、系统时间、远程服务器等等。
      • 数据库访问:当用户不知道最后系统采用哪一类数据库,以及数据库可能有变化时。
    • 注意事项:作为一种创建类模式,在任何时候要生成复杂对象的地方,都可以使用工厂方法模式。有一点需要注意的地方就是复杂对象适合使用工厂模式,而简单对象,特别是只需要 new 就可以完成创建的对象,无需使用工厂模式。如果使用工厂模式,就需要你引入一个工厂类,会增加系统的复杂度。
  • Factory_Pattern.java

    //1. 创建一个接口
    interface Person {
    	// 人类都具有吃的方法
    	public void eat();
    }
    //2. 创建实现接口的实体类
    class Chinese implements Person {
    	@Override
    	public void eat() {
    		System.out.println("中国人用筷子吃饭");
    	}
    }
    
    class American implements Person {
    	@Override
    	public void eat() {
    		System.out.println("美国人用刀和叉子吃饭");
    	}
    }
    
    class Indian implements Person {
    	@Override
    	public void eat() {
    		System.out.println("印度人用手吃饭");
    	}
    }
    //3. 创建一个获取实例的接口
    interface Instance {
    	public Person getInstance(String str);
    }
    //4. 创建工厂,实现获取实例的接口
    class Factory implements Instance {
    	@Override
    	public Person getInstance(String str) {
    		if ("Chinese".equals(str)) {
    			return new Chinese();
    		} else if ("American".equals(str)) {
    			return new American();
    		} else if ("Indian".equals(str)) {
    			return new Indian();
    		} else {
    			return null;
    		}
    	}
    }
    //5.主方法
    public class Factory_Pattern {
    	public static void main(String[] args) {
            //使用该工厂,通过传递消息来获取实体类的对象
    		Factory factory = new Factory();
    		
    		Person chinese = factory.getInstance("Chinese");
    		chinese.eat();
    
    		Person american = factory.getInstance("American");
    		american.eat();
    
    	}
    }
    
    
  • 程序输出:

    中国人用筷子吃饭
    美国人用刀和叉子吃饭
    
  • 补充:可以使用枚举类优化,以防止类名输入错误

  • 另补充:

    一、一句话概括工厂模式

    • 简单工厂:一个工厂类,一个产品抽象类。
    • 工厂方法:多个工厂类,一个产品抽象类。
    • 抽象工厂:多个工厂类,多个产品抽象类。

    二、生活中的工厂模式

    • 简单工厂类:一个麦当劳店,可以生产多种汉堡。
    • 工厂方法类:一个麦当劳店,可以生产多种汉堡。一个肯德基店,也可以生产多种汉堡。
    • 抽象工厂类:百胜餐饮集团下有肯德基和百事公司,肯德基生产汉堡,百事公司生成百事可乐。
抽象工厂模式
  • 是围绕一个超级工厂创建其他工厂的,该超级工厂又称为其他工厂的工厂。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。接口是负责创建一个相关对象的工厂,不需要显示地指定它们的类。每个生成的工厂都能按照工厂模式提供对象。

  • 介绍:

    • 意图:提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
    • 主要解决:接口选择的问题
    • 如何使用:系统的产品有多于一个的产品族,而系统只消费其中某一族的产品。
    • 如何解决:在一个产品族里面,定义多个产品。
    • 关键代码:在一个工厂里聚合多个同类的产品
    • 优点:当一个产品族中的多个对象被设计成一起工作时,它能保证客户端始终只使用相同一个产品族中的对象。
    • 缺点:产品组扩展非常困难,要增加一个系列的某一个产品,既要保证抽象的Creator里加代码,又要在具体的里面加代码。
    • 使用场景:
      • QQ换皮肤,一整套一起换
      • 生成不同操作系统的程序
    • 注意事项:产品族难扩展,产品等级易扩展。
  • Abstract_Factory_Pattern.java

    //1.为形状创建一个接口
    interface Shape {
    	public void draw();
    }
    
    // 2. 创建实现形状接口的实体类(3个)
    class Rectangle implements Shape {
    	@Override
    	public void draw() {
    		System.out.println("矩形的画画方法");
    	}
    }
    
    class Square implements Shape {
    	public void draw() {
    		System.out.println("正方形的画画方法");
    	}
    
    }
    
    class Circle implements Shape {
    	@Override
    	public void draw() {
    		System.out.println("圆的画画方法");
    	}
    }
    
    //3. 创建一个颜色的接口
    interface Color {
    	public void fill();
    }
    
    //4. 创建颜色接口的实现类(3个)
    class Red implements Color {
    	@Override
    	public void fill() {
    		System.out.println("红色");
    	}
    }
    
    class Blue implements Color {
    	@Override
    	public void fill() {
    		System.out.println("蓝色");
    	}
    }
    
    class Green implements Color {
    	@Override
    	public void fill() {
    		System.out.println("绿色");
    	}
    }
    
    //5. 为 Shape 和 Color 对象创建 抽象类 来获取工厂
    abstract class AbstractFactory {
    	public abstract Color getColor(String color);
    
    	public abstract Shape getShape(String shape);
    }
    
    //6. 创建 扩展了 AbstractFactory 的工厂类,基于给定的信息生成实体类的对象
    class ShapeFactory extends AbstractFactory {
    
    	@Override
    	public Shape getShape(String shape) {
    
    		if (shape.equals("Circle")) {
    			return new Circle();
    		} else if (shape.equals("Square")) {
    			return new Square();
    		} else if (shape.equals("Rectangle")) {
    			return new Rectangle();
    		} else {
    			return null;
    		}
    	}
    
    	@Override
    	public Color getColor(String color) {
    		return null;
    	}
    
    }
    
    class ColorFactory extends AbstractFactory {
    
    	@Override
    	public Color getColor(String color) {
    		if (color.equals("Red")) {
    			return new Red();
    		} else if (color.equals("Green")) {
    			return new Green();
    		} else if (color.equals("Blue")) {
    			return new Blue();
    		} else {
    			return null;
    		}
    
    	}
    
    	@Override
    	public Shape getShape(String shape) {
    		return null;
    	}
    }
    
    //7. 创建一个超级工厂(工厂生成器),通过传形状或者颜色信息来获取工厂
    class FactoryProducer {
    	public static AbstractFactory getFactory(String choice) {
    		if ("Shape".equals(choice)) {
    			return new ShapeFactory();
    		} else if ("Color".equals(choice)) {
    			return new ColorFactory();
    		} else {
    			return null;
    		}
    	}
    }
    
    // 测试类
    public class Abstract_Factory_Pattern {
    	public static void main(String[] args) {
    		// 获取形状工厂
    		AbstractFactory shapeFactory = FactoryProducer.getFactory("Shape");
    		// 获取形状为 Circle 的对象
    		Shape circle = shapeFactory.getShape("Circle");
    		circle.draw();
    
    		Shape square = shapeFactory.getShape("Square");
    		square.draw();
    
    		// 获取颜色工厂
    		AbstractFactory colorFactory = FactoryProducer.getFactory("Color");
    		//获取颜色为 Red 的对象
            Color red = colorFactory.getColor("Red");
    		red.fill();
    
    		Color blue = colorFactory.getColor("Blue");
    		blue.fill();
    	}
    }
    
    
  • 输出结果

    圆的画画方法
    正方形的画画方法
    红色
    蓝色
    
代理模式
  • 一个类代表另一个类的功能。这种类型的设计模式属于结构性模式。在代理模式中,我们创建具有现有对象的对象,以便向外界提供功能接口。

  • 介绍

    • 意图:为其他对象提供一种代理以控制对这个对象的访问。
    • 主要解决:在直接访问对象时带来的问题,比如:要访问的对象在远程的服务器上。在面向对象系统中,有些对象由于某些原因(对象创建开销很大、某些操作需要安全控制、需要进程外的访问 等),直接访问会给使用者或者系统带来很多麻烦,我们可以在访问此对象时加上一个对此对象的访问层。
    • 何时使用:想在访问一个类时做一些控制。
    • 如何解决:增加中间层。
    • 关键代码:实现与被代理类组合。
    • 应用实例:
      1. windows里面的快捷方式;
      2. spring aop;
      3. 买火车票不一定在火车站买,也可以去代售点买;
      4. 一直支票或者银行存单是账户中资金的代理。
    • 优点:
      • 职责清晰
      • 高扩展性
      • 智能化
    • 缺点:
      • 由于在客户端和真实主题之间增加了代理对象,因此有些类型的代理模式可能会造成请求的处理速度变慢
      • 实现代理模式需要额外的工作,有些代理模式的实现非常复杂。
    • 注意事项:
      • 和适配器模式的区别:适配器模式主要改变所考虑对象的接口,而代理模式不能改变所代理类的接口
      • 和装饰器模式的区别:装饰器模式为了增强功能,代理模式是为了加以控制。
    • Proxy_Pattern
    //1. 创建一个图片接口
    interface Image {
    	void dispaly();
    }
    
    // 2.创建实现接口的实体类
    class RealImage implements Image {
    	private String fileName;
    
    	public RealImage() {
    	}
    
    	public RealImage(String fileName) {
    		this.fileName = fileName;
    		loadFromDisk(fileName);
    	}
    
    	private void loadFromDisk(String fileName) {
    		System.out.println("load:" + fileName);
    
    	}
    
    	@Override
    	public void dispaly() {
    		System.out.println("display:" + fileName);
    	}
    }
    
    class ProxyImage implements Image {
    
    	private RealImage realImage;
    	private String fileName;
    
    	public ProxyImage() {
    	}
    
    	public ProxyImage(String fileName) {
    		this.fileName = fileName;
    	}
    
    	@Override
    	public void dispaly() {
    		if (realImage == null) {
    			realImage = new RealImage(fileName);
    		}
    		realImage.dispaly();
    	}
    }
    
    // 3.当被请求时,使用ProxyImage 来获取 RealImage类的对象
    public class Proxy_Pattern {
    	public static void main(String[] args) {
    		Image image = new ProxyImage("test.png");
    
    		//第一次调用display需要初始化RealImage
    		image.dispaly();
    		System.out.println();
    		//第二次就不需要了
    		image.dispaly();
    	}
    }
    
    
    • 输出结果
    load:test.png
    display:test.png
    
    display:test.png
    
观察者模式
  • 当对象存在一对多关系时,则使用观察者模式。比如,当一个对象被修改,则会自动通知他的依赖。观察者模式输入行为型模式。

  • 介绍:

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

    • 主要解决:一个对象状态改变给其他对象通知的问题,而且要考虑到易用和低耦合,保证高度的协作。

    • 何时使用:一个对象(目标对象)的状态发生改变,所有的依赖对象(观察者对象)都将得到通知,进行广播通知。

    • 如何解决:使用面向对象技术,可以将这种依赖关系弱化。

    • 关键代码:在抽象类里有一个 ArrayList 存放观察者们。

    • 应用实例:拍卖的时候,拍卖师观察最高标价,然后通知其他竞价者竞价。

    • 优点

      1. 观察者和被观察者是抽象耦合的。
      2. 建立一套触发机制
    • 缺点:

      1. 如果一个被观察者对象有很多的直接和间接的观察者的话,将所有观察者都通知到的话会花费很多时间。
      2. 如果观察者和观察目标之间有循环依赖的话,观察目标会触发他们之间进行循环调用,可能导致系统崩溃。
      3. 观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化。
    • 注意事项

      • Java中已经有了对观察者模式的支持类
      • 避免循环调用
      • 如果顺序执行,某一观察者错误会导致系统卡壳,一般采用异步方式。
    • 这个的代码没有看明白,不贴了

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值