关于设计模式:浅谈设计模式-状态模式十三

浅谈设计模式 - 状态模式(十三)前言 状态模式其实也是一个非常常见的模式,最常见的利用场景是线程的状态切换,最常应用的形式就是对于If/else进行解耦,另外这个模式能够配合 责任链模式组合搭配出各种不同的状态切换成果,能够用设计模式模仿一个简略的“工作流”。 优缺点: 状态模式非常明显的是用于解耦大量If/else的模式,所以他的长处非常突出,就是能够简化大量的if/else判断,然而毛病页非常显著,那就是程序的执行受限于状态,如果状态的常量十分多的状况下,仍然会呈现大量的if/else的景象,状态模式和策略模式一样一旦状况十分复杂的时候很容易造成类的收缩,当然少数状况下这种毛病简直能够疏忽,总比太多。 对于状态模式在jdk1.8之后的lambada表达式中能够有体现,lambada实现了java的参数“办法化”,这样极大地简化了类的收缩,然而可能比拟难以了解,并且一旦简单仍然倡议应用状态来实现切换,这样更不便保护。 状态模式的结构图: 上面是状态模式的结构图,自身比较简单,仿佛并没有什么特地的中央,然而当咱们和“策略模式”比照之后,仿佛很容易混同,上面咱们来看下这两个结构图的比照: 状态模式结构图: 策略模式结构图: 通过比照能够看到,状态和策略这两个模式是十分相似的,那么咱们应该如何辨别这两个模式呢?在平时的开发工作中,如果一个对象有很多种状态,并且这个对象在不同状态下的行为也不一样,那么咱们就能够应用状态模式来解决这个问题,然而如果你让同一事物在不同的时刻有不同的行为,能够应用策略模式触发不同的行为。打个比方,如果你想让开关呈现不同的行为,你须要设计两个状态开关,而后在事件处理的时候将逻辑散发到不同的状态实现触发,而如果你想要实现相似商品的折扣或者优惠促销,满减等等“模式”的时候更加适宜应用策略,当然如果无奈辨别也没有关系,哪个应用更为纯熟即可。 案例:糖果机 这是《head first设计模式》中对于状态模式案例当中的糖果机,咱们能够从上面的图中看到如果应用单纯的代码来实现上面的工作,就会呈现十分多难堪的状况,比方大量繁冗的if/else代码充斥,上面咱们来看下对于这个糖果机依照一般的形式要如何设计? 不应用设计模式 不应用设计模式的状况下,咱们通常的做法是定义状态常量,比方设置枚举或者间接设置final的标示位等等,咱们 首先咱们须要划分对象,糖果机和糖果,糖果机蕴含硬币的总钱数,糖果的数量等等。 定义四个状态:售罄,售出中,存在硬币,没有硬币为了实现状态的实现,咱们须要设计相似枚举的常量来示意糖果机的状态。 状态设置为常量,而糖果机须要内置机器的状态最初用逻辑代码和判断让糖果机外部进行工作,当然这会呈现巨多的if/else判断。 最初咱们的代码表现形式如下,用传统的模式咱们很可能写出相似的代码: MechanicaState:定义了糖果机的状态,当然能够作为糖果机的公有外部类定义应用,也能够设计为枚举,这里偷懒设计为一个常量类的模式。 /** * 机器状态 */public final class MechanicaState { /** * 售罄 */ public static final int SOLD_OUT = 0; /** * 存在硬币 */ public static final int HAS = 1; /** * 没有硬币 */ public static final int NOT = 2; /** * 售出糖果中 */ public static final int SOLD = 4;} CandyMechaica:糖果器,蕴含了糖果外部的工作办法,能够看到有十分多冗余的If/else判断: ...

November 5, 2021 · 3 min · jiezi

关于设计模式:俺就因为把int改成Integer第2天被辞了

本文节选自《设计模式就该这样学》之享元模式(Flyweight Pattern)1 故事背景一个程序员就因为改了生产环境上的一个办法参数,把int型改成了Integer类型,因为波及到钱,后果上线之后公司损失惨重,程序员被解雇了。信不信持续往下看。先来看一段代码: public static void main(String[] args) { Integer a = Integer.valueOf(100); Integer b = 100; Integer c = Integer.valueOf(129); Integer d = 129; System.out.println("a==b:" + (a==b)); System.out.println("c==d:" + (c==d));}大家猜它的运行后果是什么?在运行完程序后,咱们才发现有些不对,失去了一个意想不到的运行后果,如下图所示。 看到这个运行后果,有人就肯定会问,为什么是这样?之所以失去这样的后果,是因为Integer用到的享元模式。来看Integer的源码, public final class Integer extends Number implements Comparable<Integer> { ... public static Integer valueOf(int i) { if (i >= IntegerCache.low && i <= IntegerCache.high) return IntegerCache.cache[i + (-IntegerCache.low)]; return new Integer(i); } ...}再持续进入到IntegerCache的源码来看low和high的值: private static class IntegerCache { // 最小值 static final int low = -128; // 最大值,反对自定义 static final int high; // 缓存数组 static final Integer cache[]; static { // 最大值能够通过属性配置来扭转 int h = 127; String integerCacheHighPropValue = sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high"); // 如果设置了对应的属性,则应用该值 if (integerCacheHighPropValue != null) { try { int i = parseInt(integerCacheHighPropValue); i = Math.max(i, 127); // 最大数组大小为Integer.MAX_VALUE h = Math.min(i, Integer.MAX_VALUE - (-low) -1); } catch( NumberFormatException nfe) { // If the property cannot be parsed into an int, ignore it. } } high = h; cache = new Integer[(high - low) + 1]; int j = low; // 将low-high范畴内的值全副实例化并存入数组中当缓存应用 for(int k = 0; k < cache.length; k++) cache[k] = new Integer(j++); // range [-128, 127] must be interned (JLS7 5.1.7) assert IntegerCache.high >= 127; } private IntegerCache() {}}由上可知,Integer源码中的valueOf()办法做了一个条件判断,如果目标值在-128 - 127,则间接从缓存中取值,否则新建对象。其实,Integer第一次应用的时候就会初始化缓存,其中范畴最小值为-128,最大值默认是127。接着会把low至high中所有的数据初始化存入数据中,默认就是将-128 - 127总共256个数循环实例化存入cache数组中。精确的说应该是将这256个对象在内存中的地址存进数组中。这里又有人会问了,那为什么默认是-128 - 127,怎么不是-200 - 200或者是其余值呢?那JDK为何要这样做呢? ...

November 2, 2021 · 3 min · jiezi

关于设计模式:软件设计七大原则

开闭准则依赖倒置准则繁多职责准则接口隔离准则迪米特法令里氏替换准则合成复用准则 代码开发遵循设计准则,使代码构造有条理且易于扩大和保护。并不需要僵硬地依照软件设计准则去实现,而是依据不同的场景,选取比拟适合的设计准则。 开闭准则含意:一个软件实体,如类、模块和函数要对扩大凋谢,对批改敞开。在一个根底类上要减少性能时,不要去批改类中的代码,而是新增类继承根底类,在新增类中减少性能。 示例: 一般计算器反对加减乘除 public class GeneralCalculator { public int add(int x, int y){ return x + y; } public int sub(int x, int y){ return x - y; } public int mul(int x, int y){ return x * y; } public int div(int x, int y){ return x / y; }}迷信计算器反对幂运算和一般运算 public class ScientificCalculator extends GeneralCalculator { public int power(int x, int y){ if (x == 0){ return 0; } if (y == 0){ return 1; } int sum = 1; for (int i = 0; i < y; i++) { sum = mul(sum, x); } return sum; }}类图: ...

November 1, 2021 · 3 min · jiezi

关于设计模式:经典设计模式之动态代理

为什么要学习设计模式?设计模式在很多源码框架中广泛应用,如果不理解设计模式,间接看源码必定一头雾水。那我不看源码行不行?行,除非你有其余更好的倒退方向或者始终做一个高级。不然源码是绕不过来的,你不理解它,它对你来说就是一个黑盒子。 怎么学习设计模式?网上学习教程很多,大多数讲一些demo。我在学习的过程中,甚至有的把很简略的货色讲得超级简单。个别是简略类图+demo+源码+理论场景中的利用联合来学习。尽可能找到走心的老师。 什么是动静代理?mybatis谁都会用,然而为啥一个定义一个接口,没有实例能够间接调用?起因是java外部主动生成了一个实例。 怎么写?咱们先找到java.lang.reflect包下的Proxy对象,调用它的newProxyInstance办法;;点进去看到,须要三个参数,别离是类加载器,类数组,以及Invocation接口; vm参数-Dsun.misc.ProxyGenerator.saveGeneratedFiles=true package disign.pattern;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;/** * 动静代理 */public class DynamicProxy { interface DynamicProxyInterface { void sayHello(); } public static void main(String[] args) { ClassLoader loader = DynamicProxy.class.getClassLoader(); Class<?>[] interfaces = new Class[]{DynamicProxyInterface.class}; DynamicProxyInterface dynamicProxyInterface = (DynamicProxyInterface) Proxy.newProxyInstance(loader, interfaces, new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("sayHello"); return null; } }); dynamicProxyInterface.sayHello(); }}这图一放调用链路是不是很清晰,$Proxy0外部保护了InvocationHandler接口,最终调用还是匿名外部类实现的办法;从栈帧的角度看也是一样一样的;

October 31, 2021 · 1 min · jiezi

关于设计模式:浅谈设计模式-组合模式十二

浅谈设计模式 - 组合模式(十二)前言 组合模式是一种十分重要的设计模式,应用场景简直随处可见,各类菜单和目录等中央都能看到组合模式的影子,组合模式通常状况下是和树形构造相辅相成的,而树是软件设计外面十分重要的数据结构,这篇文章将介绍什么是组合模式。 什么是组合模式 容许你将对象组合到树形构造体现“整体局部”的构造,组合能让客户以统一的形式解决个别对象和对象组合,组合其实更像是对于对于各种独立组建的“统一性”,能够将一类类似的事物看为一个整体然而领有齐全不同的工作机制。 介绍 能够说将类似的物品造成一个汇合的模式就是组合模式,他能看两个类似的物品在一处进行完满的交融以及操作。当咱们须要 整体/局部的操作时候,就能够应用这种模式。 特点组合模式考究的是整体和局部之间的关系,整体能够蕴含局部,局部能够回溯到整体,相互蕴含组合模式能够让对象构造以“树”的模式蕴含关系。少数状况能够疏忽整体和个体之前的差异优缺点长处:组合模式能够帮忙对象和组合的对象厚此薄彼的看待毛病:继承构造,批改抽象类违反凋谢敞开准则如果层次结构十分深,递归结构影响效率应用迭代器有可能造成并发遍历菜单的问题组合模式以繁多职责的准则换取透明性? 组合模式毁坏了的繁多职责准则,组合了多个对象的办法,同时在办法外面做了多种操作,然而这样做却是能够让整个对象能够更加直观的理解整体和局部的个性,这是设计模式外面十分常见的操作。 组合模式的结构图 组合模式的结构图如下: Component 组件:定义组件的接口,这里能够设计为抽象类,能够设计为接口,能够视为组件的“可能的公共行为”。Leaf 叶子节点:用于示意原始对象,叶子节点只须要实现本人的非凡性能即可,比方菜单的菜单子项。Composite 组件节点:定义组件行为,能够具备子节点。同时实现叶子节点的相干操作(继承同一个接口),能够视为一个分类的大类理论利用场景 因为事实场景当中这样的设计模式构造是有树状构造转换而来的,所以组合模式的应用场景就是呈现树形构造的中央。比方:文件目录显示,多及目录出现等树形构造数据的操作。上面咱们就应用一个菜单的构造来理解一下组合模式的“模板”代码。 实战模仿场景 组合模式是为树形结构设计的一种设计模式,案例参照一个菜单的治理性能作为模仿,咱们须要拿到不同的菜单分类,在菜单的分类外面,咱们有须要拿到不同的菜单项,咱们能够由任意的菜单项进入到不同的菜单分类,同时能够进入不同的叶子节点。 这次的代码案例是从网上找的例子: 形象组件形象组件定义了组件的告诉接口,并实现了增删子组件及获取所有子组件的办法。同时重写了hashCode和equales办法(至于起因,请读者自行思考。如有疑难,请在评论区留言)。 package com.jasongj.organization;import java.util.ArrayList;import java.util.List;public abstract class Organization { private List<Organization> childOrgs = new ArrayList<Organization>(); private String name; public Organization(String name) { this.name = name; } public String getName() { return name; } public void addOrg(Organization org) { childOrgs.add(org); } public void removeOrg(Organization org) { childOrgs.remove(org); } public List<Organization> getAllOrgs() { return childOrgs; } public abstract void inform(String info); @Override public int hashCode(){ return this.name.hashCode(); } @Override public boolean equals(Object org){ if(!(org instanceof Organization)) { return false; } return this.name.equals(((Organization) org).name); }}简略组件(部门)简略组件在告诉办法中只负责对接管到音讯作出响应。 ...

October 27, 2021 · 4 min · jiezi

关于设计模式:发现一个学习资料宝库

最近看vertx的reactor模式介绍,翻了一下网页,链接进入软件设计模式,发现了机密,软件设计模式类型1.创立类型设计模式2.构造类型的设计模式3.行为类型的设计模式4.并发设计模式(reactor是并发设计模式的一种) 各种设计模式的利用场景都有介绍,很全;以前买的书籍下面介绍的设计模式,还没有这里全,很多讲得没有这里业余。 这是什么网站,不说类,懂的都懂!

October 24, 2021 · 1 min · jiezi

关于设计模式:发现一个学习资料宝库

最近看vertx的reactor模式介绍,翻了一下网页,链接进入软件设计模式,发现了机密,软件设计模式类型1.创立类型设计模式2.构造类型的设计模式3.行为类型的设计模式4.并发设计模式(reactor是并发设计模式的一种) 各种设计模式的利用场景都有介绍,很全;以前买的书籍下面介绍的设计模式,还没有这里全,很多讲得没有这里业余。 这是什么网站,不说类,懂的都懂!

October 24, 2021 · 1 min · jiezi

关于设计模式:设计模式中的俄罗斯套娃装饰者Decorator模式

俄罗斯套娃想必大家都不生疏,就是同一种玩具娃娃大的套小的,而后一层一层嵌套上来。 在设计模式中,有一种罕用的套娃模式,叫做装璜者(Decorator)模式,又称为包装(Wrapper)模式。 HttpServletRequest 套娃在 Spring 框架开发的 Web 利用中,如果应用了 Spring Security 或 Spring Session,用 Debug 模式察看一下某个申请对应的 HttpServletRequest 对象,会发现这就是一个俄罗斯套娃: 图中能够看到咱们拿到的 HttpServletRequest 对象,外部成员中蕴含了一个 HttpServletRequest 对象,而这个外部的 HttpServletRequest 对象外部又蕴含了一个 HttpServletRequest 对象,层层蕴含,层层套娃。这就是一个典型的装璜者模式。 咱们晓得,HttpServletRequest 是 Servlet 标准中提供的一个 interface 接口。Servlet 标准自身没有实现 HttpServletRequest 接口,HttpServletRequest 接口个别是由 Servlet 容器来实现,例如 Tomcat、Jetty。如果 Spring Security、Spring Session 等框架想要加强 HttpServletRequest 对象的性能,然而不扭转原有对象的接口,最好的方法就是应用装璜者模式。例如: Spring Security 加强了 HttpServletRequest.getRemoteUser() 办法,可返回以后通过 Spring Security 框架登录用户的用户名;Spring Session 加强了 HttpServletRequest.getSession() 办法,加强后的 Session 取代了 Servlet 容器的默认实现,其读写能够应用一个集中式的存储,例如 Redis,这样能够不便集群中的多个实例共享 Session。HttpServletRequestWrapper / ServletRequestWrapper在 javax.servlet.http 包下有个 HttpServletRequestWrapper 类[源码],继承自 ServletRequestWrapper 类[源码]。能够看到这两个类上的正文: ...

October 20, 2021 · 3 min · jiezi

关于设计模式:设计模式策略模式

策略模式1.定义与类型定义:定义了算法家族,别离封装起来,让他们之间能够相互转换,此模式让算法的变动不会影响到应用算法的用户if...else类型:行为型2.实用场景零碎有很多类,而他们的区别仅仅在于他们的行为不同一个零碎须要动静地在几种算法中抉择一种3.长处开闭准则防止应用多种条件转移语句进步算法的保密性和安全性4.毛病客户端必须晓得所有的策略类,并自行决定应用哪一个策略类产生很多策略类5.相干设计模式策略模式 和 工厂模式策略模式 和 状态模式6.Coding 策略模式加工厂模式 创立策略接口Promotionpublic interface PromotionStrategy { void doPromotion();}创立一系列促销策略public class FanXianPromotionStrategy implements PromotionStrategy{ @Override public void doPromotion() { System.out.println("返现促销,返回的余额寄存到用户余额中!"); }}public class LiJianPromotionStrategy implements PromotionStrategy { @Override public void doPromotion() { System.out.println("立减促销,课程的价格间接减去配置的价格"); }}public class ManJianPromotionStrategy implements PromotionStrategy{ @Override public void doPromotion() { System.out.println("满减促销:满200减20"); }}创立促销流动:用来执行促销策略的类public class PromotionActivity { private PromotionStrategy strategy; public PromotionActivity(PromotionStrategy strategy){ this.strategy = strategy; } public void executeStrategy(){ strategy.doPromotion(); }}创立促销策略工厂/** * @program: design_pattern * @description: 促销策略工厂 * @create: 2021-10-13 22:23 **/public class PromotionStrategyFactory { /** 私有化结构器 */ private PromotionStrategyFactory(){} private static final Map<String,PromotionStrategy> PROMOTION_STRATEGY_MAP = new HashMap<>(); //初始化工厂 static { PROMOTION_STRATEGY_MAP.put(PromotionType.FANXIAN,new FanXianPromotionStrategy()); PROMOTION_STRATEGY_MAP.put(PromotionType.LIJIAN,new LiJianPromotionStrategy()); PROMOTION_STRATEGY_MAP.put(PromotionType.MANJIAN,new ManJianPromotionStrategy()); } /** 对外提供获取策略的办法 */ public static PromotionStrategy getPromotionStrategy(String promotionKey){ PromotionStrategy promotionStrategy = PROMOTION_STRATEGY_MAP.get(promotionKey); return promotionStrategy == null?null:promotionStrategy; } private interface PromotionType{ String LIJIAN = "LIJIAN"; String MANJIAN = "MANJIAN"; String FANXIAN = "FANXIAN"; }}测试类public class Test { public static void main(String[] args) { String promotionKey = "LIJIAN"; PromotionActivity promotionActivity = new PromotionActivity(PromotionStrategyFactory.getPromotionStrategy(promotionKey)); promotionActivity.executeStrategy(); }}控制台输入: ...

October 19, 2021 · 1 min · jiezi

关于设计模式:设计模式观察者模式

//观察者public interface Observer { public void update(float temp, float humidity, float pressure);}//观察者行为public interface Displayment { public void display();}//主题public interface Subject { public void registerObserver(Observer o); public void removeObserver(Observer o); public void notifyObserver();}//观察者1public class CurrentConditionsDisplay implements Observer, Displayment{ private float temp; private float humidity; private Subject weatherData; public void CurrentConditionsDisplay(Subject weatherData){ this.weatherData = weatherData; } public void display() { System.out.println("Current conditions: " + temp + "F degrees and "+ humidity + " % humidity"); } public void update(float temp, float humidity, float pressure) { this.temp = temp; this.humidity = humidity; display(); }}//主题相干的实例public class WeatherData implements Subject { private ArrayList observers; private float temperature; private float humidity; private float pressure; public WeatherData(){ this.observers = new ArrayList<Observer>(); } @Override public void registerObserver(Observer o) { observers.add(o); } @Override public void removeObserver(Observer o) { observers.remove(o); } @Override public void notifyObserver() { for(int i = 0; i < observers.size(); i++ ){ Observer observer = (Observer) observers.get(i); observer.update(temperature,humidity,pressure); } } public void measurementsChanged(){ notifyObserver(); } public void setMeasurements(float temperature, float humidity, float pressure){ this.temperature = temperature; this.humidity = humidity; this.pressure = pressure; }}//测试public class WeatherDataTest extends TestCase { public void testRegisterObserver() { WeatherData weatherData = new WeatherData(); weatherData.setMeasurements(23,15,175); CurrentConditionsDisplay currentConditionsDisplay = new CurrentConditionsDisplay();// CurrentConditionsDisplay currentConditionsDisplay = new CurrentConditionsDisplay(weatherData); weatherData.registerObserver(currentConditionsDisplay); weatherData.notifyObserver(); weatherData.removeObserver(currentConditionsDisplay); weatherData.notifyObserver(); }}//测试后果Current conditions: 23.0F degrees and 15.0 % humidity ...

October 19, 2021 · 1 min · jiezi

关于设计模式:设计模式系列-代理模式

代理模式: 为其余对象提供一个代理以管制对这个对象的拜访应用场景: 近程代理虚代理爱护代理...后续补充应用场景举例思考一个能够在文档中镶嵌图形对象的文档编辑器,有些图形对象的创立开销很大, 然而打开文档必须很迅速, 因而咱们在打开文档时应该防止一次性创立所有开销很大的对象。这里就能够使用代理模式。在打开文档时候, 并不关上图形对象。而是关上图形对象的代理以代替实在的图形,待到真正须要关上图形时,仍由代理负责关上, 上面给出UML图: 简略实现class Image{public:Image(string name):m_imageName(name){}virtual ~Image()virtual void show() {}protected:string m_imageName;};class BigImage: public Image {public:BigImage(string name):Image(name){}~BigImage(){}viod show(){cout <<" show big Image: " << m_imageName << endl;}};class BigImageProxy:public Image{private:BigImage* m_bigImage;public:BigImageProxy(string name):Image(name): m_bigImage(nullptr){}~BigImageProxy(){delete m_bigImage;}void show(){ if(m_bigImage == nullptr){ m_bigImage = new BigImage(m_imageName); m_bigImage->show() ; }}};int main(){ Image * iamge = new BigImageProxy("proxy.jpg");image->show();delete image;return 0;}在这个例子属于虚代理的状况; 上面给出两个只能援用的例子。

October 18, 2021 · 1 min · jiezi

关于设计模式:设计模式适配器模式

定义:适配器模式(Adapter Pattern)是作为两个不兼容的接口之间的桥梁。这种类型的设计模式属于结构型模式 思考到某些产品的性能很类似,如果想兼容其它产品,然而又不想思考太多的对象辨别或者if else, 能够用适配器模式来适配对象。 在产品迭代的过程中常常有不同的版本,尽管版本不同,然而大体上的性能和接口差不多,只是具体的实现有些微的区别,这个时候能够在前面的迭代零碎中一直适配最新的产品就能够了。 //产品对立接口interface AsianCarRun { public void run(String carType, int speed);}//被兼容产品的接口interface ChinaCarRun { public void BiYaDiRun(int speed); public void HongQiRun(int speed);}//被兼容产品1public class HongqiCar implements ChinaCarRun{ @Override public void BiYaDiRun(int speed) { } @Override public void HongQiRun(int speed) { System.out.println("this is HongQi running, and the speed is: "+ speed); }}//被兼容产品2public class ChangaAnCar implements ChinaCarRun{ @Override public void BiYaDiRun(int speed) { System.out.println("this is BiYaDi running, and the speed is: "+speed); } @Override public void HongQiRun(int speed) { }}//兼容主体类产品public class AsianCar implements CarRun { @Override public void run(String carType, int speed) { AsianCarAdapter carAdapter = new AsianCarAdapter(carType); carAdapter.run(carType,speed); }}//适配器public class AsianCarAdapter implements CarRun{ ChinaCarRun chinaCarRun; public AsianCarAdapter(String carType) { if(carType == "HongQi"){ chinaCarRun = new HongqiCar(); } if(carType == "BiYaDi"){ chinaCarRun = new ChangaAnCar(); } } @Override public void run(String carType,int speed) { if(carType == "HongQi"){ chinaCarRun.HongQiRun(speed); } if(carType == "BiYaDi"){ chinaCarRun.BiYaDiRun(speed); } }}测试类:public class AsianCarTest { @Test public void runTest() { AsianCar asianCar = new AsianCar(); asianCar.run("HongQi",120); }}测试后果:this is HongQi running, and the speed is: 120

October 18, 2021 · 1 min · jiezi

关于设计模式:设计模式解释器模式

解释器模式1.定义与类型定义:给定一个语言,定义它的文法的一种示意,并定义一个解释器,这个解释器应用该示意来解释语言中的句子为了解释一种语言,而为语言创立的解释器类型:行为型2.实用场景某个特定类型问题产生频率足够高3.长处语法由很多类示意,容易扭转及扩大此语言4.毛病当语法规定数目太多,减少了零碎复杂度5.相干设计模式解释器模式和适配器模式6.Coding创立解释器顶级接口public interface Interpreter { int interpreter();}解释器的相干实现类public class AddInterpreter implements Interpreter{ private Interpreter firstExpression,secondExpression; public AddInterpreter(Interpreter firstExpression,Interpreter secondExpression){ this.firstExpression = firstExpression; this.secondExpression = secondExpression; } @Override public int interpreter() { return this.firstExpression.interpreter() + this.secondExpression.interpreter(); } @Override public String toString() { return "+"; }}public class MultiInterpreter implements Interpreter{ private Interpreter firstExpression,secondExpression; public MultiInterpreter(Interpreter firstExpression,Interpreter secondExpression){ this.firstExpression = firstExpression; this.secondExpression = secondExpression; } @Override public int interpreter() { return this.firstExpression.interpreter() * this.secondExpression.interpreter(); } @Override public String toString() { return "*"; }}创立数字解释器,用于解决入参public class NumberInterpreter implements Interpreter { private int number; public NumberInterpreter(int number) { this.number = number; } public NumberInterpreter(String number) { this.number = Integer.parseInt(number); } @Override public int interpreter() { return this.number; }}简略实现一个工具类public class OperatorUtil { public static boolean isOperator(String symbol) { return (symbol.equals("+") || symbol.equals("*")); } public static Interpreter getExpressionObjects(Interpreter firstInterpreter, Interpreter secondInterpreter, String symbol) { if ("+".equals(symbol)) { return new AddInterpreter(firstInterpreter, secondInterpreter); } else if ("*".equals(symbol)) { return new MultiInterpreter(firstInterpreter, secondInterpreter); } return null; }}自定义一个解释器语法public class QchExpressionParser { private Stack<Interpreter> stack = new Stack<>(); public int parse(String str) { String[] strArray = str.split(" "); for (String item : strArray) { if (!OperatorUtil.isOperator(item)) { NumberInterpreter numberInterpreter = new NumberInterpreter(item); stack.push(numberInterpreter); System.out.println(String.format("入栈:%d", numberInterpreter.interpreter())); } else { Interpreter firstInterpreter = stack.pop(); Interpreter secondInterpreter = stack.pop(); System.out.println(String.format("出栈:%d 和 %d", firstInterpreter.interpreter(), secondInterpreter.interpreter())); Interpreter expressionObjects = OperatorUtil.getExpressionObjects(firstInterpreter, secondInterpreter, item); System.out.println(String.format("利用运算符: %s", expressionObjects.interpreter())); int result = expressionObjects.interpreter(); NumberInterpreter numberInterpreter = new NumberInterpreter(result); stack.push(numberInterpreter); System.out.println(String.format("阶段后果入栈:%d", result)); } } int result = stack.pop().interpreter(); return result; }}Test测试类public class Test { public static void main(String[] args) { String geelyInputStr = "6 100 11 + *"; QchExpressionParser expressionParser = new QchExpressionParser(); int parse = expressionParser.parse(geelyInputStr); System.out.println("解释器执行后果为:"+parse); }}控制台打印 ...

October 15, 2021 · 2 min · jiezi

关于设计模式:设计模式装饰器

装璜者模式是一种结构型模式,它对现有的类进行包装,容许向一个现有的对象增加现有的性能,同时又不扭转其构造。 这种模式创立了一个新的装璜器类,用来包装原有的类。并在放弃类签名完整性的状况下提供了额定的性能。 用意:动静地给一个对象增加额定的职责,就新增红能来说,装璜器模式相比于生成子类更加灵便。 次要解决:通常咱们为了减少一个类的性能,常常应用继承的形式,因为继承引入动态代码的特色,并且随着扩大性能的增多,子类会很收缩。 如何应用;在不想减少子类的状况下应用。 如何解决:将具体性能职责进行划分,同时继承装璜者模式。 要害代码: Component类充当形象角色,不负责具体实现。 装璜者类继承和援用Component类,具体扩大类重写父类办法。 有点:装璜类和被装璜类能够独立倒退,不会相互耦合。装璜模式是继承很好的的一个代替模式。 形象组件: public abstract class Beverage { String description = "Unknow Beverage"; public String getDescription(){ return description; } public abstract double cost();}形象装璜者类 public abstract class CondimentDecorator extends Beverage { public abstract String getDescription();}具体组件 public class Espresso extends Beverage{ public Espresso(){ description = "Espresso"; } @Override public double cost() { return 1.99; }}具体装璜者 public class Mocha extends CondimentDecorator{ Beverage beverage; public Mocha(Beverage beverage){ this.beverage = beverage; } @Override public String getDescription() { return beverage.getDescription() + ", Mocha"; } @Override public double cost() { return 0.20 + beverage.cost(); }}单元测试 ...

October 14, 2021 · 1 min · jiezi

关于设计模式:设计模式模板模式

定义:定义一个操作中算法的骨架,而将一些步骤提早到子类中,模板办法使得子类能够不扭转算法的构造即可重定义该算法的某些特定步骤。艰深点的了解就是 :实现一件事件,有固定的数个步骤,然而每个步骤依据对象的不同,而实现细节不同;就能够在父类中定义一个实现该事件的总办法,依照实现事件须要的步骤去调用其每个步骤的实现办法。每个步骤的具体实现,由子类实现。类关系:形象父类(AbstractClass):实现了模板办法,定义了算法的骨架。具体类(ConcreteClass):实现抽象类中的形象办法,即不同的对象的具体实现细节。 package designPattern.template;public class A { public void funA(){ fun1(); fun2(); } public void fun1(){ System.out.println("this is fun1 of A"); } public void fun2(){ System.out.println("this is fun2 of A"); }}public class B extends A{ public void funB(){ funA(); } @Override public void fun1(){ System.out.println("this is fun1 of B"); }}//单元测试:public class BTest { @Test public void funBTest() { B b = new B(); b.funB(); }}后果:this is fun1 of Bthis is fun2 of A ...

October 14, 2021 · 1 min · jiezi

关于设计模式:设计模式系列-装饰器模式

装璜器模式(DECRATOR):为了实现动静的给对象增加职能,即从内部给对象增加相干职能。能够这样了解,比如说一个Person类,该类的操作有能吃、能睡、能跑、但如果随着人类的进化,某一天Person能飞了,能在水里游了等等,依照个别的写法是批改Person这个类,给这个类增加上能飞,能游等操作,然而这样毁坏了面向对象的凋谢-关闭准则(对批改关闭,对拓展开发,有趣味的能够查看相干文献),且随着人类的进化这个类就会变得越来越臃肿,越来越简单,增加任何一个性能都必须对这个臃肿的类进行批改,出错的概率大大晋升,且容易影响老性能,而装璜器模式能够解决这类问题,装璜器从内部给类增加职能,而不必去批改原始的类,拓展性好,可复用水平高。UML 类图cake 为一个形象对象,装璜器和具体须要被装璜的对象都继承自该形象对象,最重要的一点是Decrator保护了一个须要被装璜的对象的援用,从而达到为该对象增加职能的目标。 思考如下的例子:为一个蛋糕增加装璜。蛋糕店刚生产进去的蛋糕是最原始的,只是一个蛋糕原型,咱们须要再这个蛋糕上加上奶油,加上巧克力,加上瓜子仁,写上字等等,将原始蛋糕作为一个Cake类,咱们给这个Cake类的对象作装璜,为了不毁坏凋谢-关闭准则,也为了更好的拓展,咱们不能间接在Cake这个类里批改,而应该做一个有固定跟你的机器(装璜器),通过装璜器来给这个蛋糕做装璜。 #include <iostream>#include <string>using namespace std;class cake{public: virtual void getName();};class mangoCake: class cake{ void getname() overide { std::cout <<"this cake is made of mango"; }};class decoratorCake: class cake{public: decoratorCake(cake* cake){ mcake_ = cake; }private: cake* mcake_;};class chocolateDecorator: class decoratorCake {public: void getName(){std::cout << mcake_->operation() << " " + "chocolate" ;}};class creamDecorator: class decoratorCake {public: void getName(){std::cout << mcake_->operation() << " " + "cream" ;}};int main() { cake * mycake = new mangoCake(); mycake->getName(); mycake = new chocolateDecorator(mycake); mycake->getName(); mycake = new creamDecorator(mycake); mycake->getName(); delete cake; return 0;}

October 12, 2021 · 1 min · jiezi

关于设计模式:智汀家庭云开发指南Golang架构概述

智汀家庭云,立项于2021年,联合国内智能家居各厂商软件特点,研发“智汀家庭云”,并对该生态系统全面开源,为国内首个采纳智能家居零碎全生态开源协定(Apache License, Version 2.0)的软件。 1.利用场景智汀家庭云能够离线运行在局域网内,也能够通过绑定到智汀云来获取更弱小的性能。运行在局域网环境时,用户能够通过智汀APP发现与治理智汀家庭云,装置插件来对设施进行治理与管制。 用户也能够通过在智汀云下面注册帐号,将智汀家庭云设施绑定到云端,而后通过云端直达的形式反对在外网对设施进行管制。 在开发过程中须要留神的是,任何状况下,用户的隐衷都是最重要的,因而在任何状况下用户都可无条件地勾销对智汀云,第三方利用或插件的受权; 同时也应保障用户数据不被第三方获取。 2.架构设计智汀家庭云运行在 Linux 主机下,通过 Docker 来对其中的服务进行部署与资源隔离。其中局部外围服务容器须要事后配置, 并且随系统启动主动运行;而插件(plugin)类服务则是由 SA 调用 docker API 的形式进行治理。插件启动后会运行一个 gRPC 服务以及一个可选的 HTTP 服务,SA 通过 docker API 监听插件运行状态, 通过 gRPC 接口获取插件信息 3.功能模块智汀家庭云模块拆分为 internal 与 pkg 两个分组,其中 internal 为与我的项目业务逻辑相关性比拟强功能模块分组;pkg 蕴含与业务关系不大的通用组件。其援用关系如下图所示: 其中比拟重要的业务模块如下: 4.程序设计的规定参考根底模块应用单例模式实例化,但应防止间接应用全局变量,可应用 entity.DB(), pkg.Log() 的模式做一层封装; 懒汉模式提早初始化应应用 sync.Once根底模块只依赖其余根底模块,不应波及业务逻辑简略的业务模块(譬如只依赖根底模块),可间接应用单例模式,或者通过容器模块(app,command,server 等)进行实例化依赖其余业务模块,或者两个模块间可能会进行互相调用而导致循环援用的,应用管制反转(依赖注入)技术进行解决,由容器模块进行实例化(请参考 ioc exmaple)利用内防止应用 eventbus 等 pubsub 模型进行模块解耦;如需应用 pubsub,请在 event 包中对事件类型、音讯进行预约义;禁止为了不便而间接应用 Bus.Pub("my_event", data) 的模式尽量避免应用 init,应显式地在外层调用相干的 InitXXX() 函数5.目录构造我的项目源码构造参考 Standard Go Project Layout : ...

September 29, 2021 · 1 min · jiezi

关于设计模式:设计模式中的观察者模式

观察者模式是一种软件设计模式,其中一个名为主体(Subject)的对象保护其依赖项列表,称为观察者,并通常通过调用它们(observers)的办法之一来主动告诉它们任何状态更改。 观察者模式次要用于在“事件驱动”软件中实现分布式事件处理零碎。在这些零碎中,主体 Subject 通常被称为“事件流(stream of events)”或“事件流源”,而观察者被称为“事件接收器”。 流命名法暗示了一种物理设置,其中观察者在物理上是离开的,并且无法控制从主题/流源收回的事件。 这种模式非常适合任何过程,其中数据从启动时 CPU 不可用的某些输出达到,而是“随机”达到(HTTP 申请、GPIO 数据、来自键盘/鼠标/的用户输出...、分布式数据库)和区块链,...)。 大多数古代编程语言都蕴含实现观察者模式组件的内置“事件”构造。尽管不是强制性的,但大多数“观察者”实现将应用后盾线程监听主题事件和内核提供的其余反对机制(Linux epoll,...)。 观察者设计模式是二十三个驰名的“四人帮”设计模式之一,形容了如何解决重复呈现的设计挑战,以设计灵便且可重用的面向对象软件,即更容易实现、更改、 测试和重用。 What problems can the Observer design pattern solve?观察者模式解决了以下问题: 对象之间的一对多依赖关系应该在不使对象严密耦合的状况下定义。应该确保当一个对象扭转状态时,自动更新有限数量的依赖对象。一个对象能够告诉有限数量的其余对象应该是可能的。通过定义一个间接更新依赖对象状态的对象(主体)来定义对象之间的一对多依赖是不灵便的,因为它将主体耦合到特定的依赖对象。尽管如此,从性能的角度来看,或者如果对象实现是严密耦合的(想想每秒执行数千次的低级内核构造),它依然有意义。在某些状况下,严密耦合的对象可能难以实现,并且难以重用,因为它们援用并理解(以及如何更新)具备不同接口的许多不同对象。在其余状况下,严密耦合的对象可能是更好的抉择,因为编译器将可能在编译时检测谬误并在 CPU 指令级别优化代码。 What solution does the Observer design pattern describe?定义主题和观察者对象。 这样当一个主题扭转状态时,所有注册的观察者都会被主动告诉和更新(可能是异步的)。 主体的惟一职责是保护观察者列表并通过调用它们的 update() 操作告诉它们状态变动。 观察者的职责是在一个主题上注册(和勾销注册)本人(以取得状态变动的告诉)并在收到告诉时更新他们的状态(将他们的状态与主题的状态同步)。 这使得主体和观察者涣散耦合。 主体和观察者彼此之间没有明确的感知。 能够在运行时独立增加和删除观察者。 这种告诉-注册交互也称为公布-订阅。 Strong vs. weak reference观察者模式会导致内存透露,称为生效侦听器问题,因为在根本实现中,它须要显式注册和显式勾销注册,就像在处理模式中一样,因为主体持有对观察者的强援用,使它们放弃活动状态。 这能够通过主体持有对观察者的弱援用来避免。 Coupling and typical pub-sub implementations通常,观察者模式被实现,因而被“察看”的“主体”是正在察看状态变动的对象的一部分(并传播给观察者)。这种类型的实现被认为是“严密耦合的”,迫使观察者和主体相互了解并能够拜访它们的外部局部,从而产生可扩展性、速度、音讯复原和保护(也称为事件或告诉)的可能问题损失),条件扩散不足灵活性,以及可能障碍所需的安全措施。在公布-订阅模式(又名公布-订阅模式)的一些(非轮询)实现中,这是通过创立一个专用的“音讯队列”服务器(有时还有一个额定的“音讯处理程序”对象)作为额定阶段来解决的观察者和被察看对象之间,从而解耦组件。在这些状况下,音讯队列服务器由观察者应用观察者模式拜访,“订阅某些音讯”只晓得预期的音讯(或在某些状况下不晓得),而对音讯发送者自身无所不知;发送者也可能对观察者无所不知。公布订阅模式的其余实现,实现了相似的告诉和向感兴趣的各方通信的成果,基本不应用观察者模式。 在 OS/2 和 Windows 等多窗口操作系统的晚期实现中,术语“公布-订阅模式”和“事件驱动的软件开发”被用作观察者模式的同义词。 正如 GoF 书中所形容的,观察者模式是一个十分根本的概念,并没有解决在告诉观察者之前或之后打消对察看到的“主体”或被察看“主体”所做的非凡逻辑的更改的趣味。该模式也不解决发送更改告诉时的记录或保障收到更改告诉。这些问题通常在音讯队列零碎中解决,其中观察者模式只是其中的一小部分。 观察者模式的 UML 和 时序图 在下面的UML类图中,Subject类并没有间接更新依赖对象的状态。 相同,Subject 援用 Observer 接口(update())来更新状态,这使得 Subject 独立于依赖对象的状态如何更新。 Observer1 和 Observer2 类通过将它们的状态与主题的状态同步来实现 Observer 接口。UML 序列图显示了运行时交互:Observer1 和Observer2 对象调用Subject1 上的attach(this) 来注册它们本人。 假如 Subject1 的状态产生了变动,Subject1 会对其本身调用 notify() 。notify() 对已注册的 Observer1 和 Observer2 对象调用 update(),它们从 Subject1 申请更改的数据 (getState()) 以更新(同步)它们的状态。 ...

September 25, 2021 · 2 min · jiezi

关于设计模式:责任链模式探究

背景责任链模式(又称职责链模式,The Chain of Responsibility Pattern),作为开发设计中罕用的代码设计模式之一,属于行为模式中的一种,从来被咱们开发所相熟。 责任链模式也是实人 SDK 应用的次要设计模式之一,从通过 start 接口获取相干配置信息,到 upload 接口上传认证资料,后续通过 verify 接口提交认证获取认证后果,能够说将整个实人业务的逻辑以链的形式实现,上一个业务节点的后果作为下一个业务的开始,从而串起了整个SDK的外围逻辑。咱们尽管在日常开发过程中看过很多设计模式,同时也或多或少利用在工程中,但像老话说的一样,想到不肯定晓得,晓得不肯定能做到,做进去又不代表能说进去,说的进去还不肯定能写进去。如何将本人写过的代码,用到的设计模式翻译成文字,对开发者来说也是一个很有意思的事件和小挑战。 所以本篇旨在从新梳理一下本人印象中的设计模式,并诉诸文字,温故而知新。 什么是责任链模式如上所述,责任链模式是一种了解上比较简单的行为设计模式,它容许开发者通过解决者链进行程序发送,每个链节点在收到申请后,具备两种能力: 对其进行解决(生产)将其传递给链上的下个解决者当你想要让一个以上的对象有机会能解决某个申请时,就能够应用责任链模式。通过责任链模式,为某个申请创立一个对象链,每个对象链依序查看此申请,并对其进行解决,或者将它传给链中的下一个对象。 从某种生存场景中了解,就像患者去医院看病,传统上可能会经验从挂号到医生问诊再到抽血拍片再到医生复诊以及最终药房拿药的过程。 从生存教训上能够看出,责任链上每个节点的产物是不同的(当然也能够雷同,但雷同的话就没必要通过责任链去解决了,可能放在单个对象中会更适合),像链表构造一样,每个节点除了须要蕴含指向下一个链节点的索引以及必要时终止传递的能力外,还须要具备传递给下一个节点的产物的能力。如何针对不同的业务场景对链节点的产物进行形象,也成为了代码编写中的一个问题,为什么会成为一个问题?因为应用责任链的一大劣势就是咱们能够动静地去新增或删除链节点以达到业务能力的扩大,如果咱们对输入的产物定义的不够清晰,就会导致在做链式扩大时,相干的产物代码会变得更加简单导致代码的可读性升高。 举个例子,在实人 SDK 的工程中,通过创立一个对象将业务链中所有的过程产物都蕴含进了该类中,相似如下代码: RealIdentityChainOutputs { // start 过程产物 public StartOutput mStartOutput; // upload 过程产物 public UploadOutput mUploadOutput; // verify 过程产物 public VerifyOutput mVerifyOutput; // submit 最终后果产物 public SubmitOutput mSubmitOutput; }这样写的益处是,能够通过传递一个对象的形式,将过程产物对立通过一个类对象的形式传递,就像是我在医院拿了一个蕴含各种单据的文件袋,每次走完一个流程就将其中一个单据填满,进入下一个流程,简略不便。但存在的问题也很显著。 首先,会带来代码的可见性危险,最开始的几个链节点曾经晓得了前面几个链节点产物的数据结构,那是否就存在前几个节点有能力批改前面节点产物的可能?其次,如果在链传递过程中呈现两个雷同的产物对象,那依照目前的产物包装类,是很难「优雅」地去创立两个雷同数据的对象的,是建一个List还是再新建一个雷同类的对象?其三,每个节点都有完结以后流转流程的能力,也属于链流转最终产物中的一种后果,但放到上述包装类中的话,代表着某一个产物即为最终整个链的产物,这和当初定义这个包装类的初衷又是相违反的。当然,这些问题都是基于将来业务扩大的角度来思考,针对实人比较简单的业务场景,是可用的。提出太多的问题,有「适度设计」之嫌。 所以责任链到底解决了什么问题? 前置查看,缩小不必要的后置代码逻辑发送者(sender)和接收者(receiver(s))的逻辑解耦,进步代码灵活性,这一点是最重要的通过链路程序传递申请,也使每一个链节点职责明确,合乎繁多职责准则通过扭转链内的成员或调动它们的秩序,容许你动静地新增或删除,也进步了代码的灵活性责任链模式代码的根本表白咱们来看一下责任链模式的 UML 图。 从最根本的 UML 图中能够看出责任链里个别蕴含4种角色: Client 客户端,定义链的规定和运行形式,依据具体业务场景动静生成链(所以链并不是固定不变的,可定制组合,并抉择链头和链尾)Handler 解决者接口,次要用于申明具体解决者的通用能力,个别蕴含形象解决能力以及指向下一个节点的能力BaseHandler 根本解决者,这是一个可有可无的角色,能够依据业务场景将具体解决者中的一些共有逻辑放到该类当中ConcreteHandlers 具体解决者,形成了链中的解决节点,外围职能是解决申请,决定申请是在该节点生产掉还是沿着链持续传递(具体解决者之间独立且不可变)能够看出,责任链模式外围的逻辑是解决和传递,同时具备由内部灵便定制的能力。 通过 UML 图也能够看出责任链的固定的几步实现形式: 申明 Handler 接口定义节点解决的接口通过创立形象解决者基类打消具体解决者之间的反复模版代码顺次创立具体解决者子类及其实现办法,通过具体解决类决定以后解决类是否要生产这个申请或者沿着链持续传递最终体现到业务层,由 Client 对象自行组装实现的链节点,实现逻辑解决和调用对象的解耦// 解决者接口申明了一个创立解决者链的办法。还申明了一个执行申请的办法。interface Handler is method handle() method setNext(h: Handler)// 简略组件的根底类。abstract class BaseHandler implements Handler is field canHandle: boolean // 如果组件能解决申请,则解决 method handle() is doCommonThings method setNext(h: Handler)// 原始组件应该可能应用帮忙操作的默认实现class ConcreteHandlerA extends BaseHandler is // ...// 简单解决者可能会对默认实现进行重写class ConcreteHandlerB extends BaseHandler is method handle() is if (canHandle) // 解决者B的解决形式 else super.handle()// ...同上...class ConcreteHandlerC extends BaseHandler is field wikiPageURL: string method handle() is if (canHandle) // 解决者C的解决形式 else super.handle()// Clientclass Application is // 每个程序都能以不同形式对链进行配置。 method cor() is handlerA = new ConcreteHandlerA() handlerB = new ConcreteHandlerB() handlerC = new ConcreteHandlerC() // ... handlerA.setNext(handlerB) handlerB.setNext(handlerC)实用场景通过下面的形容咱们也能够看出,其实只有波及到逻辑程序解决的,都能够应用责任链模式来解决。但从理论场景登程,决定是否应用该模式要考虑一下两个因素: ...

September 24, 2021 · 2 min · jiezi

关于设计模式:正交设计

前置介绍Kent Beck(肯特·贝克)设计模式重构《重构:改善既有代码的设计》,代码坏滋味 极限编程一个轻量级的、乖巧的软件开发办法;同时它也是一个十分谨严和周密的办法。它的根底和价值观是交换、奢侈、反馈和勇气;即,任何一个软件我的项目都能够从四个方面动手进行改善:增强交换;从简略做起;寻求反馈;敢于捕风捉影。XP是一种近螺旋式的开发方法,它将简单的开发过程合成为一个个绝对比较简单的小周期;通过踊跃的交换、反馈以及其它一系列的办法,开发人员和客户能够十分分明开发进度、变动、待解决的问题和潜在的艰难等,并依据理论状况及时地调整开发过程。 麻利软件开发的一种,极限编程和传统方法学的实质不同在于它更强调可适应性以及面临的艰难。 测试驱动开发英文全称Test-Driven Development,简称TDD 简略设计准则 Kent Beck给出的答案: 通过所有测试(Passes its tests)尽可能打消反复 (Minimizes duplication)尽可能清晰表白 (Maximizes clarity)更少代码元素 (Has fewer elements)以上四个准则的重要水平顺次升高。 这组定义被称做简略设计准则。 1、通过所有测试(实现性能)这里提到的测试,真正的意思是客户验收。如果你的我的项目通过了客户的所有验收条件(Acceptance Criteria),那就阐明你们曾经实现与客户约定的全副需要。至于验收形式是靠人工还是靠自动化测试则无关紧要。 所以,这句话强调的是对外部需要——包含功能性需要和非功能性需要——正确的实现。 2、尽可能打消反复(易于重用)反复,意味着低内聚,高耦合。而打消反复的过程,也就意味着是让软件走向高内聚,低耦合,达到良好正交性的过程。辨认和打消反复,对于加强软件应答变动能力的重要水平,怎么强调都不为过。 不过,并不是所有的反复都能够打消:比方,C++一个源文件里对外部公开的类,其每个public办法原型,除了在源文件里定义时,须要申明一次,还须要在头文件里再次申明。这样的反复,是语言机制的要求,无奈打消。 因此,这条准则被形容为最小化反复,而不是打消反复。 3、尽可能清晰表白(易于了解)清晰性,指的是一个设计容易了解的水平。留神:这不仅仅是对整洁代码(Clean Code)及申明式设计(Declarative Design)的强调。 #### 申明式设计 申明式设计,形容想要让一个事物达到的指标状态,由这个工具本人外部去解决如何令这个事物达到目标状态。 命令式设计或者过程式设计,形容的是一系列的动作,这一系列的动作如果被正确执行,最终后果将达到咱们冀望的指标状态。 申明式设计和命令式设计的区别 申明式设计,是通知计算机你想要什么,由计算机本人去设计执行门路,如SQL; 命令式设计,是间接向计算机收回服务器要执行的操作命令; 相比于更关注状态和后果的申明式设计形式,命令式设计形式更强调过程。 幻数magic number,弊病:代码可读性差,批改不不便 4、更少代码元素(没有冗余)这一条是点睛之笔,正是因为它的存在,这组准则才被称做简略设计准则,从而区别于其它设计准则。 在这里,常量,变量,函数,类,包 …… 都属于代码元素。代码元素的数量,通常反映了设计的复杂度。因此,这句话强调的是:尽可能升高复杂度,放弃简略。 总结简略设计准则,通过对需要、易批改性、可了解性、复杂度,这四个在设计决策中最要害的因素给出了排序,让简略设计不再一个语义含糊的口号,而是对设计决策给出了清晰判断规范。 正交设计「正交」是一个数学概念:所谓正交,就是指两个向量的内积为零。简略的说,就是这两个向量是垂直的。在一个正交零碎里,沿着一个方向的变动,其另外一个方向不会发生变化。为此,Bob大叔将「职责」定义为「变动的起因」。 「正交性」,意味着更高的内聚,更低的耦合。为此,正交性能够用于掂量零碎的可重用性。 1、一个出发点软件设计的目标只有一个:性能实现。这是一个软件存在的根本原因。 但随着软件越来简单,繁多过程的复杂度曾经超出掌控极限。这逼迫人们必须对大问题进行合成,分而治之。 这就是模块化设计的最后动机。 2、两个问题一旦开始进行进行模块化拆分,就必须解决如下两个问题: 到底软件模块该怎么划分才是正当的?将一个大单元划分为多个小单元之后,它们之间必然要通过连接点进行单干。如果咱们把这些连接点看作API,那么问题就变为:怎么定义API才是正当的?更简略的说:怎么分?而后再怎么合? 而这两个问题的答案,正是古代软件设计的外围关注点。 3、三方关系为了找到这两个问题的答案,咱们须要从新回到最后的问题:为何要做软件设计? Kent Beck给出的答案是:软件设计是为了让软件在长期范畴内容易应答变动。 在这个精炼的定义中,蕴含着三个关键词:长期,容易,变动。这意味着: 越是须要长期保护的我的项目,变动更多,也更难预测变动的形式;软件设计,事关老本;如何在难以预测的变幻无穷中,放弃低廉的变更老本,正是软件设计要解决的问题。对此,Kent Beck提出了一个更为精炼的准则:部分化影响。意思是说,咱们心愿,任何一个变动,对于咱们以后的软件设计影响范畴都能够管制在一个尽量小的部分。 如何能力做到? 内聚与耦合一个易于应答变动的软件设计应该听从高内聚,低耦合准则。 内聚性:关注的是一个软件单位外部的关联严密水平。因此高内聚谋求的是关联严密的事物应该被放在一起,并且只有关联严密的事物才应该被放在一起。简略说,就是Unix的设计哲学: Do One Thing, Do It Well。耦合性:强调两个或多个软件单位之间的关联严密水平。因此低耦合谋求的是,软件单位之间尽可能不要相互影响。 对应最后的两个问题: 当咱们划分模块时,要让每个模块都尽可能高内聚;而当咱们定义模块之间的API时,须要让单方尽可能低耦合。 ...

September 24, 2021 · 1 min · jiezi

关于设计模式:设计模式简单工厂模式

1、实用场景工厂类负责创立的对象比拟少应用层只晓得传入工厂类的参数 对于如何创建对象 创立谁的对象并不关怀 2、长处只需传入正确的参数 即可由工厂给咱们创立对应的实例 无需理解创立的细节 3、毛病减少新产品的时候 须要批改代码 违反了开闭准则 4、Coding演示 4.1 版本一UML类图预览: 1.抽象类videopublic abstract class Video { /** 创立学习视频 */ public abstract void produce();} 2.JavaVideo继承抽象类 并实现形象办法public class JavaVideo extends Video{ @Override public void produce() { System.out.println("录制java学习视频中"); }} 3.PythonVideo继承抽象类 并实现形象办法public class PythonVideo extends Video{ @Override public void produce() { System.out.println("录制python学习视频"); }} 4.简略工厂类public class VideoFactory { public Video getVideo(String videoType){ if("java".equalsIgnoreCase(videoType)) return new JavaVideo(); else if("python".equalsIgnoreCase(videoType)) return new PythonVideo(); return null; }} ...

September 19, 2021 · 1 min · jiezi

关于设计模式:设计模式策略模式

理论案例一个主题切换案例public interface Theme { void applyTheme();}public class DefaultTheme implements Theme{ @Override public void applyTheme() { System.out.println("设置默认主题"); }}public class DarkTheme implements Theme{ @Override public void applyTheme() { System.out.println("设置暗黑格调主题"); }}public class ColorfulTheme implements Theme{ @Override public void applyTheme() { System.out.println("设置黑白格调主题"); }}public class ThemeManager { private Theme theme; public ThemeManager() { this.theme = new DefaultTheme(); } public void setTheme(Theme theme){ this.theme = theme; } public void applyTheme(){ this.theme.applyTheme(); }}public class Client { public static void main(String[] args) { ThemeManager themeManager = new ThemeManager(); //设置光明格调主题 themeManager.setTheme(new DarkTheme()); themeManager.applyTheme(); }}主题模式更换的案例中,不同的主题格调就是一个个策略,咱们能够根须须要抉择不同的策略。 ...

September 17, 2021 · 1 min · jiezi

关于设计模式:设计模式建造者模式

建造者模式将一个简单对象的构建与他的示意拆散,使得同样的构建过程能够创立不同的示意如何了解建造者模式建造者模式就是将建造简单对象的过程和组成对象的部件进行解耦。 案例游戏公司设计游戏角色,其中人、兽、精灵三个种族。而每个种族又领有不同的英雄角色。所以角色设计应该具备以下特点: 角色根本属性统一角色创立过程简单,不裸露创立细节合乎开闭准则,能够随时新增角色各个角色间彼此不受影响这些特点很合乎工厂模式的实用特点,那用工厂模式就能够实现的案例为何要用建造者模式? 次要是一个角色蕴含有头、手、脚、毛发...等许多部件,不同种族不同角色的部件有许多差别。如果应用工厂模式,那么角色的创立过程会与其各个部件耦合在一起,如果部件比拟多,那么角色的创立是比较复杂的。比方所以咱们须要将对象的创立过程与组成对象的部件进行解耦,也就是这一章的主题---建造者模式 类图(todo)产品类定义产品的根本属性 形象建造者定义产品各个部件的构建标准 具体构建者实现形象构建者的所有办法,返回一个具体的产品 导演类负责封装已有模块的程序 隔离客户与生产过程管制产品的生成过程劣势良好的封装性。产品类和建造类绝对固定,将次要逻辑封装到导演类能够获得比拟好的稳定性。不需裸露产品外部细节,将产品自身与产品创立过程进行解耦。精密管制产品创立过程。创立过程清晰,可能把控产品每个部件的创立过程。良好的扩展性。新的需要只须要减少新的建造类就能够解决,合乎开闭准则。局限性建造者不适宜差异性很大的产品类。产品外部变动简单,须要定义很多建造类来实现,会导致系统变得宏大。应用场景雷同的办法,不同的执行程序,产生不同的事件后果一个对象具备多个部件,然而不同的对象的部件有所差别,也能够应用建造者模式须要隔离简单对象的创立和应用,并使雷同创立过程能够创立不同的产品建造者模式与工厂模式的区别工厂模式职责---创建对象 将创立过程封装到工厂类,有工厂类提供最终产品。建造模式职责---整机的拆卸以产生不同的对象 负责创立简单对象,须要对对象的部件进行拆卸以产生不同成果的对象,具备的建造过程交给指挥类。由指挥类负责将各个组件依照规定组建为产品。

September 17, 2021 · 1 min · jiezi

关于设计模式:head-first-设计模式-U1

1.0版本:初始实现duck类有quack,swin,display办法mallardduck和redheadduck继承duck类并改写display办法 需要:减少会飞的鸭子1.1版本:继承解决的操作:duck减少fly办法->问题:橡皮鸭子不会飞,然而继承了fly办法,所以会飞了->解决的操作:橡皮鸭子笼罩fly办法重写为空办法->问题1:橡皮鸭子不会飞然而有fly办法,容易引起误会问题2:退出其余类型鸭子,不同的行为都须要重写代码,比方说木头假鸭,不会飞也不会叫,须要重写quack和fly办法为空 毛病:代码反复,运行时行为不能扭转,很难晓得鸭子的真正行为,改一发而动全身 2.0版本:接口解决:1.duck类去除fly和quack办法,减少flyable接口和quackable接口2.所有鸭子继承自duck类,且实现了flyable接口和quackable接口毛病:1.代码反复,无奈复用。所有鸭子类型都要写本人的fly和quack办法。2.改一发而动全身。只有批改了某种fly办法,就要批改雷同实现的所有鸭子类型。 3.0版本:策略模式设计准则:找出利用中可能须要变动之处,把它们独立进去,不要和那些不须要变动的代码混在一起。即,把会变动的局部取出并封装起来,以便当前能够轻易的改变或裁减此局部,而不影响不须要变动的其余局部。解决的问题:把会变动的局部封装起来,改变时好让其余中央不会受到影响 设计准则:针对接口编程,而不是针对实现编程。即,将特定的具体行为编写在了接口中。解决的问题:没有方法扭转对象行为 针对接口编程的真正意思是针对超类型编程。形象超类型能够是抽象类或接口很好的例子:针对实现编程:dog d = new dog()d.bark()针对接口/超类型变成:animal animal = new dog();animal.makeSound() //子类dog的makeSound调用bark办法优化:子类实现的动作不须要硬编码,能够在运行时才指定具体实现的对象a = getAnimal()a.makeSound() 设计准则:多用组合,少用继承当你把两个类联合起来应用,就是组合应用组合建设零碎具备很大的弹性,不仅能够将算法族封装成类,更能够在运行时动静的扭转行为,只有组合的行为对象合乎正确的接口标准即可。 实现:duck抽象类,flybehavior接口,quackbehavior接口行为类flywithwings,flynoway实现flybehavior接口(策略模式)行为类quack,squeak,mutequack实现quackbehavior接口(策略模式)duck类中有两个实例变量flybehavior和quackbehavior,申明为接口类型duck类中应用performQuack代替quack办法委托给quackbehavior实例,performFly代替fly办法委托给flybehavior实例duck类中退出setflybehavior和setquackbehavior办法,能够在运行时调用以动静扭转鸭子行为 总结:oo根底:形象,封装,多态,继承oo准则:封装变动,多用组合少用继承,针对接口编程而不是实现oo模式:策略模式:定义算法族,别离封装起来,让它们之间能够相互替换,此模式让算法的变动独立于应用算法的客户

September 12, 2021 · 1 min · jiezi

关于设计模式:重学设计模式读后总结篇我理解的设计模式二

@TOC须要有肯定设计模式根底的看,能够联合菜鸟教程等等的来一起看 1.1 工厂办法模式将多段代码的共性行为形象到接口中去定义,具体的实现由子类实现父类后去定义。最初,通过一个工厂类去依据传参来抉择返回对应的实例化对象。关键词:工厂类个别带有Factory 1.2 形象工厂模式 形象工厂的实质是其它工厂类的抽象类,也就是将其余工厂类中的共性行为提取到了形象工厂类AbstractXXX小傅哥在形象工厂模式中是应用了形象工厂的另一种实现,其中用到了代理、适配器、形象工厂几个点,这里为CacheService的两种缓存模式实现加上了适配器,使其对应的办法与CacheService接口的办法对应,而后应用了动静代理,在代理实例调用办法时,办法调用被编码分派到调用处理程序的invoke办法。能够将不同的缓存模式的适配器类看作为工厂的构建类,这些工厂类都存在有共性的getter、setter。这些共性行为被形象到了CacheService中,通过动静代理,在service调用的办法实际上调用的是适配器类中的办法。 CacheService proxy_EGM = JDKProxy.getProxy(CacheServiceImpl.class, new EGMCacheAdapter()); proxy_EGM.set("user_name_01", "小傅哥"); String val01 = proxy_EGM.get("user_name_01"); System.out.println("测试后果:" + val01); CacheService proxy_IIR = JDKProxy.getProxy(CacheServiceImpl.class, new IIRCacheAdapter()); proxy_IIR.set("user_name_01", "小傅哥"); String val02 = proxy_IIR.get("user_name_01"); System.out.println("测试后果:" + val02);1.3 建造者模式 日常生活中,装修房子会依据不同的场景、品牌、型号、价格等等组合造成了各式各样的装修格调(套餐A:古代简洁,套餐B:轻奢田园,套餐C:欧式奢华)一些根本物料不会变,而其组合常常变动的时候,就能够抉择这样的构建者模式来构建代码。Builder 1.4 原型模式 在考试中,每个考生失去的考卷题目大致相同,都是从同一个考题池中随机组合一套题目进去分发给所有考生进行考试,然而这样失去的题目,题序一样,容易引起舞弊,而且还是一直地创立初始化对立对象。应用原型模式:通过克隆形式创立简单对象、也能够防止反复做初始化操作、不须要与类中所属的其余类耦合等。但也有一些毛病如果对象中包含了循环援用的克隆,以及类中深度应用对象的克隆,都会使此模式变得异样麻烦。(在重写的克隆办法中进行乱序)实现了Cloneable 1.5 单例模式 每次拿到或者创立取得的都是同一个实例例如:Spring中的通过@Autowird主动注入获取的对象也是单例模式的一种体现(设定的Bean注入模式是单例),其底层是通过Bean的注入模式去决定,单例模式是将new创立的实例放入容器,每次拿到的都是这个实例对象,原型模式的话就是把创立类的Class对象放入容器,每次拿都是调用这个Class.newInstance举荐应用枚举单例模式这种形式解决了最次要的;线程平安、自在串行化、繁多实例。enum 1.6 适配器模式 为存在共性行为然而调用办法不同的类创立适配器接口,适配器的实现类实际上调用的是原对象的对应办法。接口曾经做了对立的包装,内部应用时候就不须要关怀外部的具体逻辑了。而且在调用的时候只须要传入对立的参数即可,这样就满足了适配的作用。Adapter 1.7 桥接模式 桥接模式的次要作用就是通过将形象局部与实现局部拆散,把多种可匹配的应用进行组合。说白了外围实现也就是在A类中含有B类接口,通过构造函数传递B类的实现,这个B类就是设计的桥。通过模仿微信与支付宝两个领取渠道在不同的领取模式下,刷脸、指纹、明码,的组合从而体现了桥接模式的在这类场景中的正当使用。在领取形式中桥接了指纹领取、人脸领取 Pay zfbPay = new ZfbPay(new PayFingerprintMode());Bridge/在初始化时传入其它对象作为本类执行办法的判断 1.8 组合模式(没细品) 组合模式的次要解决的是一系列简略逻辑节点或者扩大的简单逻辑节点在不同构造的组织下,对于内部的调用是依然能够非常简单的。 1.9 装璜器模式(没细品) new BufferedReader(new FileReader(""));,这段代码你是否相熟,置信学习java开发到字节流、字符流、文件流的内容时都见到了这样的代码,一层嵌套一层,一层嵌套一层,字节流转字符流等等,而这样形式的应用就是装璜器模式的一种体现。 1.10 外观模式(没细品) 外观模式也叫门面模式,次要解决的是升高调用方的应用接口的简单逻辑组合。这样调用方与理论的接口提供方提供方提供了一个中间层,用于包装逻辑提供API接口。有些时候外观模式也被用在中间件层,对服务中的通用性简单逻辑进行中间件层包装,让应用方能够只关怀业务开发。 1.11 享元模式 ...

September 7, 2021 · 1 min · jiezi

关于设计模式:观察者模式的实际应用

前言设计模式不论是在面试还是工作中都会遇到,但我常常碰到小伙伴埋怨理论工作中本人利用设计模式的机会十分小。 正好最近工作中遇到一个用观察者模式解决问题的场景,和大家一起分享。 背景如下: 在用户创立完订单的规范流程中须要做额定一些事件: 同时这些业务也是不固定的,随时会依据业务倒退减少、批改逻辑。 如果间接将逻辑写在下单业务中,这一”坨“不是很外围的业务就会占据的越来越多,批改时还有可能影响到失常的下单流程。 当然也有其余计划,比方能够启动几个定时工作,定期扫描扫描订单而后实现本人的业务逻辑;但这样会节约许多不必要的申请。 观察者模式因而观察者模式就应运而生,它是由事件发布者在本身状态发生变化时发出通知,由观察者获取音讯实现业务逻辑。 这样事件发布者和接收者就能够齐全解耦,互不影响;实质上也是对开闭准则的一种实现。 示例代码 先大体看一下观察者模式所应用到的接口与关系: 主体接口:定义了注册实现、循环告诉接口。观察者接口:定义了接管主体告诉的接口。主体、观察者接口都能够有多个实现。业务代码只须要应用 Subject.Nofity() 接口即可。接下来看看创立订单过程中的实现案例。 代码采纳 go 实现,其余语言也是相似。首先依照上图定义了两个接口: type Subject interface { Register(Observer) Notify(data interface{})}type Observer interface { Update(data interface{})}因为咱们这是一个下单的事件,所以定义了 OrderCreateSubject 实现 Subject: type OrderCreateSubject struct { observerList []Observer}func NewOrderCreate() Subject { return &OrderCreateSubject{}}func (o *OrderCreateSubject) Register(observer Observer) { o.observerList = append(o.observerList, observer)}func (o *OrderCreateSubject) Notify(data interface{}) { for _, observer := range o.observerList { observer.Update(data) }}其中的 observerList 切片是用于寄存所有订阅了下单事件的观察者。 接着便是编写观察者业务逻辑了,这里我实现了两个: ...

September 6, 2021 · 1 min · jiezi

关于设计模式:深入浅出设计模式模板方法模式

1.模板办法模式介绍2.用代码演示模板办法模式3.总结4.在spring源码中,模板办法模式的利用 1.模板办法模式介绍 定义: 1)模板办法模式,在一个抽象类中公开定义了它的办法执行的模板,它的子类能够按需重写办法实现,但调用将以抽象类中定义的形式执行。 2)简略地说,模板办法模式定义一个操作中的算法骨架,而将一些步骤提早到子类中,使得子类能够不扭转一个算法的构造,就能够从新定义该算法的某些特定步骤。 3)这种类型的设计模式属于行为模式。 2.用代码演示模板办法模式 假如咱们有这样一个常见的需要:积分需要。简略地来说就是用户在生产的时候能够用积分抵扣金钱,如果交易胜利还能够处分积分,这就能够套用模板办法模式了。 咱们能够将积分处分/扣除的步骤分为三步 public interface IIntegralAction { //减少/扣除积分前的查看操作,如查看是否开户,检查用户是否异样,查看处分/应用数是否异样等等 void preCheck(String userId); //执行具体的增减逻辑 void excute(String userId); //执行后置逻辑,如更新数据工夫等等操作 void after(String userId);}再定义一个抽象类,来实现这个形象接口,并写好前置和后置的逻辑,设定好调用程序。 public abstract class AbstractIntegralAction implements IIntegralAction { //到时候子类调用这个办法就能够了 public void excuteMethod(String userId){ this.preCheck(userId); this.excute(userId); this.after(userId); } @Override public void preCheck(String userId) { //写好前置逻辑 System.out.println("执行前置查看逻辑"); } @Override public void excute(String userId) { //交给子类去实现 } @Override public void after(String userId) { //写好后置逻辑 System.out.println("执行后置更新逻辑"); }}调用办法: public static void main(String[] args) { AbstractIntegralAction abstractIntegralAction = new AddIntegeralAction(); abstractIntegralAction.excuteMethod("1"); }调用后果: ...

September 2, 2021 · 1 min · jiezi

关于设计模式:一文彻底搞懂单例模式SingletonPattern

文章已收录我的仓库:Java学习笔记与收费书籍分享 设计动机正如其名,单例模式保障一个类只有一个实例,那么为什么须要设计单例模式? 对一些类来说,只有一个实例是很重要的,例如一台电脑只应该由一个文件系统,生产厂商不应该为一台电脑配置两个文件系统;一个利用应该有一个专属的日志对象,而不应该一会儿写到这里一会儿写到那里;一个程序中往往只有一个线程池,由一个线程池治理线程,而不应该应用多个线程池,那样会使得线程乱套并且难以保护;在形象工厂中,具体的工厂类也只应该存在一个...... 诸如此类的要求,咱们都须要保障一个类只有一个实例,此时便能够应用单例模式。 设计咱们必须要避免用户实例化多个对象,解决办法是让类本人保留它的惟一实例,并将构造函数对外暗藏,并裸露特定静态方法返回惟一实例,这样用户将无奈本人实例化多个对象而只能通过类对外裸露的静态方法获取惟一实例。 代码示例假如需要如下:一个应用程序的全局状态中须要同一个日志对象。 一、懒汉模式懒汉模式并不间接初始化实例,而是等到实例被应用时才初始化它,防止不必要的资源节约。 //日志文件类class LogFile { //惟一实例 private static LogFile logFile = null; //构造方法对外暗藏 private LogFile(){}; //对外裸露的办法 public static LogFile getInstance() { //懒汉模式 if (logFile == null) { logFile = new LogFile(); } return logFile; }}public class Test { public static void main(String[] args) { var s1 = LogFile.getInstance(); var s2 = LogFile.getInstance(); System.out.println(s1 == s2); //输入true,产生的是同一个对象 }}这里的代码在单线程中运行良好,logFile属于临界区资源,因而这样的写法是线程不平安的,一开始实例为null,线程A执行完if判断句后在执行logFile = new LogFile()前被调度到线程B,此时线程B看到的实例也为空,因为A还没有初始化,所以线程B初始化实例,当回到线程A时,线程A将继续执行结构logFile的语句,此时logFile曾经被初始化两次了,它们A与B拿到的曾经不是同一个实例了。 一个简略的解决办法是为它们上锁: public static LogFile getInstance() { synchronized (LogFile.class) { //懒汉模式 if (logFile == null) { logFile = new LogFile(); } } return logFile;}然而这样上锁效率太低了,还不如采纳饿汉式,因为即时当logFile不为空时,多个线程也必须排队获取实例,而事实上并不需要排队,当logFile不为空时,多个线程该当能够同时获取logFile实例,因为它们仅仅只是读取实例而并不会更改实例,共享读是线程平安的。 ...

August 17, 2021 · 2 min · jiezi

关于设计模式:一文彻底搞懂工厂模式FactoryPattern

文章已收录我的仓库:Java学习笔记与收费书籍分享 模式类型工厂模式属于创建者模式,与对象的创立无关,其中工厂办法模式用于类,而形象工厂模式用于对象。创立型类模式将对象的局部创立工作提早到子类,由子类创建对象;而创立型对象模式将它提早到另一个对象中。 模式设计用意工厂模式将简单的对象创立工作暗藏起来,而仅仅暴露出一个接口供客户应用,具体的创立工作由工厂治理而对用户封装,将对象的创立和应用拆散开来,升高耦合度,便于管理,可能很好的反对变动。 对于某些类而言,其对象的创立可能是须要一系列简单的参数或大量筹备代码,当这个工作由客户实现时,如果客户创立多个简单对象,先不说这些代码可能难以编写,也会造成不必要的代码反复,交给工厂产生对象则不会造成代码反复,因为工厂中的代码写一次便能够复用无数次,可能缩小代码量,并且用户无需关注这些难以编写的代码,减少可读性,例如Spring框架中的beanFactory便是如此。 此外,将对象的创立和应用拆散开来,所有的创立工作由工厂治理,工厂能够治理类并适应相应业务变动,而无须对客户裸露,例如如果某个产品A降级为AA,咱们能够间接在工厂中将return new A()改为return new AA(),客户依然调用factory.createProductA()而无须变更代码,如果客户是通过new A()的模式创建对象,那么咱们还须要找到所有的代码并把它们改成new AA(),这在一个宏大的工程中是一项微小的工作。 当客户应用的对象可能发生变化时,例如一开始应用A产品而起初想应用B产品时,一般的形式咱们可能不得不更改所有的new办法,如果应用简略工厂模式,能够仅仅更改配置文件而无须更改客户代码来实现这个目标,如果应用工厂办法模式或者形象工厂模式,那么能够调整工厂的构造函数或者应用set注入来达到这个目标,大大减少因变动而造成的不适应性。 上述所说的所有都归功于将类的应用与创立解耦,这也就是整个工厂模式的核心思想与设计用意。无论何时,高内聚、低耦合永远都是编写须要思考到的中央。 工厂模式具体分为简略工厂、工厂办法和形象工厂模式,这些办法都合乎上述设计用意,但同时又满足不同的需要、适应不同的场景。 简略工厂(Simple Factory)设计定义一个创建对象的接口,创立一个子类通过传入的参数决定创立哪一种实例。 实用场景工厂类负责生产的对象较少。一个类不确定它所必须创立的对象的类的时候,具备不确定性。客户晓得须要传入工厂的参数而并不关怀具体的类创立逻辑。代码实例假如咱们具备如下需要:一家游戏厂商开发了A、B、C三种游戏,某个测试者被要求试玩相应游戏。 //定义游戏接口interface Game { public void play();}//A游戏class GameA implements Game{ public void play(){System.out.println("Playing GameA");};}//B游戏class GameB implements Game{ public void play(){System.out.println("Playing GameB");};}//C游戏class GameC implements Game{ public void play(){System.out.println("Playing GameC");};}class GameFactory { public Game createGame(char type) { switch (type) { case 'A': return new GameA(); case 'B': return new GameB(); case 'C': return new GameC(); } return null; }}//测试者(客户)类class Tester { private char type; public Tester(char type) { this.type = type; } public void testGame() { GameFactory gameFactory = new GameFactory(); //通过简略工厂获取游戏实例 Game game = gameFactory.createGame(type); //试玩游戏 game.play(); }}//代码测试public class Test { public static void main(String[] args) { //要求测试者试玩游戏A Tester tester = new Tester('A'); tester.testGame(); }}在测试代码Test类中咱们是这样写的: ...

August 17, 2021 · 3 min · jiezi

关于设计模式:一文彻底搞懂设计模式之建造者模式Builder

文章已收录我的仓库:Java学习笔记与收费书籍分享 设计用意为了将简单对象的构建与它的示意拆散,使得对象能够通过不同的示意创立进去。 例如对一个迷宫可能有墙、房间和门,并且数量不计。迷宫可能仅由一堵墙形成,也可能由两堵墙形成,也可能由2个房间加一扇门形成...如果采纳重载的形式生产迷宫,代码量是难以计数的、无比宏大的。 针对一个对象领有大量的组件(迷宫能够领有很多墙或房间或门),而结构这个对象对其组件的应用又是不确定的这一问题(应用墙、房间、门的数量是不确定的),想要精密的管制构建过程,此时能够采纳建造者模式解决问题。 建造者模式的用意是为了结构对象,因而它属于创立型模式。 实用场景结构过程中,被结构的对象具备不同的示意。一些根本部件不会变,而其组合常常变动的时候。须要生成的对象外部属性自身相互依赖。设计指派一个建造者交给总指挥,由总指挥设计如何建造,由建造者理论建造,最终建造者将产品交给总指挥,用户从总指挥手中实现交付。 这样的流程是十分人性化的,例如咱们理论的房子装修也是如此,咱们请一些工人们,再请一个工人喽罗设计建造思路,领导这些工人该如何装修,咱们接下来只与工人喽罗打交道,由工人喽罗将装修好的房子交付给咱们。 代码示例思考上述的迷宫问题: //定义迷宫类class Maze { public void setRoom(int x, int y, int roomId) { System.out.println("在[" + x + "," + y + "]处建设一座编号为" + roomId + "的房间"); //保留相干信息 } public void setDoor(int Id1, int Id2) { System.out.println("在组件编号为" + Id1 + "和组件编号为" + Id2 + "之间建设一扇门"); //保留相干信息 } public void setBarrier(int x, int y, int barrierId) { System.out.println("在[" + x + "," + y + "]处建设一座编号为" + barrierId + "的障碍物"); //保留相干信息 }}//定义迷宫建造者接口interface MazeBuilder { void buildRoom(int x, int y, int roomId);//建造房间 void buildDoor(int Id1, int Id2);//建造门 void buildBarrier(int x, int y, int barrierId);//建造障碍物 Maze getMaze();//获取最终后果}//迷宫建造团队A,每个建造团队的建造形式是不一样的class MazeBuilderA implements MazeBuilder { //建造团队将逐步完善这个迷宫,并交付给客户 private Maze maze = new Maze(); @Override public void buildRoom(int x, int y, int roomId) { maze.setRoom(x, y, roomId); } @Override public void buildDoor(int Id1, int Id2) { maze.setDoor(Id1, Id2); } @Override public void buildBarrier(int x, int y, int barrierId) { maze.setBarrier(x, y, barrierId); } @Override public Maze getMaze() { return maze; }}//迷宫指挥者类class MazeDirecotr { MazeBuilder mazeBuilder; public MazeDirecotr(MazeBuilder mazeBuilder) { this.mazeBuilder = mazeBuilder; } //将工作交给指挥,用户只须要期待修建实现取走实例 public Maze getMaze() { //具体的设计思维在这里产生 //在这里咱们能够一步一步依照咱们的想法结构出简单的模型 //例如这里我想要建造两个房间和两头的一扇门 mazeBuilder.buildRoom(0, 0, 0); mazeBuilder.buildRoom(0, 1, 1); mazeBuilder.buildDoor(0, 1); //理论的工作是由工人们建造的 //总指挥从工人们手中获取最终产品,由总指挥实现与用户的交接 return mazeBuilder.getMaze(); }}//测试类public class Test { public static void main(String[] args) { //请工人 MazeBuilder mazeBuilder = new MazeBuilderA(); //请指挥,并将工人交给其指挥 MazeDirecotr mazeDirecotr = new MazeDirecotr(mazeBuilder); //最终与总指挥实现产品交付 Maze maze = mazeDirecotr.getMaze(); }}//输入/* 在[0,0]处建设一座编号为0的房间在[0,1]处建设一座编号为1的房间在组件编号为0和组件编号为1之间建设一扇门*/通过建造者模式,咱们不再须要重载大量函数。通过设计导演类而一步一步的生成咱们冀望的对象,能够更加精密的管制创立的过程。理论开发中,导演类由用户本人编写定义,一个优化的技巧是采纳链式编程,咱们能够定义建造者接口如下: ...

August 17, 2021 · 2 min · jiezi

关于设计模式:一文彻底搞懂观察者模式Observer-Pattern

文章已收录我的仓库:Java学习笔记与收费书籍分享 设计用意定义对象间的一种一对多的依赖关系,当一个对象的状态产生扭转时,所有依赖于它的对象都失去告诉并被自动更新。 在理论设计开发中,咱们通常会升高类与类之间的耦合度,这样可能会产生一个副作用:因为类与类被宰割,咱们难以保护类之间的一致性。 举一个常见的例子,咱们对用户显示数学饼状图是须要数据撑持的,例如上面这张东京奥运会金牌榜: 在开发中,这张图表分为两个局部,一个是视图局部,也就是以饼状图呈现出的样子,一个是数据局部,即各国的金牌数量,因为咱们将数据与视图抽离,因而一旦数据局部更新,视图局部得不到最新的数据,难以维持一致性,这个时候咱们须要一个时刻关注数据变动的观察者,一旦观察者感知到数据变动则立刻更新视图,咱们能够让视图自身作为一个观察者,但这样设计是不好的,视图类该当做好设计视图的事而无需插手其余工作,更好的方法是独自拆散出一个观察者类以保护两个类之间的一致性,这就是观察者模式的设计用意。 在理论例子中,这种模式利用十分宽泛,例如一旦小说更新将会主动订阅,一旦会员过期将会主动续费,MVC三层模式中的控制器就会察看视图并实时更新模型局部......观察者模式是利用最宽泛的模式之一。 设计实现观察者模式时要留神具体指标对象和具体观察者对象之间不能间接调用,否则将使两者之间严密耦合起来,这违反了面向对象的设计准则。 观察者模式的次要角色如下。 形象主题(Subject)角色:也叫形象指标类或指标接口类,它提供了一个用于保留观察者对象的汇集类和减少、删除观察者对象的办法,以及告诉所有观察者的形象办法。具体主题(Concrete Subject)(被察看指标)角色:也叫具体指标类,它是被察看的指标,它实现形象指标中的告诉办法,当具体主题的外部状态产生扭转时,告诉所有注册过的观察者对象。观察者接口(Observer)角色:它是一个抽象类或接口,它蕴含了一个更新本人的形象办法,当接到具体主题的更改告诉时被调用。具体观察者(Concrete Observer)角色:实现形象观察者中定义的形象办法,以便在失去指标的更改告诉时更新本身的状态。设计接口(形象)是惯例的设计思维:定义一个接口由子类实现。这样做利于后续扩大,但如果确定只有一个被察看对象,则没有必要设计接口(形象)类。 常见的设计是:观察者到被察看指标中注册注销,通知它有一个观察者正在察看他,如有变动请告诉,随后察看指标发生变化,则告诉所有注册登录过的观察者并通知本人的身份(观察者可能察看多个指标,某些时候它必须晓得具体是那个指标产生了变动),随后观察者更新相应数据。 代码示例咱们思考上述数据与视图之间的例子,这里假如咱们的视图接管谷歌数据源与百度数据源: import java.util.ArrayList;import java.util.Date;import java.util.List;//视图类class View { //通过简单转换将数据可视化,这里简略的打印 public void show(Object data) { System.out.println(data); }}//定义抽象类 数据源类abstract class DataSource { //相干的源数据 protected String data = ""; //存储曾经注册过的观察者 protected List<Observer> observers = new ArrayList<>(); //获取该数据 public String getData() { return data; } //观察者到这里注册,被观察者保留观察者信息 public void addObserver(Observer observer) { observers.add(observer); } //移除更改观察者就不写了 //接口办法,更新数据,由指标类告诉观察者 abstract protected void updateData(String newData); //接口办法,告诉观察者,由子类采纳不同的办法实现 abstract public void notifyObserver();}//数据源类的具体实现之一,百度数据源类class BaiduDataSource extends DataSource { @Override protected void updateData(String newData) { //如果数据发生变化,则更新数据并告诉观察者 if (!newData.equals(data)) { //这一步是必须的,在告诉观察者前肯定要实现变动 //这就好比你今天才登程可你却通知你的好敌人明天走,你的好敌人来接你没看到你,情谊破碎 //必须要放弃状态的一致性 data = newData; notifyObserver(); } } @Override public void notifyObserver() { //播送音讯,并告知观察者本人是谁 for (var observer : observers) { observer.update(this, data); } }}//数据源类的具体实现之一,谷歌数据源类class GoogleDataSource extends DataSource { @Override protected void updateData(String newData) { //如果数据发生变化,则更新数据并告诉观察者 if (!newData.equals(data)) { //必须要放弃状态的一致性 data = newData; notifyObserver(); } } @Override public void notifyObserver() { //播送音讯,并告知观察者本人是谁 for (var observer : observers) { observer.update(this, data); } }}//观察者接口interface Observer { /** * 更新操作 * @param ds 察看的具体数据源 * @param data 更新的数据 */ void update(DataSource ds, String data);}//观察者Aclass ObserverA implements Observer { //由view示例委托察看数据源 private View view; public ObserverA(View view) { this.view = view; } @Override public void update(DataSource ds, String data) { System.out.println("察看到" + ds.getClass().getSimpleName() + "发生变化,更新视图"); //更新视图View view.show(data); }}//测试类public class Test { public static void main(String[] args) { //定义视图类 View view = new View(); view.show("初始状态"); System.out.println(); //定义与view相干数据源 DataSource bds = new BaiduDataSource();//百度数据源 DataSource gds = new GoogleDataSource();//谷歌数据源 //为view增加察看数据源的观察者 Observer observer = new ObserverA(view); //观察者须要到到数据源类中注册 bds.addObserver(observer); gds.addObserver(observer); //手动更新数据 bds.updateData("这是百度新数据--" + new Date()); System.out.println(); gds.updateData("这是谷歌新数据--" + new Date()); }}//输入/*初始状态察看到BaiduDataSource发生变化,更新视图这是百度新数据--Fri Jul 30 10:43:55 CST 2021察看到GoogleDataSource发生变化,更新视图这是谷歌新数据--Fri Jul 30 10:43:55 CST 2021*/探讨与优化咱们围绕下面的代码示例来探讨。 ...

August 17, 2021 · 2 min · jiezi

关于设计模式:一文彻底弄懂适配器模式Adapter-Pattern

回到博客导航 设计用意适配器模式(Adapter Pattern)是作为两个不兼容的接口之间的桥梁。这种类型的设计模式属于结构型模式,它联合了两个独立接口的性能。 在某些时候,客户冀望取得某种性能接口但现有的接口无奈满足客户的需要,例如美国的失常供电电压为110V,一个中国人带了一款中国制作电器去美国,这个电器必须要在220V电压下能力充电应用。这种状况下,客户(中国人)的冀望接口是有一个220V的电压为电器充电,但理论的接口是仅有一个110V的电压供电器充电,这种状况下就须要采纳一根电压转换器(适配器)使得110V的电压可能转换为220V的电压,供客户应用。 将一个类的接口转换成客户心愿的另外一个接口,这就是适配器须要做的事件,适配器模式使得本来因为接口不兼容而不能一起工作的那些类能够一起工作。 实用条件零碎须要应用现有的类,而此类的接口不合乎零碎的须要(外围需要)。想要建设一个能够重复使用的适配器类,用于与一些彼此之间没有太大关联的一些类,包含一些可能在未来引进的类一起工作,这些源类不肯定有统一的接口,但通过适配器使得它们都具备统一的接口。通过接口转换,将一个类插入另一个类系中。(比方老虎和走兽,当初多了一个飞虎,在不减少实体的需要下,减少一个适配器,在外面容纳一个虎对象,实现飞的接口。)设计通常有两种形式实现适配器模式,一种是类适配器,类适配器目前已不太应用,另一种实现形式是对象适配器,通常状况下采纳对象适配器会使得代码更易扩大与保护。 不论采纳何种形式,其根本的实现思维都是:对现有接口的实现类进行扩大,使其实现客户冀望的指标接口。 类适配器通过继承现有接口类并实现目标接口,这样的话会使得现有接口类齐全对适配器裸露,使得适配器具备现有接口类的全副性能,毁坏了封装性。此外从逻辑上来说,这也是不合乎常理的,适配器要做的是扩大现有接口类的性能而不是代替,类适配器只有在特定条件下会被应用。 对象适配器持有现有接口类一个实例,并扩大其性能,实现目标接口。这是举荐的形式,优先采纳组合而不是继承,会使得代码更利于保护。此外,这也是十分合乎常理的——“给我一根线,让我来给他加长到5m,我并不需要晓得这跟线是什么组成的,因为我的工作就是让线加长到5m”——咱们扩大了相应性能而并不关怀其具体实现。 类适配器结构图: 对象适配器结构图: Target:客户冀望取得的性能接口(220V电压供电)。Cilent:客户,冀望拜访Target接口(客户冀望能有220V电压)。Adaptee:现有接口,这个接口须要被适配(现有110V电压供电,须要被适配至220V)。Adapter:适配器类,适配现有接口使其合乎客户需要接口(适配110V电压,使其变为220V电压)。在适配器模式中,Cilent调用Adapter以取得相应性能,Adapter扩大Adaptee以实现对应性能。 代码示例类适配器://客户冀望的接口——220V的电压充电interface Target { void chargeBy220V();}//现有接口——只能通过110V电压充电interface Adaptee { void chargeBy110V();}//现有接口的具体实现类,美国供电器——通过110V电压供电class americanCharger implements Adaptee { @Override public void chargeBy110V() { System.out.println("美国供电器,只为你服务,正在通过110V电压为您充电"); }}//类适配器,通过继承现有接口来实现对现有接口的扩大class Adapter extends americanCharger implements Target { @Override public void chargeBy220V() { super.chargeBy110V();//现有性能 System.out.println("再加110V,达到220V,冲鸭!");//对现有性能扩大 }}//测试类public class Test { public static void main(String[] args) throws FileNotFoundException { //类适配器使得代码逻辑凌乱 //这种状况下好像Adapter是一种110V的美国供电器能够间接应用不须要其余信息 //具体能够和对象适配器比照以下 new Adapter().chargeBy220V(); }}//输入/*美国供电器,只为你服务,正在通过110V电压为您充电再加110V,达到220V,冲鸭!*/对象适配器://客户冀望的接口——220V的电压充电interface Target { void chargeBy220V();}//现有接口——只能通过110V电压充电interface Adaptee { void chargeBy110V();}//现有接口的具体实现类,美国供电器——通过110V电压供电class americanCharger implements Adaptee { @Override public void chargeBy110V() { System.out.println("美国供电器,只为你服务,正在通过110V电压为您充电"); }}//类适配器,通过继承现有接口来实现对现有接口的扩大,使得可能110V供电class Adapter implements Target { Adaptee adaptee;//持有现有接口具体实现对象的援用 public Adapter(Adaptee adaptee) { this.adaptee = adaptee; } @Override public void chargeBy220V() { adaptee.chargeBy110V();//该对象的现有性能 System.out.println("再加110V,达到220V,冲鸭!");//对现有性能扩大 }}//测试类public class Test { public static void main(String[] args) throws FileNotFoundException { //当初咱们有一个美国110V供电站,但咱们无奈应用 Adaptee adaptee = new americanCharger(); //咱们将这个供电器交给适配器,适配器转换为220V供电器 Adapter adapter = new Adapter(adaptee); //接下来咱们通过适配器充电就好了 adapter.chargeBy220V(); }}//输入同上对象适配器采纳组合的形式实现对现有接口的扩大以达到客户冀望的接口。 ...

August 16, 2021 · 2 min · jiezi

关于设计模式:设计模式之代理模式

代理模式定义顾名思义,代理模式就是应用代理的形式来拜访具体对象,而不是间接拜访对象。目标是提供一种代理也就是中间层来管制对实在对象的拜访,应用代理方不须要关怀实在对象外部的具体实现。举个例子,咱们平时坐火车能够到火车站售票处进行购票,也能够到代售点购票,代售点能够了解是火车站的一个售票代理。假如火车站售票处有售票、退票、改签所有服务,但只容许代售点只能售票、退票,不反对改签操作。这里代售点就是一个代理。UML类图 PHP 代码实现<?phpinterface ITicket{ public function buyTicket(); public function returnTicket();}class Ticket implements ITicket{ public function buyTicket() { echo '购票'; } public function returnTicket() { echo '退票'; } public function changeTicket() { echo '改签'; }}/** * 代理对象,代售点仅反对购票/退票 */class TicketProxy implements ITicket{ protected $ticket; public function __construct(Ticket $ticket) { $this->ticket = $ticket; } public function buyTicket() { $this->ticket->buyTicket(); } public function returnTicket() { $this->ticket->returnTicket(); }}$obj = new TicketProxy(new Ticket());$obj->buyTicket();应用场景近程代理。虚构代理。Copy-on-Write 代理。爱护(Protect or Access)代理。Cache代理。防火墙(Firewall)代理。同步化(Synchronization)代理。智能援用(Smart Reference)代理。

August 8, 2021 · 1 min · jiezi

关于设计模式:设计模式解析器Interpreter模式

模式定义给定一个语言,定义它的文法的一种示意,并定义一种解释器,这个解释器应用该示意来解释语言中的句子 类图 要点总结Interpreter模式的利用场合是Interpreter模式利用中的难点,只有满足“业务规定频繁变动,且相似的构造一直反复呈现,并且容易形象为语法规定的问题”才适宜应用Interpreter模式应用interpreter模式来示意文法规定,从而能够应用面向对象技巧来不便地“扩大”文法Interpreter模式比拟适宜简略的文法示意,对于简单的文法示意,Interpreter模式会产生比拟大的类层次结构,须要求助于语法分析生成器这样的规范工具Go语言代码实现工程目录 Interpretor.go package Interpreterimport "strings"type Expression interface { Interpret(variables map[string]Expression)int}type Interger struct { integer int}func (n *Interger) Interpret(variables map[string]Expression) int { return n.integer}type Plus struct { leftOperand Expression rightOperand Expression}func (p *Plus) Interpret(variables map[string]Expression) int { return p.leftOperand.Interpret(variables) + p.rightOperand.Interpret(variables)}func (e Evaluator) Interpret(variable map[string]Expression)int{ return e.syntaxTree.Interpret(variable)}type Variable struct { name string}type Node struct { value interface{} next *Node}type Stack struct { top *Node size int}func (s *Stack) Push (value interface{}){ s.top= &Node{ value: value, next: s.top, }}func (v *Variable) Interpret(variable map[string]Expression)int { value, found := variable[v.name] if !found { return 0 } return value.Interpret(variable)}func (s *Stack) Pop() interface{} { if s.size == 0{ return nil } value := s.top.value s.top = s.top.next s.size-- return value}type Evaluator struct { syntaxTree Expression}func NewEvaluator(expression string) *Evaluator{ expressionStack := new(Stack) for _, token := range strings.Split(expression, " ") { switch token { case "+": right := expressionStack.Pop().(Expression) left := expressionStack.Pop().(Expression) subExpression := &Plus{left, right} expressionStack.Push(subExpression) default: expressionStack.Push(&Variable{token}) } } syntaxTree := expressionStack.Pop().(Expression) return &Evaluator{syntaxTree: syntaxTree}}Interpretor_test.go ...

July 26, 2021 · 1 min · jiezi

关于设计模式:设计模式访问器Visitor模式

模式定义示意一个作用于某对象构造中的各元素的操作,使得能够在不扭转(稳固)各元素的类的前提下定义(扩大)作用于这些元素的新操作(变动) 类图 要点总结Visitor模式通过所谓双重散发(double dispatch)来实现在不更改(不增加新的操作-编译时)Element类层次结构的前提下,在运行时通明地为类层次结构上的各个类动静增加新的操作(反对变动)所谓双重散发即Visitor模式两头包含了两个多态散发:第一个为accept办法的多态辨析,第二个为visitElementX办法的多态辨析Visitor模式的最大毛病在于扩大类层次结构(减少新的Element子类),会导致Visitor类的扭转,因而Visitor模式实用于“Element类层次结构稳固,而其中的操作却常常面临频繁改变”Go语言代码实现工程目录 visitor.go package Visitorimport "fmt"type IVisitor interface { Visit()}type WeiBoVisitor struct {}func (w WeiBoVisitor) Visit(){ fmt.Println("Visit WeiBo")}type IQIYIVisitor struct {}func (i IQIYIVisitor) Visit () { fmt.Println("Visit IQiYi")}type IElement interface { Accept(visitor IVisitor)}type Element struct {}func (e Element) Accept(v IVisitor) { v.Visit()}visitor_test.go package Visitorimport "testing"func TestElement_Accept(t *testing.T) { e := new(Element) e.Accept(new(WeiBoVisitor)) e.Accept(new(IQIYIVisitor))}

July 26, 2021 · 1 min · jiezi

关于设计模式:设计模式命令Command模式

模式定义将一个申请(行为)封装为一个对象,从而使你可用不同的申请对客户进行参数化,对申请排队或记录申请日志,以及反对可撤销的操作 类图 要点总结Command模式的基本目标在于将“行为请求者”与“行为实现者”解耦,在面向对象语言中,常见的实现伎俩是“将行为形象为对象”实现Command接口的具体命令对象ConcreteCommand有时候依据须要可能会保留一些额定的状态信息,通过应用Composite模式,能够将多个“命令”封装为一个“复合命令”MacroCommandGo语言代码实现工程目录 command.go package Commandimport "fmt"type Person struct { name string cmd Command}type Command struct { person *Person method func()}func NewCommand (p *Person, method func()) Command { return Command{ person: p, method: method, }}func (c *Command) Execute(){ c.method()}func NewPerson (name string, cmd Command) Person{ return Person{ name: name, cmd: cmd, }}func (p *Person) Buy() { fmt.Println(fmt.Sprintf("%s is buying ", p.name)) p.cmd.Execute()}func (p *Person) Cook() { fmt.Println(fmt.Sprintf("%s is cooking ", p.name)) p.cmd.Execute()}func (p *Person) Wash() { fmt.Println(fmt.Sprintf("%s is washing ", p.name)) p.cmd.Execute()}func (p *Person) Listen() { fmt.Println(fmt.Sprintf("%s is listening ", p.name)) p.cmd.Execute()}func (p *Person) Talk() { fmt.Println(fmt.Sprintf("%s is talking ", p.name)) p.cmd.Execute()}command_test.go ...

July 26, 2021 · 1 min · jiezi

关于设计模式:设计模式责任链ResponsibilityChain模式

模式定义使多个对象都有机会解决申请,从而防止申请的发送者和接受者之间耦合关系,将这些对象连成一条链,并沿着这条链传递申请,直到有一个对象解决它为止 类图 要点总结Chain of Responsibility模式的利用场合在于“一个申请可能有多个接受者,然而最初真正的接受者只有一个”,这时候申请发送者与接受者的耦合有可能呈现“变动软弱”的症状,职责链的目标就是将二者解耦,从而更好地应答变动利用了Chain of Responsibility模式后,对象的职责调配将更具灵活性,咱们能够在运行时动静增加、批改申请的解决职责如果申请传递到职责链的开端任得不到解决,应该有一个正当的缺省机制,这也是每一个接受者对象的责任,而不是发出请求的对象的责任Go语言代码实现工程目录 responsibility_chain.go package Responsibility_Chainimport "strconv"type Handler interface { Handler(handlerID int) string}type handler struct { name string next Handler handlerID int}func NewHandler(name string, next Handler, handlerID int) *handler{ return &handler{ name: name, next: next, handlerID: handlerID, }}func (h *handler) Handler(handlerID int) string{ if h.handlerID == handlerID{ return h.name + " handled " + strconv.Itoa(handlerID) } return h.next.Handler(handlerID)}responsibility_chain_test.go package Responsibility_Chainimport ( "fmt" "testing")func TestNewHandler(t *testing.T) { wang := NewHandler("laowang", nil, 1) zhang := NewHandler("lanzhang", wang, 2) r := wang.Handler(1) fmt.Println(r) r = zhang.Handler(2) fmt.Println(r)}

July 26, 2021 · 1 min · jiezi

关于设计模式:设计模式迭代器Iterator模式

模式定义提供一中办法程序拜访一个聚合对象中的各个元素,而又不裸露(稳固)该对象的外部示意 类图 要点总结迭代形象:拜访一个聚合对象的外部而无需裸露它的外部示意迭代多态:为遍历不同的汇合构造提供一个对立的接口,从而反对同样的算法在不同的汇合构造上进行操作迭代器的健壮性思考:遍历的同时更改迭代器所在的汇合构造,会导致问题Go语言代码实现工程目录 iterator.go package Iteratortype Iterator interface { Index() int Value() interface{} HasNext() bool Next()}type ArrayIterator struct { array []interface{} index *int}func (a *ArrayIterator) Index() *int{ return a.index}func (a *ArrayIterator) Value() interface{} { return a.array[*a.index]}func (a *ArrayIterator) HasNext() bool { return *a.index + 1 <= len(a.array)}func (a *ArrayIterator) Next() { if a.HasNext(){ *a.index++ }}iterator_test.go package Iteratorimport ( "fmt" "testing")func TestArrayIterator(t *testing.T) { array := []interface{}{1,3,9,2,8,7} a := 0 iterator := ArrayIterator{array: array, index: &a} for it := iterator; iterator.HasNext(); iterator.Next(){ index, value := it.Index(), it.Value().(int) for value != array[*index]{ fmt.Println("error") } fmt.Println(*index, value) }}

July 26, 2021 · 1 min · jiezi

关于设计模式:设计模式组合Component模式

模式定义将对象组合成树形构造以示意“局部--整体”的层次结构,Composite使得用户对单个对象和组合对象的应用具备一致性(稳固) 类图 要点总结Composite模式采纳树形构造来实现普遍存在的对象容器,从而将“一对多”的关系转化为“一对一”的关系,使得客户代码能够统一地(复用)解决对象和对象容器,无需关系解决的是单个的对象,还是组合的对象容器将“客户代码与简单的对象容器构造”解耦是Composite的核心思想解耦之后,客户代码将于纯正的形象接口--而给对象容器的外部实现构造--产生依赖,从而更能“应答变动”Composite模式在具体实现中,能够让父对象中的子对象反向追溯,如果父对象有频繁的遍历需要,可应用缓存技巧来改善效率Go语言代码实现工程目录 composite.go package Compositeimport "fmt"type Component interface { Traverse()}type Leaf struct { value int}func NewLeaf (value int) *Leaf{ return &Leaf{value: value}}func (l *Leaf) Traverse() { fmt.Println(l.value)}type Composite struct { children []Component}func NewComposite() * Composite{ return &Composite{children: make([]Component, 0)}}func (c *Composite) Add (component Component) { c.children = append(c.children, component)}func (c *Composite) Traverse() { for idx, _ := range c.children{ c.children[idx].Traverse() }}composite_test.go package Compositeimport ( "fmt" "testing")func TestComposite_Traverse(t *testing.T) { containers := make([]Composite, 4) for i := 0; i< 4; i++ { for j := 0; j < 3 ; j++ { containers[i].Add(NewLeaf(i * 3 + j)) } } for i := 0; i < 4; i++ { containers[0].Add(&containers[i]) } for i := 0; i < 4; i++{ containers[i].Traverse() fmt.Printf("Finished\n") }}

July 26, 2021 · 1 min · jiezi

关于设计模式:设计模式备忘录Memento模式

模式定义在不毁坏封装性的前提下,捕捉一个对象的外部状态,并在该对象之外保留这个状态,这样当前就能够将该对象复原到原先保留的状态 类图 要点总结备忘录(Memento)存储原发器(Originator)对象的外部状态,在须要时复原原发器状态Memento模式的外围是信息暗藏,即Originator须要向外界暗藏信息,放弃其封装性,但同时又须要将状态放弃到外界(Memento)Go语言代码实现工程目录 memento.go package Mementotype Memento struct { state int}func NewMemento(value int) *Memento{ return &Memento{value}}type Number struct { value int}func NewNumber (value int) *Number{ return &Number{value: value}}func (n * Number) Double(){ n.value = 2 * n.value}func (n *Number) Half () { n.value /= 2}func (n *Number) Value() int { return n.value}func (n *Number) CreateMemento() *Memento{ return NewMemento(n.value)}func (n *Number) SetMemento(memento *Memento){ n.value = memento.state}memento_test.go package Mementoimport ( "fmt" "testing")func TestNumber_SetMemento(t *testing.T) { n := NewNumber(7) n.Double() n.Double() memento := n.CreateMemento() //记录以后时刻的值 n.Half() n.SetMemento(memento) //拿出过后记录的值 fmt.Println(n.value)}

July 26, 2021 · 1 min · jiezi

关于设计模式:设计模式状态State模式

模式定义容许一个对象在其外部状态扭转时扭转它的行为,从而使对象看起来仿佛批改了其行为 类图 要点总结State模式将所有与一个特定状态相干的行为都放入一个State的子类对象中,在对象状态切换时,切换相应的对象,但同时维持State的接口,这样实现了具体操作与状态转换之间的解耦为不同的状态引入不同的对象使得状态转换变得更加明确,而且能够保障不会呈现状态不统一的状况,因为转化是原子性的--即要么彻底转化过去,要么不转换如果State对象没有实例变量,那么各个上下文能够共享一个State对象,从而节俭对象开销Go语言代码实现工程目录 State.go package Stateimport "fmt"type State interface { On(m *Machine) Off(m *Machine)}type Machine struct { current State}func NewMachine() *Machine{ return &Machine{NewOff()}}func (m *Machine) setCurrent(s State) { m.current = s}func (m * Machine) On() { m.current.On(m)}func (m * Machine) Off() { m.current.Off(m)}type ON struct {}func NewON() State{ return &ON{}}func (o *ON) On(m *Machine) { fmt.Println("设施曾经开启...")}func (o * ON) Off(m * Machine) { fmt.Println("从On的状态到Off") m.setCurrent(NewOff())}type OFF struct {}func NewOff() State{ return &OFF{}}func (o *OFF) On (m *Machine) { fmt.Println("从Off状态到On") m.setCurrent(NewON())}func (o * OFF) Off(m * Machine) { fmt.Println("曾经敞开")}State_test.go ...

July 26, 2021 · 1 min · jiezi

关于设计模式:设计模式中介者Mediator模式

模式定义用一个中介对象来封装(封装变动)一系列的对象交互,中介者使各对象不须要显示的互相援用,从而使其耦合涣散(治理变动),而且能够独立地扭转它们之间的交互 类图 利用场景当多个对象相互关联交互并存在简单的援用关系时,且对新需要须要进行大量更改时应用中介者模式解耦合 长处能够防止互相交互的对象之间的紧耦合援用关系,从而更好地抵挡变动 要点总结要点总结将多个对象间简单的关联关系解耦,Mediator模式将多个对象间的管制逻辑进行集中管理,变“多个对象相互关联”为“多个对象和一个中介者关联”,简化了零碎的保护,抵挡了可能的变动随着管制逻辑的复杂化,Mediator具体对象的实现可能相当简单,这时候能够对Mediator对象进行合成解决Facade模式是解耦零碎间(单向)的对象关联关系,Mediator模式是解耦零碎内各个对象之间(双向)的关联关系Go语言代码实现工程目录 mediator.go package Mediatorimport "fmt"type Mediator interface { Communicate (who string)}type WildStallion interface { SetMediator(mediator Mediator)}type Bill struct { mediator Mediator}func (b * Bill) SetMediator(mediator Mediator) { b.mediator = mediator}func (b * Bill) Respond () { fmt.Println("bill what ?") b.mediator.Communicate("bill")}type Ted struct { mediator Mediator}func (t *Ted) Talk () { fmt.Println("Ted : Bill?") t.mediator.Communicate("Ted")}func (t *Ted) SetMediator(mediator Mediator) { t.mediator = mediator}func (t *Ted) Respond() { fmt.Println("Ted:how are you today?")}type ConcreteMediator struct { Bill Ted}func NewMediator() *ConcreteMediator { mediator := &ConcreteMediator{} mediator.Bill.SetMediator(mediator) mediator.Ted.SetMediator(mediator) return mediator}func (m *ConcreteMediator) Communicate(who string) { if who == "Ted" { m.Bill.Respond() }else { m.Ted.Respond() }}mediator_test.go ...

July 22, 2021 · 1 min · jiezi

关于设计模式:设计模式门面Facade模式

模式定义为子系统中的一组接口提供一个统一(稳固)的界面,Facade模式定义了一个高层接口,这个接口使得这个子系统更加容易应用(复用) 类图 利用场景1.当你须要应用简单子系统的无限但间接的接口时,请应用Facade模式 2.当你须要将子系统组织成层时,请应用Facade模式 长处简化客户端的调用 要点总结要点总结从客户程序的角度来看,Facade模式简化了整个组件零碎的接口,对于组件外部与内部客户程序来说,达到了一种“解耦”的成果--外部子系统的任何变动不会影响到facade接口的变动Facade设计模式更重视从架构的档次去看整个零碎,而不是单个类的档次,Facade很多时候更是一种架构设计模式Facade设计模式并非一个集装箱,能够任意地放进任何多个对象,Facade模式中组件的外部应该是“互相耦合关系比拟大的一系列组件”,而不是一个简略的性能汇合Go语言代码实现工程目录 facade.go package Facadeimport "fmt"type CarModel struct {}func NewCarModel() *CarModel { return &CarModel{}}func (c * CarModel) SetModel () { fmt.Println("CarModel - SetModel")}type CarEngine struct {}func NewCarEngine () *CarEngine { return &CarEngine{}}func (c *CarEngine) SetEngine (){ fmt.Println("CarEngine - SetEngine")}type CarBody struct {}func NewCarBody () *CarBody { return &CarBody{}}func (c *CarBody) SetCarBody() { fmt.Println("CarBody - SetBody")}type CarFacade struct { model CarModel engine CarEngine body CarBody}func NewCarFacade() * CarFacade{ return &CarFacade{ model: CarModel{}, engine: CarEngine{}, body: CarBody{}, }}func (c *CarFacade) CreateCompleteCar() { c.model.SetModel() c.engine.SetEngine() c.body.SetCarBody()}facade_test.go ...

July 22, 2021 · 1 min · jiezi

关于设计模式:设计模式享元Flyweight模式

模式定义使用共享技术无效地反对大量细粒度的对象 类图 利用场景如果零碎有大量相似的对象,能够应用享元模式 长处如果零碎有大量相似的对象,能够节俭大量的内存及CPU资源 要点总结要点总结如果零碎有解耦实现对象的代价问题,Flyweight次要解决面向对象的代价问题,个别不涉及面向对象的抽象性问题Flyweight采纳对象共享的做法来升高零碎中对象的个数,从而升高细粒度对象给零碎带来的内存压力。在具体实现方面,要留神对象状态的解决对象的数量太大从而导致对象内存开销加大--什么样的数量才算大?这须要咱们认真的依据具体利用状况进行评估,而不能凭空臆断Go语言代码实现工程目录 flyweight.go package Flyweighttype FlyWeight struct { Name string}func NewFlyWeight (name string) *FlyWeight{ return &FlyWeight{Name: name}}type FlyWeightFactory struct { pool map[string]*FlyWeight}func NewFlyWeightFactory() *FlyWeightFactory { return &FlyWeightFactory{pool: make(map[string]*FlyWeight)}}func (f *FlyWeightFactory) GetFlyWeight (name string) *FlyWeight { weight, ok := f.pool[name] if !ok { weight = NewFlyWeight(name) f.pool[name] = weight } return weight}flyweight_test.go package Flyweightimport "testing"import "github.com/stretchr/testify/assert"func TestFlyWeightFactory_GetFlyWeight(t *testing.T) { factory := NewFlyWeightFactory() hong := factory.GetFlyWeight("hong beauty") xiang := factory.GetFlyWeight("xiang beauty") assert.Len(t, factory.pool, 2) assert.Equal(t, hong, factory.pool["hong beauty"]) assert.Equal(t, xiang, factory.pool["xiang beauty"])}

July 22, 2021 · 1 min · jiezi

关于设计模式:设计模式建造者Builder模式

模式定义将一个简单对象的创立与他的示意拆散,使得同样的构建过程能够创立不同的示意 类图 利用场景1.须要生成的对象具备简单的内部结构; 2.须要生成的对象外部属性自身相互依赖; 3.与不可变对象配合应用; 长处1.建造者独立,易扩大; 2.便于管制细节危险; 要点总结Builder模式次要用于“分步骤构建一个简单的对象”,在这其中“分步骤”是一个稳固的算法,而简单对象的各个局部则常常变动变动点在哪里,封装哪里----Builder模式次要在于应答“简单对象各个局部”的频繁需要变动,其毛病在于难以应答“分步骤构建算法”的需要变动Go语言代码实现工程目录 Builder.go package Buildertype Builder interface { Part1() Part2() Part3()}type Director struct { builder Builder //建造者的接口}//发明接口func NewDirector (builder Builder) *Director { return &Director{builder: builder}}func (d *Director) Makedata(){ d.builder.Part1() d.builder.Part2() d.builder.Part3()}StringBuilder.go package Buildertype StringBuilder struct { result string}func (sb *StringBuilder) Part1 () { sb.result += "1"}func (sb *StringBuilder) Part2 () { sb.result += "2"}func (sb *StringBuilder) Part3 () { sb.result += "3"}func (sb *StringBuilder) GetResult() string { return sb.result}IntBuilder.go ...

July 21, 2021 · 1 min · jiezi

关于设计模式:如何利用云原生技术构建现代化应用

简介: 阿里云为企业提供了基于阿里云互联网架构的解决方案,也同时让这些新的互联网利用、新的电商平台利用迁徙到阿里云上。作者|愚奇 明天,云和云计算技术曾经被企业宽泛所承受,对于云、云计算、云原生都有十分多的话题,然而我比拟想探讨的是在所有云当中真正的配角,就是咱们的利用。 因为当企业应用上云后,这些利用的高可用能力有可能晋升了一部分,但仍存有许多问题;而当咱们探讨上云后这些利用的运维效率,却未必有很大的晋升,因为所有的运维都是基于基础设施进行的,而云计算是一个比拟大的基础设施的扭转;如果咱们再问,上云后整个利用的开发速度是不是失去了极大的晋升,这个时候很多人都要说,并不。 因而,明天次要探讨的就是如何利用云原生相干的技术帮忙咱们的利用去做优化,从传统利用转变成现代化利用。 非典型的典型——云上众生相 咱们先采取一个从个体再到整体的形而上的形式,来看一个比拟典型的企业案例。 这个企业尽管和很多上云企业有很多不同,比如说行业、利用类别、上云动机等等,但他们同时也有很多共同点:比方上云后解决了很多问题但依然遗留了相当多的问题。这个企业属于新批发行业,有不错的销售额。 然而随着业务的倒退,传统的 ERP 软件曾经不能满足业务倒退的诉求,最次要体现在当他要参加 618、双十一这样的年度大促时,他的 ERP 供应商通知他,他们的软件并不能反对达到上千或者上万的 TPS,只可能反对到百级的 TPS。因而对于这些新批发的电商企业而言,他们没有方法去满足大规模业务倒退的诉求,也因而找到了阿里云。 阿里云为企业提供了基于阿里云互联网架构的解决方案,也同时让这些新的互联网利用、新的电商平台利用迁徙到阿里云上。整体而言,开发是找了 ISV 去进行委托开发,把客户的利用从线下 IDC 迁徙到了线上公共云上,在这外面最次要的技术升级是区域化,上云之后整体的运维是客户本人的运维部门来负责。整个迁云的过程也十分胜利,很好地解决了客户利用的大规模问题,使得客户能够很好地参加 618、双十一这类的大促。 同时因为整体软件也就是这个电商平台采纳的是自研形式,所以比拟大地开释了像传统 ERP 一样昂扬的老本。但因为整体的构造迭代十分快,导致在有一次大促中,因为业务量十分大,导致原来架构中的一个隐患引发了比拟大的生产事变,对客户本人而言,他们评估这次事变给他们造成了十分大体量的损失。 To 云:“不上很焦虑,上了也焦虑” 所以说明天的很多企业,他们对于上云都有很多的焦虑,体现在他们思考到底要不要上云,因为上云不能只是单纯跟风,而是要想上云到底能够为他们解决什么问题。 对于上云之后的企业,他们尽管获得了阶段性的胜利,也须要思考他们还有哪些问题没有失去解决。所以说不论有没有上云的企业,他们都十分焦虑,这就体现在他们都在思考怎么样能力很好地缩短研发周期,以反对疾速的业务倒退须要;怎么样去晋升整体的运维效率,并在这个过程中让他们的 IT 部门具备很强的控制力;在整体上云和上云之后,能够比拟好地升高整体的 IT 利用老本,以及升高软件的复杂度,晋升整个零碎的高可用能力等,这些方方面面绝大部分都聚焦在利用的非功能性个性下面。 1、焦虑的本源 所有的这些焦虑,咱们能够从利用的角度去深度剖析是什么起因造成的。 大家晓得对于利用而言,外围的就是架构,包含了利用的业务架构和技术架构。从利用架构下来看,须要满足客户的利用倒退诉求。比如说数据的产生,随着明天 IoT 一直遍及,数据会产生十分大的接入量,对于这些数据的解决也带来了更高的要求。 基于传统的、更多的服务于人的申请的响应式数据处理形式曾经不能满足于业务的需要,对于 IoT 设施更多的是基于申请、响应这类事件的模型和形式。同样的,企业的业务倒退须要跟更多的公司去进行生态的连贯。这些大量的业务诉求也对底层的技术架构带来了比拟多的要求。这些要求就体现在,要求底层的技术架构可能反对高度的冗余,能反对微服务和海量的业务并发、以及可能反对动静伸缩、可能提供 SLA 等。 如果咱们再进一步深度挖掘,这外面到底是须要解决什么样的外围矛盾时,咱们能够发现其实外围矛盾在于随着上云、业务的复杂度一直减少,使得 IT 有更多的治理老本。而这个老本就体现在,所有的微服务、高可用都须要用高度的零碎冗余去解决。同时因为业务的疾速倒退,须要整个 IT 零碎去响应频繁的变换。外围矛盾就在于,零碎的高度冗余与零碎的频繁变动之间的矛盾,所有的分布式系统都在围绕这一主要矛盾来进行解决。 举个例子,在原来的单机时代,如果咱们只须要一个人治理一台机器,用一台机器上的软件就能够满足本身业务倒退的要求,那么咱们显然没有这么多的矛盾。只有当一个人变成几十甚至上百集体,当这样一台机器不是运行在一个节点而是几十上百甚至上千个节点时,整个 IT 须要解决的复杂度就从 1 对 1 变成了 1 对 N 的频发。所以说整体的复杂度失去了一个极大的晋升,这也是咱们所讲的矛盾的本源。 ...

July 20, 2021 · 1 min · jiezi

关于设计模式:设计模式原型Prototype模式

模式定义指原型实例指定创建对象的品种,并且通过拷贝这些原型创立新的对象 类图 利用场景当代码不应该依赖于须要复制的对象的具体类时 长处1.以不耦合具体类的状况下克隆对象; 2.防止反复的初始化代码; 3.更不便的构建简单对象; 要点总结Prototype模式同样用于隔离类对象的使用者和具体类型(易变类)之间的耦合关系,它同样要求这些“易变类”领有“稳固的接口”Prototype模式对于“如何创立易变类的实体对象”采纳“原型克隆”的办法来做,它使得咱们能够非常灵活地动态创建“领有某些稳固接口”的新对象--所需工作仅仅是注册一个新类的对象(即原型),而后在任何须要的中央CloneGo语言代码实现工程目录 prototype.go package ProtoType//原型对象须要实现的接口type Cloneable interface { Clone() Cloneable}//原型对象的类type ProtoTypeManger struct { Prototypes map[string]Cloneable}//结构初始化办法func NewProtoTypeManger () * ProtoTypeManger { return &ProtoTypeManger{make(map[string]Cloneable)}}//抓取func (p *ProtoTypeManger) Get (name string) Cloneable { return p.Prototypes[name]}//设置func (p *ProtoTypeManger) Set (name string, prototype Cloneable) { p.Prototypes[name] = prototype}type1.go package ProtoTypetype Type1 struct { name string}func (t * Type1) Clone() Cloneable { tc := *t //开拓内存新建变量,存储指针指向的内容 return &tc //return t}type2.go ...

July 19, 2021 · 1 min · jiezi

关于设计模式:设计模式抽象工厂Abstract-Factory模式

模式定义提供一个创立一系列相干或相互依赖对象的接口,而无需指定它们具体的类 类图 利用场景程序须要解决不同系列的相干产品,然而你不心愿它依赖于这些产品的具体类时能够应用形象工厂模式 长处1.能够确信你从工厂失去的产品彼此是兼容的; 2.能够防止具体产品和客户端代码之间的严密耦合; 3.合乎繁多职责准则; 4.合乎开闭准则 要点总结如果没有应答“多系列对象构建”的需要变动,则没有必要应用Abstract Factory模式,这时候应用简略的工厂齐全能够“系列对象”指的是在某一特定系列下的对象之间有相互依赖或作用的关系,不同系列的对象之间不能相互依赖Abstract Factory模式次要在于应答“新系列”的需要变动,其毛病在于难以应答“新对象”的需要变动Go语言代码实现工程目录 DaoFactory.go package AbstractFactory//记录接口type OrderMainDao interface { SaveOrderMain() //SearchOrderMain()}//详情接口type OrderDetailDao interface { SaveOrderDetail()}//形象工厂接口type DaoFactory interface { //一系列相干接口 CreateOrderMainDao() OrderMainDao CreateOrderDetailDao() OrderDetailDao}MYSQLDetailDaoFactory.go package AbstractFactoryimport "fmt"type MYSQLMainDao struct {}func (*MYSQLMainDao) SaveOrderMain() { fmt.Println("MYSQL main save")}type MYSQLDetailDao struct {}func (*MYSQLDetailDao) SaveOrderDetail() { fmt.Println("MYSQL detail save")}MYSQLFactory.go package AbstractFactory//形象工厂type MYSQLFactory struct {}func (*MYSQLFactory) CreateOrderMainDao() OrderMainDao { return &MYSQLMainDao{}}func (*MYSQLFactory) CreateOrderDetailDao() OrderDetailDao { return &MYSQLDetailDao{}}OracleFactory.go package AbstractFactory//形象工厂type OracleFactory struct {}func (*OracleFactory) CreateOrderMainDao() OrderMainDao { return &OracleMainDao{}}func (*OracleFactory) CreateOrderDetailDao() OrderDetailDao { return &OracleDetailDao{}}OracleDetailDaoFactory.go ...

July 19, 2021 · 1 min · jiezi

关于设计模式:设计模式工厂方法Factory-Method模式

模式定义定义一个用于创建对象的接口,让子类决定实例化哪一个类,使得一个类的实例化提早到子类 类图 利用场景1.当你不晓得该应用对象的确切类型的时候; 2.当你心愿为库或框架提供扩大其外部组件的办法时。 次要长处1.将具体产品和创建者解耦; 2.合乎繁多职责准则; 3.合乎开闭准则。 要点总结Factory Method模式用于隔离类对象的使用者和具体类型之间的耦合关系。面对一个常常变动的具体类型,紧耦合关系(new)会导致软件的软弱Factory Method模式通过面向对象的手法,将所要创立的具体对象工作提早到子类,从而实现一种扩大(而非更改)的策略,较好地解决了这种紧耦合关系Factory Method模式解放了“单个对象”的需要变动,毛病在于要求创立办法、参数雷同Go语言实现工程目录 OperatorFactory.go package Factory//理论运行类的接口type Operator interface { SetLeft(int) SetRight(int) Result() int}//工厂接口type OperatorFactory interface { Create() Operator}OperatorData.go package Factory//数据type OperatorData struct { left, right int}//赋值func (op *OperatorData) SetLeft(left int) { op.left = left}func (op *OperatorData) SetRight(right int) { op.right = right}PlusOpertaorFactory.go package Factory//操作的形象type PlusOpertaorFactory struct {}//操作类中蕴含操作数type PlusOpertaor struct { *OperatorData}//理论运行办法func(o PlusOpertaor) Result() int { return o.right + o.left}func(PlusOpertaorFactory) Create() Operator { return &PlusOpertaor{&OperatorData{}}}SubOpertaorFactory.go ...

July 19, 2021 · 1 min · jiezi

关于设计模式:设计模式桥Bridge模式

模式定义将形象局部(业务性能)与实现局部(平台实现)拆散,使它们都能够独立地变动。 类图 利用场景在业务性能具备形象性能和差别实现时须要独立的适应前面可能遇到的变动时应用桥接模式 长处1.合乎开闭准则 2.提供办法然而暗藏底层具体实现 3.将性能和实现拆散开来,有利于解耦 要点总结Bridge模式应用“对象间的组合关系”解耦了形象和实现之间固有的绑定关系,使得形象和实现能够沿着各自的维度来变动,所谓形象和实现沿着各自维度的变动,即“子类化”它们Bridge模式有时候相似于多继承计划,然而多继承计划往往违反了繁多职责准则,复用性比拟差,Bridge模式是比多继承计划更好的解决办法。Bridge模式的利用个别在“两个十分强的变动维度”,有时一个类也有多于两个维度的变动,这时能够应用Bridge的扩大模式。Go语言代码实现工程目录 Bridge.go  package Bridge  type Set struct {    impl map[string]bool }  func NewSet() *Set {    return &Set{make(map[string]bool)} }  func (s *Set) Add(key string) {    s.impl[key] = true }  func (s *Set) Iter(f func(key string)) {    for key := range s.impl{       f(key)    } }Bridge_test.go  package Bridge  import (    "fmt"    "testing" )  func TestNewSet(t *testing.T) {    s := NewSet()    s.Add("hello")    s.Add("world")    s.Iter(func(key string) {       fmt.Printf("key: %s\n", key)    }) }

July 19, 2021 · 1 min · jiezi

关于设计模式:设计模式装饰者Decorator模式

模式定义动静(组合)地给一个对象减少一些额定的职责,就减少性能而言,Decorator模式比生成子类(继承)更为灵便(打消反复代码并且缩小子类个数) 类图 利用场景扩大一个类的性能或给一个类增加附加职责 长处1.合乎开闭准则 2.不扭转原有对象的状况下给一个对象扩大性能 3.应用不同的组合能够实现不同的成果 要点总结通过采纳组合而非继承的手法,Decorator模式实现了在运行时动静扩大对象性能的能力,而且能够依据须要扩大多个性能。防止了应用继承带来的“灵活性差”和“多子类衍生问题”Decorator类在接口上体现为is-a 的继承关系,即Decorator类继承了Component类所具备的接口,但在实现上又体现为has-a的组合关系,即Decorator类又应用了另外一个Component类Decorator模式的目标并非解决“多子类衍生的多继承”问题,Decorator模式利用的要点在于解决“主体类在多个问题方向上的扩大性能”--是为“装璜”的含意Go语言代码实现工程目录 Decorator.go  package Decorator  import "fmt"  //定义一个形象组件 type Component interface {    Operate() }  //实现一个具体的组件:组件1 type Compontent1 struct {  }  func (c1 *Compontent1) Operate() {    fmt.Println("c1 operate") }  //定义一个形象的装璜者 type Decorator interface {    Component    Do() //这是一个额定的办法 }  //实现一个具体的装璜者 type Decorator1 struct {    c Component }  func (d1 *Decorator1) Do() {    fmt.Println("产生了装璜行为") }  func (d1 *Decorator1) Operate() {    d1.Do()    d1.c.Operate() }Decorator_test.go  package Decorator  import "testing"  func TestCompontent1_Operate(t *testing.T) {    c1 := &Compontent1{}    c1.Operate() }  func TestDecorator1_Operate(t *testing.T) {    d1 := &Decorator1{}    c1 := &Compontent1{}    d1.c = c1    d1.Operate() }

July 19, 2021 · 1 min · jiezi

关于设计模式:设计模式观察者Observer模式

模式定义定义了对象之间的一对多依赖,让多个观察者对象同时监听某一个主题对象,当主题对象发生变化时,它的所有依赖者都会收到告诉并更新 类图 利用场景当更改一个对象的状态可能须要更改其余对象,并且理论的对象当时未知或动静更改时,应用观察者模式 长处1.合乎开闭准则 2.能够在运行时建设对象之间的关系 要点总结应用面向对象的形象,Observe模式使得咱们能够独立地扭转指标与观察者,从而使二者之间的依赖关系达到松耦合指标发送告诉时,无需指定观察者,告诉(能够携带告诉信息作为参数)会主动流传观察者本人解决是否须要订阅告诉,指标对象对此无所不知Observer模式是基于事件的UI框架中十分罕用的设计模式,也是MVC模式的一个重要组成部分Go语言代码实现工程目录 observe.go  package Observer  import (    "fmt"    "sync"    "time" )  type Event struct {    Data int }  type Observer interface {    NotifyCallback(event Event) }  type Subject interface {    AddListener(observer Observer)    RemoveListener(observer Observer)    Notify(event Event) }  type eventObserver struct {    ID   int    Time time.Time }  type eventSubject struct {    Observers sync.Map }  func (e eventObserver) NotifyCallback(event Event) {    fmt.Printf("Recieved:%d after %v\n", event.Data, time.Since(e.Time)) }  func (e *eventSubject) AddListener(obs Observer) {    e.Observers.Store(obs, struct{}{}) }  func (e *eventSubject) RemoveListener(obs Observer) {    e.Observers.Delete(obs) }  func (e *eventSubject) Notify(event Event) {    e.Observers.Range(func(key, value interface{}) bool {       if key == nil {          return false      }       key.(Observer).NotifyCallback(event)       return true    }) }  func Fib(n int) chan int {    out := make(chan int)    go func() {       defer close(out)       for i, j := 0, 1; i < n; i, j = i+j, i {          out <- i      }    }()    return out }observer_test.go ...

July 19, 2021 · 2 min · jiezi

关于设计模式:设计模式策略Strategy模式

模式定义定义一系列算法,把它们一个个封装起来,并且使它们可相互替换(变动),该模式使得算法可独立于应用它的客户程序(稳固)而变动(扩大,子类化) 类图 要点总结Strategy及其子类为组件提供了一系列可重用的算法,从而能够使得类型在运行时不便地依据须要在各个算法之间进行替换Strategy模式提供了用条件判断语句以外的另一种抉择,打消条件判断语句,就是解耦合。含有许多条件判断语句的代码通常都须要Strategy模式如果Strategy对象没有实例变量,那么各个上下文能够共享一个Strategy对象,从而节俭对象开销Go语言代码实现工程目录 strategy.go  package Strategy  //策略接口 type Strategy interface {    Execute() }strategyA.go  package Strategy  import "fmt"  //策略A type strategyA struct {  }  //实现接口 func (s *strategyA) Execute(){    fmt.Println("A plan executed.") }  //简略工厂办法 func NewStrategyA() Strategy {    return &strategyA{} }strategyB.go  package Strategy  import "fmt"  //策略B type strategyB struct {  }  //实现接口 func (s *strategyB) Execute() {    fmt.Println("B plan executed.") }  //简略工厂办法 func NewStrategyB() Strategy {    return &strategyB{} }context.go  package Strategy  //上下文,也能够了解为主逻辑 type Context struct {    strategy Strategy }  //多态办法 func NewContext() *Context {    return &Context{} }  //多态设置具体的对象 func (c *Context) SetStrategy(strategy Strategy) {    c.strategy = strategy }  //多态办法执行具体策略 func (c *Context) Execute(){    c.strategy.Execute() }strategy_test.go ...

July 19, 2021 · 1 min · jiezi

关于设计模式:设计模式模板方法Template-Method模式

模式定义定义一个操作的算法骨架,而将一些步骤提早到子类中,使得子类能够不扭转一个算法的构造即可重定义该算法某些特定步骤 类图 要点总结Template Method模式是一种十分基础性的设计模式,在面向对象零碎中有着大量的利用(像C++中虚函数的多态性)除了能够灵便应答子步骤的变动外,“不要调用我,让我来调用你”的反向控制结构是Template Method的典型利用Go语言代码实现工程目录 template.go  package Template  //工作流程接口 type WorkInterface interface {    GetUp()    Work()    Sleep() }  //工作人员绑定了工作流程接口 type Worker struct {    WorkInterface }  //工厂模式,生产一个具体的工作人员对象(随时变动的) func NewWorker(w WorkInterface) *Worker {    return &Worker{w} }  //主流程已定好(模板办法),实用于不同的工作人员(稳固不变的) func (w *Worker) Daily(){    w.GetUp()    w.Work()    w.Sleep() }coder.go  package Template  import "fmt"  //程序员类定义 type Coder struct {  }  //程序员办法的具体实现接口 func (c *Coder) GetUp(){    fmt.Println("coder GetUp.") }  func (c *Coder) Work(){    fmt.Println("coder is Coding.") }  func (c *Coder) Sleep(){    fmt.Println("coder Sleep.") }teacher.go  package Template  import "fmt"  type Teacher struct {  }  func (t *Teacher) GetUp(){    fmt.Println("teacher GetUp.") }  func (t *Teacher) Work(){    fmt.Println("teacher is speaking.") }  func (t *Teacher) Sleep(){    fmt.Println("teacher Sleep.") }template_test.go ...

July 19, 2021 · 1 min · jiezi

关于设计模式:程序设计中的几种设计原则

依赖倒置准则(DIP)高层模块(稳固)不应该依赖于底层模块(变换),二者都应该依赖于形象(稳固)形象(稳固)不应该依赖于实现细节(变动), 实现细节应该依赖于形象(稳固)开闭准则对扩大凋谢,对更改关闭类模块应该是可扩大的,然而不可批改繁多职责准则一个类应该仅有一个引起它变动的起因变动的方向隐含着类的责任Liskov替换准则(LSP)子类必须可能替换它们的基类(IS-A)继承表白类型形象接口隔离准则(ISP)不应该强制客户程序依赖它们不必的办法接口应该小而齐备优先应用对象组合,而不是类继承类继承通常为“白箱复用”,对象组合通常为“黑箱复用”继承在某种程度上毁坏了封装性,子类父类耦合度高而对象组合则只要求被组合的对象具备良好定义的接口耦合度低封装变动点应用封装来创建对象之间的分阶层,让设计者能够在合成点的一侧进行批改,而不会对另一侧产生不良的影响,从而实现耦合针对接口编程,而不是针对实现编程不将变量类型申明为某个特定的具体类,而是申明为某个接口客户程序无需获知对象的具体类型,只须要直到对象所具备的接口缩小零碎中各局部的依赖关系,从而实现“高内聚,松耦合”的类型设计方案重构的要害技法动态->动静早绑定->晚绑定继承-> 组合编译时依赖->运行时依赖紧耦合->松耦合

July 19, 2021 · 1 min · jiezi

关于设计模式:设计模式单例模式

单例模式定义:保障一个类仅有一个实例,并提供一个全局拜访点类型:创立型实用场景:想确保任何状况下都相对只有一个实例长处: 在内存里只有一个实例,缩小了内存开销能够防止对资源的多重占用设置全局拜访点,严格控制拜访毛病:没有接口,扩大艰难重点: 公有结构器线程平安提早加载序列化和反序列化平安反射Double Check 动态外部类: 实用技能 反编译内存原理多线程Debug 相干设计模式 单例模式和工厂模式单例模式和享元模式代码示例懒汉式public class LazySingleton { private static LazySingleton lazySingleton; private LazySingleton() { } /** * synchronized(同步锁比拟耗费资源) * 加在静态方法上:锁的是类的class文件 * 加在一般办法上:锁的是堆内存中的对象 * @return */ public synchronized static LazySingleton getInstance(){//懒汉式 if(lazySingleton==null){ lazySingleton = new LazySingleton(); } return lazySingleton; }}public class T implements Runnable{ @Override public void run() { LazySingleton lazySingleton = LazySingleton.getInstance(); System.out.println(Thread.currentThread()+" "+lazySingleton); }}测试类: public class Test { public static void main(String[] args) {// LazySingleton lazySingleton = LazySingleton.getInstance(); Thread t1 = new Thread(new T()); Thread t2 = new Thread(new T()); t1.start(); t2.start(); System.out.println("program end");/* for (int i = 0; i < 10; i++) { new Thread(new T()).start(); }*/ }}双重校验(改良): ...

July 18, 2021 · 4 min · jiezi

关于设计模式:设计模式建造者模式

建造者模式定义:将一个简单对象的构建与它的示意拆散,使得同样的构建过程能够创立不同的示意用户只需指定须要建造的类型就能够失去它们,建造过程及细节不须要晓得类型:创立型实用场景: 如果一个对象有非常复杂的内部结构(很多属性)想把简单对象的创立和应用拆散长处: 封装性好,创立和应用拆散扩展性好、建造类之间独立、肯定水平上解耦毛病: 产生多余的Builder对象产品外部发生变化,建造者都要批改,老本较大代码示例版本一: public class Course { private String courseName; private String coursePPT; private String courseVideo; private String courseArticle;// question&Answer private String courseQA; public String getCourseName() { return courseName; } public void setCourseName(String courseName) { this.courseName = courseName; } public String getCoursePPT() { return coursePPT; } public void setCoursePPT(String coursePPT) { this.coursePPT = coursePPT; } public String getCourseVideo() { return courseVideo; } public void setCourseVideo(String courseVideo) { this.courseVideo = courseVideo; } public String getCourseArticle() { return courseArticle; } public void setCourseArticle(String courseArticle) { this.courseArticle = courseArticle; } public String getCourseQA() { return courseQA; } public void setCourseQA(String courseQA) { this.courseQA = courseQA; } @Override public String toString() { return "Course{" + "courseName='" + courseName + '\'' + ", coursePPT='" + coursePPT + '\'' + ", courseVideo='" + courseVideo + '\'' + ", courseArticle='" + courseArticle + '\'' + ", courseQA='" + courseQA + '\'' + '}'; }}public abstract class CourseBuilder { public abstract void buildCourseName(String courseName); public abstract void buildCoursePPT(String coursePPT); public abstract void buildCourseVideo(String courseVideo); public abstract void buildCourseArticle(String courseArticle); public abstract void buildCourseQA(String courseQA); public abstract Course makeCourse();}public class CourseActualBuilder extends CourseBuilder{ private Course course = new Course(); @Override public void buildCourseName(String courseName) { course.setCourseName(courseName); } @Override public void buildCoursePPT(String coursePPT) { course.setCoursePPT(coursePPT); } @Override public void buildCourseVideo(String courseVideo) { course.setCourseVideo(courseVideo); } @Override public void buildCourseArticle(String courseArticle) { course.setCourseArticle(courseArticle); } @Override public void buildCourseQA(String courseQA) { course.setCourseQA(courseQA); } @Override public Course makeCourse() { return course; }}public class Coach { private CourseBuilder courseBuilder; public void setCourseBuilder(CourseBuilder courseBuilder) { this.courseBuilder = courseBuilder; } public Course makeCourse(String courseName,String coursePPT, String courseVideo,String courseArticle, String courseQA){ courseBuilder.buildCourseName(courseName); courseBuilder.buildCoursePPT(coursePPT); courseBuilder.buildCourseVideo(courseVideo); courseBuilder.buildCourseArticle(courseArticle); courseBuilder.buildCourseQA(courseQA); return courseBuilder.makeCourse(); }}测试类: ...

July 18, 2021 · 3 min · jiezi

关于设计模式:浅谈-SOLID-原则的具体使用

繁多职责准则(SRP)凋谢关闭准则(OCP)里氏替换准则(LSP)接口隔离准则(ISP)依赖倒置准则(DIP) SOLID 是面向对象设计5大重要准则的首字母缩写,当咱们设计类和模块时,恪守 SOLID 准则能够让软件更加强壮和稳固。那么,什么是 SOLID 准则呢?本篇文章我将谈谈 SOLID 准则在软件开发中的具体应用。 繁多职责准则(SRP)繁多职责准则(SRP)表明一个类有且只有一个职责。一个类就像容器一样,它能增加任意数量的属性、办法等。然而,如果你试图让一个类实现太多,很快这个类就会变得轻便。任意小的扭转都将导致这个单一类的变动。当你改了这个类,你将须要从新测试一遍。如果你恪守 SRP,你的类将变得简洁和灵便。每一个类将负责繁多的问题、工作或者它关注的点,这种形式你只须要扭转相应的类,只有这个类须要再次测试。SRP 外围是把整个问题分为小局部,并且每个小局部都将通过一个独自的类负责。 假如你在构建一个应用程序,其中有个模块是依据条件搜寻顾客并以Excel模式导出。随着业务的倒退,搜寻条件会一直减少,导出数据的分类也会一直减少。如果此时将搜寻与数据导出性能放在同一个类中,势必会变的轻便起来,即便是渺小的改变,也可能影响其余性能。所以依据繁多职责准则,一个类只有一个职责,故创立两个独自的类,别离解决搜寻以及导出数据。 凋谢关闭准则(OCP)凋谢关闭准则(OCP)指出,一个类应该对扩大凋谢,对批改敞开。这象征一旦你创立了一个类并且应用程序的其余局部开始应用它,你不应该批改它。为什么呢?因为如果你扭转它,很可能你的扭转会引发零碎的解体。如果你须要一些额定性能,你应该扩大这个类而不是批改它。应用这种形式,现有零碎不会看到任何新变动的影响。同时,你只须要测试新创建的类。 假如你当初正在开发一个 Web 应用程序,包含一个在线征税计算器。用户能够拜访Web 页面,指定他们的支出和费用的细节,并应用一些数学公式来计算应纳税额。思考到这一点,你创立了如下类: public class TaxCalculator{ public decimal Calculate(decimal income, decimal deduction, string country){ decimal taxAmount = 0; decimal taxableIncome = income - deduction; switch (country) { case "India": //Todo calculation break; case "USA": //Todo calculation break; case "UK": //Todocalculation break; } return taxAmount;}}这个办法非常简单,通过指定支出和收入,能够动静切换不同的国家计算不同的征税额。但这里隐含了一个问题,它只思考了3个国家。当这个 Web 利用变得越来越风行时,越来越多的国家将被加进来,你不得不去批改 Calculate 办法。这违反了凋谢关闭准则,有可能你的批改会导致系统其余模块的解体。 让咱们对这个性能进行重构,以合乎对扩大是凋谢,对批改是关闭的。 依据类图,能够看到通过继承实现横向的扩大,并且不会引发对其余不相干类的批改。这时 TaxCalculator 类中的 Calculate 办法会异样简略: ...

July 18, 2021 · 1 min · jiezi

关于设计模式:设计模式抽象工厂模式

形象工厂模式定义:形象工厂模式提供一个创立一系列相干或相互依赖对象的接口毋庸指定它们具体的类类型:创立型实用场景 客户端(应用层)不依赖于产品类实例如何被创立、实现等细节强调一系列相干的产品对象(属于同一产品族)一起应用创建对象须要大量反复的代码提供一个产品类的库,所有的产品以同样的接口呈现,从而使客户端不依赖于具体实现长处: 具体产品在应用层代码隔离,毋庸关怀创立细节将一个系列的产品族对立到一起创立毛病: 规定了所有可能被创立的产品汇合,产品族中扩大新的产品艰难,须要批改形象工厂的接口减少了零碎的抽象性和了解难度产品等级构造与产品族 代码示例 public interface CourseFactory { Video getVideo(); Article getArticle();}public abstract class Video { public abstract void produce();}public abstract class Article { public abstract void produce();}public class JavaCourseFactory implements CourseFactory{ @Override public Video getVideo() { return new JavaVideo(); } @Override public Article getArticle() { return new JavaArticle(); }}public class JavaVideo extends Video{ @Override public void produce() { System.out.println("录制Java课程视频"); }}public class JavaArticle extends Article{ @Override public void produce() { System.out.println("撰写Java课程手记"); }}public class PythonCourseFactory implements CourseFactory{ @Override public Video getVideo() { return new PythonVideo(); } @Override public Article getArticle() { return new PythonArticle(); }}public class PythonVideo extends Video{ @Override public void produce() { System.out.println("录制Python课程视频"); }}public class PythonArticle extends Article{ @Override public void produce() { System.out.println("撰写Python课程手记"); }}public class Test { public static void main(String[] args) { CourseFactory courseFactory = new JavaCourseFactory(); Video video = courseFactory.getVideo(); Article article = courseFactory.getArticle(); video.produce(); article.produce(); }}利用场景JDK: ...

July 18, 2021 · 1 min · jiezi

关于设计模式:设计模式工厂方法模式

工厂办法模式定义:定义一个创建对象的接口,但让实现这个接口的类来决定实例化哪个类。工厂办法让类的实例化推延到子类中进行。类型:创立型实用场景: 创建对象须要大量反复的代码客户端(应用层)不依赖于产品类实例如何被创立、实现等细节一个类通过其子类来指定创立哪个对象长处: 用户只须要关怀所需产品对应的工厂,毋庸关怀创立细节退出新产品合乎开闭准则,进步可扩展性毛病: 类的个数容易过多,减少复杂度减少了零碎的抽象性和了解难度代码示例 实体类: public abstract class Video { public abstract void produce();}public class JavaVideo extends Video { @Override public void produce() { System.out.println("录制Java视频"); }}public class PythonVideo extends Video { @Override public void produce() { System.out.println("录制Python视频"); }}public class FEVideo extends Video{ @Override public void produce() { System.out.println("录制FE视频"); }}工厂类: public abstract class VideoFactory { public abstract Video getVideo();}public class JavaVideoFactory extends VideoFactory{ @Override public Video getVideo() { return new JavaVideo(); }}public class PythonVideoFactory extends VideoFactory{ @Override public Video getVideo() { return new PythonVideo(); }}public class FEVideoFactory extends VideoFactory{ @Override public Video getVideo() { return new FEVideo(); }}测试类: ...

July 18, 2021 · 1 min · jiezi

关于设计模式:设计模式简单工厂

简略工厂定义:由一个工厂对象决定创立出哪一种产品类的实例类型:创立型,但不属于GOF23种设计模式实用场景: 工厂类负责创立的对象比拟少客户端(应用层)只晓得传入工厂类的参数,对于如何创建对象(逻辑)不关怀长处:只须要传入一个正确的参数,就能够获取你所须要的对象,而无须晓得其创立细节毛病:工厂类的职责绝对过重,减少新的产品须要批改工厂类的判断逻辑,违反开闭准则代码示例 public abstract class Video { public abstract void produce();}public class JavaVideo extends Video{ @Override public void produce() { System.out.println("录制Java视频"); }}public class PythonVideo extends Video{ @Override public void produce() { System.out.println("录制Python视频"); }}public class VideoFactory { public Video getVideo(Class cls) {//String type Video video = null; try { video = (Video) Class.forName(cls.getName()).newInstance(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } return video;/* if ("java".equalsIgnoreCase(type)){ return new JavaVideo(); }else if ("python".equalsIgnoreCase(type)){ return new PythonVideo(); } return null;*/ }}测试类: ...

July 17, 2021 · 1 min · jiezi

关于设计模式:软件设计的七大原则

软件设计七大准则开闭准则定义:一个软件实体如类、模块和函数应该对扩大凋谢,对批改敞开。用形象构建框架,用实现扩大细节。长处:进步软件系统的可复用性及可维护性。代码示例接口: public interface ICourse { Integer getId(); String getName(); Double getPrice();}基类: public class JavaCourse implements ICourse{ private Integer id; private String name; private Double price; public JavaCourse(Integer id, String name, Double price) { this.id = id; this.name = name; this.price = price; } @Override public Integer getId() { return this.id; } @Override public String getName() { return this.name; } @Override public Double getPrice() { return this.price; } @Override public String toString() { return "JavaCourse{" + "id=" + id + ", name='" + name + '\'' + ", price=" + price + '}'; }}扩大类(子类): ...

July 17, 2021 · 5 min · jiezi

关于设计模式:九种常用的UML图总结转

九种罕用的UML图总结

July 17, 2021 · 1 min · jiezi

关于设计模式:单例模式

利用场景封装一些罕用的工具类,保障整个利用罕用的数据对立保留一些共享数据在内存中,其余类随时能够读取。创建对象耗时或者消耗资源过多,但又须要频繁用到;须要频繁的进行创立和销毁的对象;留神:如果写成单例模式就不要用spring注入了,spring注入默认单例,两者反复7种形式 饿汉式线程平安public class Singleton { private static final Singleton instance = new Singleton(); private Singleton() { } public static Singleton getInstance() { return instance; }}线程平安,类加载的时候实例化,意思就是在初始化instance的时候就new了,所以导致资源节约(求全责备的说) 懒汉式-线程不平安线程不平安public class Singleton { private static Singleton instance;private Singleton() {}public static Singleton getInstance() { if (instance == null) { instance = new Singleton(); } return instance;}}首次我调用getInstance,那么就会进行类加载,这时候instance援用没被初始化。而后进行判断空后,给instance援用初始化一个对象。下次调用getInstance因为是不是空,间接返回。疑难:我调用getInstance后,都会返回一个对象。饿汉式只是说初始化的时候就new了对象,而我这做了判断再new,本质上都把对象new了。那么懒汉式节俭资源体现在哪? 体现在你调用类的其它办法的时候,它不会new(实例化)对象!上代码! 懒汉式-同步办法线程平安,同步办法public class Singleton { private static Singleton instance; private Singleton() { } public static synchronized Singleton getInstance() { if (instance == null) { instance = new Singleton(); } return instance; }}线程平安,但效率低下! ...

July 15, 2021 · 2 min · jiezi

关于设计模式:如何利用云原生技术构建现代化应用

简介:在2021研发效力峰会上,阿里云中间件首席架构师愚奇就“如何利用云原生技术构建现代化利用”的主题分享了,如何利用云的个性及云原生的技术及产品,帮忙企业的传统利用转化为现代化利用。作者 | 愚奇 明天,云和云计算技术曾经被企业宽泛所承受,对于云、云计算、云原生都有十分多的话题,然而我比拟想探讨的是在所有云当中真正的配角,就是咱们的利用。 因为当企业应用上云后,这些利用的高可用能力有可能晋升了一部分,但仍存有许多问题;而当咱们探讨上云后这些利用的运维效率,却未必有很大的晋升,因为所有的运维都是基于基础设施进行的,而云计算是一个比拟大的基础设施的扭转;如果咱们再问,上云后整个利用的开发速度是不是失去了极大的晋升,这个时候很多人都要说,并不。 因而,明天次要探讨的就是如何利用云原生相干的技术帮忙咱们的利用去做优化,从传统利用转变成现代化利用。 非典型的典型——云上众生相咱们先采取一个从个体再到整体的形而上的形式,来看一个比拟典型的企业案例。 这个企业尽管和很多上云企业有很多不同,比如说行业、利用类别、上云动机等等,但他们同时也有很多共同点:比方上云后解决了很多问题但依然遗留了相当多的问题。这个企业属于新批发行业,有不错的销售额。 然而随着业务的倒退,传统的 ERP 软件曾经不能满足业务倒退的诉求,最次要体现在当他要参加 618、双十一这样的年度大促时,他的 ERP 供应商通知他,他们的软件并不能反对达到上千或者上万的 TPS,只可能反对到百级的 TPS。因而对于这些新批发的电商企业而言,他们没有方法去满足大规模业务倒退的诉求,也因而找到了阿里云。 阿里云为企业提供了基于阿里云互联网架构的解决方案,也同时让这些新的互联网利用、新的电商平台利用迁徙到阿里云上。整体而言,开发是找了 ISV 去进行委托开发,把客户的利用从线下 IDC 迁徙到了线上公共云上,在这外面最次要的技术升级是区域化,上云之后整体的运维是客户本人的运维部门来负责。整个迁云的过程也十分胜利,很好地解决了客户利用的大规模问题,使得客户能够很好地参加 618、双十一这类的大促。 同时因为整体软件也就是这个电商平台采纳的是自研形式,所以比拟大地开释了像传统 ERP 一样昂扬的老本。但因为整体的构造迭代十分快,导致在有一次大促中,因为业务量十分大,导致原来架构中的一个隐患引发了比拟大的生产事变,对客户本人而言,他们评估这次事变给他们造成了十分大体量的损失。 To 云:“不上很焦虑,上了也焦虑”所以说明天的很多企业,他们对于上云都有很多的焦虑,体现在他们思考到底要不要上云,因为上云不能只是单纯跟风,而是要想上云到底能够为他们解决什么问题。 对于上云之后的企业,他们尽管获得了阶段性的胜利,也须要思考他们还有哪些问题没有失去解决。所以说不论有没有上云的企业,他们都十分焦虑,这就体现在他们都在思考怎么样能力很好地缩短研发周期,以反对疾速的业务倒退须要;怎么样去晋升整体的运维效率,并在这个过程中让他们的 IT 部门具备很强的控制力;在整体上云和上云之后,能够比拟好地升高整体的 IT 利用老本,以及升高软件的复杂度,晋升整个零碎的高可用能力等,这些方方面面绝大部分都聚焦在利用的非功能性个性下面。 1.焦虑的本源所有的这些焦虑,咱们能够从利用的角度去深度剖析是什么起因造成的。 大家晓得对于利用而言,外围的就是架构,包含了利用的业务架构和技术架构。从利用架构下来看,须要满足客户的利用倒退诉求。比如说数据的产生,随着明天 IoT 一直遍及,数据会产生十分大的接入量,对于这些数据的解决也带来了更高的要求。 基于传统的、更多的服务于人的申请的响应式数据处理形式曾经不能满足于业务的需要,对于 IoT 设施更多的是基于申请、响应这类事件的模型和形式。同样的,企业的业务倒退须要跟更多的公司去进行生态的连贯。这些大量的业务诉求也对底层的技术架构带来了比拟多的要求。这些要求就体现在,要求底层的技术架构可能反对高度的冗余,能反对微服务和海量的业务并发、以及可能反对动静伸缩、可能提供 SLA 等。 如果咱们再进一步深度挖掘,这外面到底是须要解决什么样的外围矛盾时,咱们能够发现其实外围矛盾在于随着上云、业务的复杂度一直减少,使得 IT 有更多的治理老本。而这个老本就体现在,所有的微服务、高可用都须要用高度的零碎冗余去解决。同时因为业务的疾速倒退,须要整个 IT 零碎去响应频繁的变换。外围矛盾就在于,零碎的高度冗余与零碎的频繁变动之间的矛盾,所有的分布式系统都在围绕这一主要矛盾来进行解决。 举个例子,在原来的单机时代,如果咱们只须要一个人治理一台机器,用一台机器上的软件就能够满足本身业务倒退的要求,那么咱们显然没有这么多的矛盾。只有当一个人变成几十甚至上百集体,当这样一台机器不是运行在一个节点而是几十上百甚至上千个节点时,整个 IT 须要解决的复杂度就从1对1变成了1对N的频发。所以说整体的复杂度失去了一个极大的晋升,这也是咱们所讲的矛盾的本源。 2.疾速解和深度解那么对于这样的矛盾有什么样的解法呢?明天在云的时代,咱们总结了一下有疾速的解法和须要更多资源投入的深度解法。 疾速解就包含了 re-host 的模式,即把利用的运行环境从传统的线下 IDC 迁徙到了云的环境。在这种模式下,利用的架构没有发生变化,利用的危险也是比拟低的,然而价值的回报只能说是较高。与此对应的另一个解法就是 re-platform,就是把整体利用的交付和运维都扭转,然而利用的软件架构不产生扭转。 比如说咱们通过容器的形式去扭转整个软件的留存,扭转整体的运维留存。那么在这个模式上面,它的架构变更的幅度是绝对比拟小的,施行危险是中等且能够失去比拟高的价值回报。 但如果咱们要彻底解决下面的问题,那么就要采取整个软件重构的 re-build 形式,或者对于软件的重要模块去进行一个 re-factor 重构的模式。这些模式都会波及到软件的架构发生变化,因而它的施行危险也是很高的,但同样的高投入高风险也带来了高回报,扭转后的利用能够更好地解决矛盾。 所有的解法都与云原生有着十分大的关系。云原生被提出来的最次要的起因,是企业上云之后发现很多利用不能很好地去利用云的个性,因而有人说很多利用不是云原生类型的利用。因而,云原生被提出来了。 云原生的要害外延咱们先不去探讨云原生的定义是什么,但咱们要专门提出对于云原生的三个要害外延,了解这三个外延对于咱们怎么样去利用云原生构建现代化利用有十分大的帮忙。 ...

July 13, 2021 · 1 min · jiezi

关于设计模式:数字化转型的路上手握一张地图但路还得自己走

简介:本文作者来自于中国人寿保险股份有限公司研发核心,对企业数字化转型、云原生实际有比拟资深的教训。以下内容整顿自作者对最新出版的《阿里云云原生架构实际》的读后感。作者|肖晟 本文作者来自于中国人寿保险股份有限公司研发核心,对企业数字化转型、云原生实际有比拟资深的教训。以下内容整顿自作者对最新出版的《阿里云云原生架构实际》的读后感。 初心 作为金融行业的 IT 从业者,参加着传统企业数字化转型过程,咱们始终在思考两个问题:一是什么是数字化,为什么要数字化?二是如何推动数字化转型,门路、工具、组织等方面该如何布局调整? 大家经常会混同信息化与数字化的概念,认为上线了一些业务零碎或是投放了一些数字大盘,就实现了 IT 建设指标。但实际上这可能只是扭转了一些信息数据向领导层流转的模式,整个业务的工作模式并没有什么变动;原来须要人工操作的仍然须要人工操作,该走的流程还得接着走(甚至新建的零碎还新增了一些流程),效率没有显著变动;企业的业绩是否有晋升,若有晋升那与 IT 建设是否正相干,性价比是否划算等等,这些往往也不足无效的评估形式,很容易陷入伪数字化的坑。 “ 任何架构都必须服务于企业策略,云原生架构也不例外! 企业必须分明业务策略与云 IT 策略之间的关系,即云IT策略只是对业务策略进行必要的技术撑持,还是云 IT 策略自身也是业务策略的一部分。 ” 十分同意《阿里云云原生架构实际》一书中提到的观点,技术终归是服务于企业价值的。因而,咱们认为,数字化是基于信息化的能力改良业务模式,聚合全价值链上的各个环节和数据,把着力点放在领导业务经营和决策上;最终表现形式,就是“全量全因素数据+自动化+实时化”的智能状态。 “ 数字化业务对技术架构的次要诉求是保障业务连续性、业务疾速上线、业务老本管制,以及科技赋能业务翻新。 ” 为了让业务开发团队可能更快更稳的进行高质量交付,以满足越来越快的业务需要,“小前端、大中台/大后端”是必选之路。因为只有让前端更轻,业务开发团队能力更聚焦业务,交付也能力更麻利;而中台和后端做重一点,高质量的设计与标准都积淀其中,其中的最佳实际复用度也就更高。 核心思想能够用一个词概括——“下沉”。 当咱们把公共技术能力与办法下沉到开发框架、下沉到根底平台、下沉到自动化的标准流程中,基于这些能力构建的利用就能够很麻利了,且生来就处于一个高质量的架构体系中(正所谓赢在起跑线上),而云原生架构是这种能力下沉落地的最佳实际方法论。 登程 “ 云原生架构是基于云原生技术的一组架构准则和设计模式的汇合,旨在帮忙企业和开发人员充分利用云平台所提供的平台化能力和弹性资源能力。 云原生包含云原生技术、云原生产品、云原生架构以及构建现代化利用的开发理念。 ” 现代化利用和云原生利用是基于云原生的架构和开发理念构建或实现的,如服务化准则、弹性准则等 7 大架构准则,计算存储拆散模式、事件驱动模式等 10 种架构模式,以及 DevOps、GitOps 等研发理念。 云原生架构和云原生开发理念是基于云原生技术和产品构建或实现的,包含容器技术、DevOps 技术、微服务、Service Mesh、Serverless、云原生大数据、云原生AI、云原生平安等十余项技术和产品。其中,凋谢利用模型(Open Application Model,OAM)的概念让人耳目一新,将 PaaS 中对资源的标准化申明拓展到对利用、配置的标准化申明,“让简略的应用程序变得更简略,让简单的应用程序更易于治理”。 最初,云原生产品和云原生技术又是须要基于私有云、公有云或混合云的云基础设施。云原生的组成,就是如此层层递进的关系。 走过的路 “ 云原生架构降级是对企业的整个IT架构的彻底降级,每个组织在进行云原生架构降级时,必须依据企业本身的状况因地制宜,其中,组织能力和技术栈处于等同重要的位置。 ” 在数字化转型的路线上,传统企业的历史包袱着实不小,在不能停业务的状况下进行架构革新无异于给航行中的飞机换发动机、换操作流程,乃至换机组人员。 笔者来自于中国人寿保险股份有限公司,亲身经历过一个服务化技术升级的案例,是不得已的状况下,云原生技术给了咱们新的答案。 IT 建设初期,烟囱式零碎林立;随着零碎越来越多,零碎间交互需要越来越大,服务化需要被提上议程,十多年前,以总线型架构为代表 SOA 理念风靡,各零碎纷纷对接服务总线。但随着挪动互联网的衰亡,服务压力逐年倍增,总线型架构的瓶颈逐渐浮现了进去,总线的一个抖动很容易造成各类服务的阻塞,微服务架构的引入更加剧了这种景象。 ...

July 9, 2021 · 1 min · jiezi

关于设计模式:08结构型模式适配器模式

1 现实生活中的适配器例子泰国插座用的是两孔的(欧标),能够买个多功能转换插头 (适配器) ,这样就能够应用了。 2 根本介绍适配器模式(Adapter Pattern)将某个类的接口转换成客户端冀望的另一个接口示意,主的目标是兼容性,让本来因接口不匹配不能一起工作的两个类能够协同工作。其别名为包装器(Wrapper)适配器模式属于结构型模式次要分为三类:类适配器模式、对象适配器模式、接口适配器模式3 工作原理适配器模式:将一个类的接口转换成另一种接口。让本来接口不兼容的类能够兼容。从用户的角度看不到被适配者,是解耦的。用户调用适配器转化进去的指标接口办法,适配器再调用被适配者的相干接口办法。用户收到反馈后果,感觉只是和指标接口交互,如图:4 类适配器模式4.1 类适配器模式介绍根本介绍:Adapter 类,通过继承 src 类,实现 dst 类接口,实现 src->dst 的适配。 4.2 类适配器模式利用实例利用实例阐明以生存中充电器的例子来解说适配器,充电器自身相当于 Adapter,220V 交流电相当于 src (即被适配者),咱们的目 dst(即 指标)是 5V 直流电思路剖析(类图)代码实现:被适配者: public class Voltage220V { //输入 220V 的电压 public int output220V() { int src = 220; System.out.println("电压=" + src + "伏"); return src; }}适配接口: public interface IVoltage5V { int output5V();}类适配器,实现适配接口: //适配器类public class VoltageAdapter extends Voltage220V implements IVoltage5V { @Override public int output5V() { //获取到 220V 电压 int srcV = output220V(); //适配逻辑:转成 5v int dstV = srcV / 44; return dstV; }}public class Phone { //充电 public void charging(IVoltage5V iVoltage5V) { if (iVoltage5V.output5V() == 5) { System.out.println("电压为 5V, 能够充电~~"); } else if (iVoltage5V.output5V() > 5) { System.out.println("电压大于 5V, 不能充电~~"); } }}public class Client { public static void main(String[] args) { System.out.println(" === 类适配器模式 ===="); Phone phone = new Phone(); phone.charging(new VoltageAdapter()); }}4.3 类适配器模式注意事项和细节Java 是单继承机制,所以类适配器须要继承 src 类这一点算是一个毛病, 因为这要求 dst 必须是接口,有肯定局限性。这样适配器类和被适配器类耦合度变大。src 类的办法在 Adapter 中都会裸露进去,也减少了应用的老本。因为其继承了 src 类,所以它能够依据需要重写 src 类的办法,使得 Adapter 的灵活性加强了。5 对象适配器模式5.1 对象适配器模式介绍基本思路和类的适配器模式雷同,只是将 Adapter 类作批改,不是继承 src 类,而是持有 src 类的实例,以解决兼容性的问题。 即:持有 src 类,实现 dst 类接口,实现 src->dst 的适配依据“合成复用准则”,在零碎中尽量应用关联关系(聚合)来代替继承关系。对象适配器模式是适配器模式罕用的一种。5.2 对象适配器模式利用实例利用实例阐明以生存中充电器的例子来解说适配器,充电器自身相当于 Adapter,220V 交流电相当于 src (即被适配者),咱们的目 dst(即指标)是 5V 直流电,应用对象适配器模式实现。思路剖析(类图):只需批改适配器即可, 如下:代码实现这里适配器有继承变成了聚合关系://类适配器,实现适配接口。适配器类public class VoltageAdapter implements IVoltage5V { // 公有属性,体现出关联关系——聚合 private Voltage220V voltage220V; public VoltageAdapter() { } // 结构器设置属性 public VoltageAdapter(Voltage220V voltage220V) { this.voltage220V = voltage220V; } // set 办法设置属性 public void setVoltage220V(Voltage220V voltage220V) { this.voltage220V = voltage220V; } @Override public int output5V() { // 获取到 220V 电压 int srcV = voltage220V.output220V(); // 适配逻辑:转成 5v int dstV = srcV / 44; return dstV; }}public class Client { public static void main(String[] args) { // 结构适配器类 VoltageAdapter adapter = new VoltageAdapter(new Voltage220V()); System.out.println(" === 类适配器模式 ===="); Phone phone = new Phone(); phone.charging(adapter); }}5.3 对象适配器模式注意事项和细节对象适配器和类适配器其实算是同一种思维,只不过实现形式不同。依据合成复用准则,应用组合代替继承, 所以它解决了类适配器必须继承 src 的局限性问题,也不再要求 dst必须是接口。应用老本更低,更灵便。6 接口适配器模式6.1 接口适配器模式介绍一些书籍称为:适配器模式(Default Adapter Pattern)或缺省适配器模式。外围思路:当不须要全副实现接口提供的办法时,可先设计一个抽象类实现接口,并为该接口中每个办法提供一个默认实现(空办法),那么该抽象类的子类可有选择地笼罩父类的某些办法来实现需求实用于一个接口不想应用其所有的办法的状况。6.2 接口适配器模式利用实例案例阐明 ...

July 6, 2021 · 2 min · jiezi

关于设计模式:07创建型模式建造者模式

1 盖房我的项目需要须要建房子:这一过程为打桩、砌墙、封顶。房子有各种各样的,比方一般房,高楼,别墅,各种房子的过程尽管一样,然而要求不要雷同的。请编写程序,实现需要。2 传统形式解决盖房需要思路剖析(图解)3 传统形式的问题剖析长处是比拟好了解,简略易操作。设计的程序结构,过于简略,没有设计缓存层对象,程序的扩大和保护不好。也就是说,这种设计方案,把产品(即:房子) 和 创立产品的过程(即:建房子流程) 封装在一起,耦合性加强了。解决方案:将产品和产品建造过程解耦 => 建造者模式。4 建造者模式根本介绍建造者模式(Builder Pattern) 又叫生成器模式,是一种对象构建模式。它能够将简单对象的建造过程形象进去(形象类别),使这个形象过程的不同实现办法能够结构出不同体现(属性)的对象。建造者模式是一步一步创立一个简单的对象,它容许用户只通过指定简单对象的类型和内容就能够构建它们,用户不须要晓得外部的具体构建细节。5 建造者模式的四个角色Product(产品角色): 一个具体的产品对象。Builder(形象建造者): 创立一个 Product 对象的各个部件指定的接口/抽象类。ConcreteBuilder(具体建造者): 实现接口,构建和拆卸各个部件。Director(指挥者): 构建一个应用 Builder 接口的对象。它次要是用于创立一个简单的对象。它次要有两个作用,一是:隔离了客户与对象的生产过程,二是:负责管制产品对象的生产过程。6 建造者模式原理类图 7 建造者模式解决盖房需要利用实例须要建房子:这一过程为打桩、砌墙、封顶。不论是一般房子也好,别墅也好都须要经验这些过程,上面咱们应用建造者模式(Builder Pattern)来实现思路剖析图解(类图)代码实现:产 品 ->Product: public class House { private String basic; private String wall; private String roofed; ... get/set}形象建造者: // 形象的建造者。定义好建造的步骤,具体实现交由子类实现。public abstract class HouseBuilder { protected House house = new House(); // 将建造的流程写好, 形象的办法 public abstract void buildBasic(); public abstract void buildWalls(); public abstract void roofed(); // 建造房子好, 将产品(房子) 返回 public House buildHouse() { return house; }}指挥者,实现建房的流程: ...

July 6, 2021 · 2 min · jiezi

关于设计模式:06创建型模式原型模式

1 克隆羊问题当初有一只羊 tom,姓名为: tom, 年龄为:1,色彩为:红色,请编写程序创立和 tom 羊 属性完全相同的 10 只羊。 2 传统形式解决克隆羊问题public class Client { public static void main(String[] args) { //传统的办法。间接反复创立屡次。 Sheep sheep = new Sheep("tom", 1, "红色"); Sheep sheep2 = new Sheep(sheep.getName(), sheep.getAge(), sheep.getColor()); Sheep sheep3 = new Sheep(sheep.getName(), sheep.getAge(), sheep.getColor()); Sheep sheep4 = new Sheep(sheep.getName(), sheep.getAge(), sheep.getColor()); Sheep sheep5 = new Sheep(sheep.getName(), sheep.getAge(), sheep.getColor()); System.out.println(sheep); System.out.println(sheep2); System.out.println(sheep3); System.out.println(sheep4); System.out.println(sheep5); }}class Sheep { private String name; private int age; private String color; public Sheep(String name, int age, String color) { this.name = name; this.age = age; this.color = color; } ... 此处省略get/set/toString 办法。}3 传统的形式的优缺点长处是比拟好了解,简略易操作。在创立新的对象时,总是须要从新获取原始对象的属性,如果创立的对象比较复杂时,效率较低总是须要从新初始化对象,而不是动静地取得对象运行时的状态, 不够灵便改良的思路剖析思路:Java 中 Object 类是所有类的根类,Object 类提供了一个 clone()办法,该办法能够将一个 Java 对象复制一份,然而须要实现 clone 的 Java 类必须要实现一个接口 Cloneable,该接口示意该类可能复制且具备复制的能力 =>原型模式。4 原型模式-根本介绍原型模式(Prototype 模式)是指:用原型实例指定创建对象的品种,并且通过拷贝这些原型,创立新的对象原型模式是一种创立型设计模式,容许一个对象再创立另外一个可定制的对象,无需晓得如何创立的细节工作原理是:通过将一个原型对象传给那个要动员创立的对象,这个要动员创立的对象通过申请原型对象拷贝它们本人来施行创立,即:对象.clone()形象的了解:孙大圣插入猴毛, 变出其它孙大圣。5 原型模式原理结构图-uml 类图 ...

July 6, 2021 · 3 min · jiezi

关于设计模式:05创建型模式工厂模式

1 简略工厂模式1.1 看一个具体的需要看一个披萨的我的项目:要便于披萨品种的扩大,要便于保护 披萨的品种很多(比方 GreekPizz、CheesePizz 等)。披萨的制作有 prepare,bake, cut, box。实现披萨店订购性能。1.2 应用传统的形式来实现思路剖析(类图)编写 OrderPizza.java 去订购须要的各种 Pizza// 当新增一个 Pizza 品种时,须要批改 OrderPizza。当很多类用 OrderPizza 时,会面临很多批改。public class OrderPizza { public static void main(String[] args) { new OrderPizza(); } // 结构器 public OrderPizza() { Pizza pizza = null; String orderType; // 订购披萨的类型 do { orderType = getType(); if (orderType.equals("greek")) { pizza = new GreekPizza(); pizza.setName(" 希腊披萨 "); } else if (orderType.equals("cheese")) { pizza = new CheesePizza(); pizza.setName(" 奶酪披萨 "); } else { break; } //输入 pizza 制作过程 pizza.prepare(); pizza.bake(); pizza.cut(); pizza.box(); } while (true); } // 获取客户心愿订购的pizza 品种 private String getType() { try { BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); System.out.println("input pizza type: "); return in.readLine(); } catch (Exception e) { e.printStackTrace(); return ""; } }}public abstract class Pizza { protected String name; // 筹备原材料,不同 Pizza 不一样。因而定义为形象办法 public abstract void prepare(); public void bake() { System.out.println(name + " baking;"); } public void cut() { System.out.println(name + " cuting;"); } public void box() { System.out.println(name + " boxing;"); } public void setName(String name) { this.name = name; }}public class CheesePizza extends Pizza{ @Override public void prepare() { System.out.println("制作奶酪披萨,筹备原材料"); }}public class GreekPizza extends Pizza { @Override public void prepare() { System.out.println("制作希腊披萨,筹备原材料"); }}1.3 传统的形式的优缺点长处是比拟好了解,简略易操作。毛病是违反了设计模式的 ocp 准则,即对扩大凋谢,对批改敞开。即当咱们给类减少新性能的时候,尽量不批改代码,或者尽可能少批改代码.比方咱们这时要新减少一个 Pizza 的品种(Pepper 披萨),咱们须要做如下批改. 如果咱们减少一个 Pizza 类,只有是订购 Pizza 的代码都须要批改。1.4 改良的思路剖析剖析:批改代码能够承受,然而如果咱们在其它的中央也有创立 Pizza 的代码,就意味着,也须要批改,而创立 Pizza的代码,往往有多处。 ...

July 6, 2021 · 5 min · jiezi

关于设计模式:04创建型模式单例模式

1 单例设计模式介绍所谓类的单例设计模式,就是采取肯定的办法保障在整个的软件系统中,对某个类只能存在一个对象实例, 并且该类只提供一个获得其对象实例的办法(静态方法)。 比方 Hibernate 的 SessionFactory,它充当数据存储源的代理,并负责创立 Session 对象。SessionFactory 并不是轻量级的,个别状况下,一个我的项目通常只须要一个 SessionFactory 就够,这是就会应用到单例模式。 1.1 单例设计模式八种形式单例模式有八种形式:1. 饿汉式(动态常量)2. 饿汉式(动态代码块)3. 懒汉式(线程不平安)4. 懒汉式(线程平安,同步办法)5. 懒汉式(线程平安,同步代码块)6. 双重查看7. 动态外部类8. 枚举2 饿汉式(动态常量)饿汉式(动态常量)利用实例步骤如下: 结构器私有化 (避免 new )类的外部创建对象向外裸露一个动态的公共办法。getInstance代码实现: public class SingletonTest01 { public static void main(String[] args) { //测试 Singleton instance = Singleton.getInstance(); Singleton instance2 = Singleton.getInstance(); System.out.println(instance == instance2); // true System.out.println("instance.hashCode=" + instance.hashCode()); System.out.println("instance2.hashCode=" + instance2.hashCode()); }}//饿汉式(动态变量)class Singleton { //1. 结构器私有化,内部能 new private Singleton() { } //2.本类外部创建对象实例 private final static Singleton instance = new Singleton(); //3. 提供一个私有的静态方法,返回实例对象 public static Singleton getInstance() { return instance; }}2.1 优缺点阐明:长处: ...

July 6, 2021 · 3 min · jiezi

关于设计模式:03设计模式之UML类图

1 UML 根本介绍UML——Unified modeling language UML (对立建模语言),是一种用于软件系统剖析和设计的语言工具,它用于帮忙软件开发人员进行思考和记录思路的后果。UML 自身是一套符号的规定,就像数学符号和化学符号一样,这些符号用于形容软件模型中的各个元素和他们之间的关系,比方类、接口、实现、泛化、依赖、组合、聚合等。 2 UML 图画 UML 图与写文章差不多,都是把本人的思维形容给他人看,关键在于思路和条理,UML 图分类: 用例图(use case)。动态结构图:类图、对象图、包图、组件图、部署图。动静行为图:交互图(时序图与合作图)、状态图、流动图。阐明: 类图是形容类与类之间的关系的,是 UML 图中最外围的。在解说设计模式时,咱们必然会应用类图。3 UML 类图用于形容零碎中的类(对象)自身的组成和类(对象)之间的各种动态关系。类之间的关系:依赖、泛化(继承)、实现、关联、聚合与组合。类图简略举例public class Person{ //代码模式->类图 private Integer id; private String name; public void setName(String name){ this.name=name; } public String getName(){ return name; }} 4 类图—依赖关系(Dependence)只有是在类中用到了对方,那么他们之间就存在依赖关系。如果没有对方,连编绎都通过不了。 public class PersonServiceBean { private PersonDao personDao;//类 public void save(Person person){} public IDCard getIDCard(Integer personid){} public void modify(){ Department department = new Department(); }}public class PersonDao{} public class IDCard{}public class Person{} public class Department{}1) 类中用到了对方;2) 如果是类的成员属性;3) 如果是办法的返回类型;4) 是办法接管的参数类型;5) 办法中应用到。 ...

July 6, 2021 · 1 min · jiezi

关于设计模式:02设计模式七大原则介绍

1 设计模式七大准则设计模式准则,其实就是程序员在编程时,该当恪守的准则,也是各种设计模式的根底(即:设计模式为什么这样设计的根据) 设计模式罕用的七大准则有: 繁多职责准则接口隔离准则依赖倒转(倒置)准则里氏替换准则开闭准则(OCP)迪米特法令合成复用准则2 繁多职责准则繁多职责准则(Single Responsibility Principle) 2.1 根本介绍对类来说的,即一个类应该只负责一项职责。如类 A 负责两个不同职责:职责 1,职责 2。当职责 1 需要变更而扭转 A 时,可能造成职责 2 执行谬误,所以须要将类 A 的粒度合成为 A1,A2。 2.2 利用实例以交通工具案例解说。 public class SingleResponsibility { public static void main(String[] args) { Vehicle vehicle = new Vehicle(); vehicle.run("摩托车"); vehicle.run("汽车"); vehicle.run("飞机"); }}/** * 交通工具类 * 1. 在此形式 的 run 办法中,违反了繁多职责准则 * 2. 解决的计划十分的简略,依据交通工具运行办法不同,分解成不同类即可 */class Vehicle { public void run(String vehicle) { System.out.println(vehicle + " 在公路上运行...."); }}解决办法1: /** * 计划 1 的剖析 * 1. 恪守繁多职责准则 * 2. 然而这样做的改变很大,行将类合成,同时批改客户端 * 3. 改良:间接批改 Vehicle 类,改变的代码会比拟少=>计划 2 */public class SingleResponsibility { public static void main(String[] args) { RoadVehicle roadVehicle = new RoadVehicle(); roadVehicle.run("摩托车"); roadVehicle.run("汽车"); AirVehicle airVehicle = new AirVehicle(); airVehicle.run("飞机"); }}class RoadVehicle { public void run(String vehicle) { System.out.println(vehicle + "公路运行"); }}class AirVehicle { public void run(String vehicle) { System.out.println(vehicle + "天空运行"); }}class WaterVehicle { public void run(String vehicle) { System.out.println(vehicle + "水中运行"); }}解决办法2: ...

July 5, 2021 · 10 min · jiezi

关于设计模式:01设计模式简介

1 设计模式简略介绍1.1 经典面试题在理论开发过程中,咱们可能会用到设计模式;在追踪我的项目源码时,咱们也可能会遇到框架源码会用到设计模式;在面试中也可能会被问到设计模式的问题。比方以下问题有请应用 UML 类图画出原型模式外围角色原型设计模式的深拷贝和浅拷贝是什么,并写出深拷贝的两种形式的源码(重写 clone 办法实现深拷贝、应用序列化来实现深拷贝)在 Spring 框架中哪里应用到原型模式,并对源码进行剖析 beans.xml<bean id="id01" class="com.spring.bean.Monster" scope="prototype"/>Spring 中原型 bean 的创立,就是原型模式的利用代码剖析+Debug 源码1.2 设计模式七大准则设计模式常见的七大准则:1. 繁多职责准则2. 接口隔离准则3. 依赖倒转准则4. 里氏替换准则5. 开闭准则OCP6. 迪米特法令7. 合成复用准则要想深刻了解设计模式的七大准则,要求把握:1)七大设计准则核心思想;2)可能以类图的阐明设计准则;3)在我的项目理论开发中,可能晓得哪里可能体现这些法令。 1.3 几个设计模式的背景1.3.1 状态模式金融借贷平台我的项目:金融借贷平台的订单,有审核、公布、抢单等等步骤,随着操作的不同,会扭转订单的状态。改订单模块其实就能够应用状态模式,也是咱们理论工作中会常面临的表状态问题。 问题剖析:这类代码难以应答变动,在增加一种状态时,咱们须要手动增加if/else,在增加一种性能是也须要对所有的状态进行判断。因而会面临diamante越来越臃肿,难以保护,一旦某个状态解决不正确就会呈现bug。 1.3.2 解释器模式介绍解释器设计模式是什么?画出解释器设计模式的 UML 类图,剖析设计模式中的各个角色是什么?请阐明 Spring 的框架中,哪里应用到了解释器设计模式,并做源码级别的剖析Spring 框架中 SpelExpressionParser 就应用到解释器模式代码剖析+Debug 源码+模式角色剖析阐明1.3.3 单例设计模式单例模式一共有几种实现形式?请别离用代码实现,并阐明各个实现形式的长处和毛病? 单例设计模式一共有 8 种写法:饿汉式两种、懒汉式三种、双重查看、动态外部类、枚举。 2 设计模式重要性软件工程中,设计模式(design pattern)是对软件设计中普遍存在(重复呈现)的各种问题,所提出的解决方案。这个术语是由埃里希·伽玛(Erich Gamma)等人在 1990 年代从建筑设计畛域引入到计算机科学的拿理论工作经验来说, 当一个我的项目开发完后,如果客户提出增新性能,怎么办?。(可扩展性,应用设计模式,软件具备很好的扩展性)如果我的项目开发完后,原来程序员到职,你接手保护该我的项目怎么办? (维护性[可读性、规范性])目前程序员门槛越来越高,一线 IT 公司(大厂),都会问你在理论我的项目中应用过什么设计模式,怎么应用的,解决了什么问题。设计模式在软件中哪里?面向对象(oo)=>功能模块[设计模式+算法(数据结构)]=>框架[应用到多种设计模式]=> 架构 [服务器集群]。如果想成为合格软件工程师,那就花工夫来钻研下设计模式是十分必要的。如何解说设计模式:采纳利用场景->设计模式->分析原理->剖析实现步骤(图解)->代码实现-> 框架或我的项目源码剖析(找到应用的中央) 的步骤解说 3 设计模式目标编写软件过程中,程序员面临着来自耦合性,内聚性以及可维护性,可扩展性,重用性,灵活性 等多方面的挑战,设计模式是为了让程序(软件),具备更好:1) 代码重用性 (即:雷同性能的代码,不必屡次编写)2) 可读性 (即:编程规范性, 便于其余程序员的浏览和了解) 3) 可扩展性 (即:当须要减少新的性能时,十分的不便,称为可保护)4) 可靠性 (即:当咱们减少新的性能后,对原来的性能没有影响)5) 使程序出现高内聚,低耦合的个性 分享金句: ...

July 5, 2021 · 1 min · jiezi

关于设计模式:设计模式抽象工厂模式

工程目录 DaoFactory.go package AbstractFactory//记录接口type OrderMainDao interface { SaveOrderMain() //SearchOrderMain()}//详情接口type OrderDetailDao interface { SaveOrderDetail()}//形象工厂接口type DaoFactory interface { CreateOrderMainDao() OrderMainDao CreateOrderDetailDao() OrderDetailDao}MYSQLDetailDaoFactory.go package AbstractFactoryimport "fmt"type MYSQLMainDao struct {}func (*MYSQLMainDao) SaveOrderMain() { fmt.Println("MYSQL main save")}type MYSQLDetailDao struct {}func (*MYSQLDetailDao) SaveOrderDetail() { fmt.Println("MYSQL detail save")}MYSQLFactory.go package AbstractFactory//形象工厂type MYSQLFactory struct {}func (*MYSQLFactory) CreateOrderMainDao() OrderMainDao { return &MYSQLMainDao{}}func (*MYSQLFactory) CreateOrderDetailDao() OrderDetailDao { return &MYSQLDetailDao{}}OracleFactory.go package AbstractFactory//形象工厂type OracleFactory struct {}func (*OracleFactory) CreateOrderMainDao() OrderMainDao { return &OracleMainDao{}}func (*OracleFactory) CreateOrderDetailDao() OrderDetailDao { return &OracleDetailDao{}}OracleDetailDaoFactory.go ...

July 2, 2021 · 1 min · jiezi

关于设计模式:设计模式工厂模式

工程目录 OperatorFactory.go package Factory//理论运行类的接口type Operator interface { SetLeft(int) SetRight(int) Result() int}//工厂接口type OperatorFactory interface { Create() Operator}OperatorData.go package Factory//数据type OperatorData struct { left, right int}//赋值func (op *OperatorData) SetLeft(left int) { op.left = left}func (op *OperatorData) SetRight(right int) { op.right = right}PlusOpertaorFactory.go package Factory//操作的形象type PlusOpertaorFactory struct {}//操作类中蕴含操作数type PlusOpertaor struct { *OperatorData}//理论运行办法func(o PlusOpertaor) Result() int { return o.right + o.left}func(PlusOpertaorFactory) Create() Operator { return &PlusOpertaor{&OperatorData{}}}SubOpertaorFactory.go package Factory//操作的形象type SubOpertaorFactory struct {}//操作类中蕴含操作数type SubOpertaor struct { *OperatorData}//理论运行办法func(o SubOpertaor) Result() int { return o.left - o.right}func(SubOpertaorFactory) Create() Operator { return &SubOpertaor{&OperatorData{}}}factory_test.go ...

July 2, 2021 · 1 min · jiezi

关于设计模式:设计模式简单工厂模式

工程目录 factory.go package Factoryimport "fmt"type Factory interface { Generate()}type Phone struct {}type Computer struct {}func (p *Phone) Generate(){ fmt.Println("生产了一部手机")}func (c *Computer) Generate() { fmt.Println("生产了一台电脑")}func NewFactory (name string) Factory { switch name { case "phone": return &Phone{} case "computer": return &Computer{} } return nil}factory_test.go package Factoryimport "testing"func TestNewFactory(t *testing.T) { NewFactory("phone").Generate() NewFactory("computer").Generate()}

July 2, 2021 · 1 min · jiezi

关于设计模式:带你认识4种设计模式代理模式装饰模式外观模式和享元模式

摘要:本文咱们次要介绍结构型模式中的代理模式、装璜模式、外观模式和享元模式。本文分享自华为云社区《快来,这里有23种设计模式的Go语言实现(三)》,原文作者:元闰子 。 设计模式(Design Pattern)是一套被重复应用、少数人通晓的、通过分类编目标、代码设计教训的总结,应用设计模式是为了可重用代码、让代码更容易被别人了解并且保障代码可靠性。本文将介绍几种结构型模式:代理模式、装璜模式、外观模式和享元模式。 代理模式(Proxy Pattern) 简介代理模式为一个对象提供一种代理以管制对该对象的拜访,它是一个使用率十分高的设计模式,即便在现实生活中,也是很常见,比方演唱会门票黄牛。假如你须要看一场演唱会,然而官网上门票曾经售罄,于是就当天到现场通过黄牛高价买了一张。在这个例子中,黄牛就相当于演唱会门票的代理,在正式渠道无奈购买门票的状况下,你通过代理实现了该指标。 从演唱会门票的例子咱们也能够看出,应用代理模式的关键在于当Client不不便间接拜访一个对象时,提供一个代理对象管制该对象的拜访。Client实际上拜访的是代理对象,代理对象会将Client的申请转给本体对象去解决。 在程序设计中,代理模式也分为好几种: 1、近程代理(remote proxy),近程代理实用于提供服务的对象处在近程的机器上,通过一般的函数调用无奈应用服务,须要通过近程代理来实现。因为并不能间接拜访本体对象,所有近程代理对象通常不会间接持有本体对象的援用,而是持有远端机器的地址,通过网络协议去拜访本体对象。 2、虚构代理(virtual proxy),在程序设计中经常会有一些重量级的服务对象,如果始终持有该对象实例会十分耗费系统资源,这时能够通过虚构代理来对该对象进行提早初始化。 3、爱护代理(protection proxy),爱护代理用于管制对本体对象的拜访,罕用于须要给Client的拜访加上权限验证的场景。 4、缓存代理(cache proxy),缓存代理次要在Client与本体对象之间加上一层缓存,用于减速本体对象的拜访,常见于连贯数据库的场景。 5、智能援用(smart reference),智能援用为本体对象的拜访提供了额定的动作,常见的实现为C++中的智能指针,为对象的拜访提供了计数性能,当拜访对象的计数为0时销毁该对象。 这几种代理都是一样的实现原理,上面咱们将介绍近程代理的Go语言实现。 Go实现思考要将音讯解决零碎输入到数据存储到一个数据库中,数据库的接口如下: package db...// Key-Value数据库接口type KvDb interface { // 存储数据 // 其中reply为操作后果,存储胜利为true,否则为false // 当连贯数据库失败时返回error,胜利则返回nil Save(record Record, reply *bool) error // 依据key获取value,其中value通过函数参数中指针类型返回 // 当连贯数据库失败时返回error,胜利则返回nil Get(key string, value *string) error}type Record struct { Key string Value string}数据库是一个Key-Value数据库,应用map存储数据,上面为数据库的服务端实现,db.Server实现了db.KvDb接口: package db...// 数据库服务端实现type Server struct { // 采纳map存储key-value数据 data map[string]string}func (s *Server) Save(record Record, reply *bool) error { if s.data == nil{ s.data = make(map[string]string) } s.data[record.Key] = record.Value *reply = true return nil}func (s *Server) Get(key string, reply *string) error { val, ok := s.data[key] if !ok { *reply = "" return errors.New("Db has no key " + key) } *reply = val return nil}音讯解决零碎和数据库并不在同一台机器上,因而音讯解决零碎不能间接调用db.Server的办法进行数据存储,像这种服务提供者和服务使用者不在同一机器上的场景,应用近程代理再适宜不过了。 ...

June 29, 2021 · 6 min · jiezi

关于设计模式:深入理解23种设计模式

设计模式介绍设计模式(Design Patterns): 一套被重复应用,少数人通晓,通过分类编目,代码设计的总结应用设计模式是为了可重用代码,让代码更容易了解,保障代码可靠性我的项目中正当使用设计模式能够完满的解决很多问题,每种模式都有相应的原理与之对应,每个模式形容了一个在咱们四周一直反复产生的问题,以及该问题的外围解决方案 # 设计模式分类 总体来说,设计模式分为三大类:创立型模式(5种): 工厂办法模式形象工厂模式单例模式建造者模式原型模式结构型模式(7种): 适配器模式装璜器模式代理模式外观模式桥接模式组合模式享元模式行为型模式(11种): 策略模式模板办法模式观察者模式迭代子模式责任链模式命令模式备忘录模式状态模式访问者模式中介者模式解释器模式其余两类模式: 并发型模式线程池模式 设计模式六大准则繁多职责准则(Single Responsibility Principle) - 这里的设计模式准则,次要探讨的是Java面向对象编程设计中设计准则,繁多职责准则因为其实用的普遍性,集体认为不放在六大准则之中 繁多职责准则 :一个类只负责一项职责不能存在多于一个导致类变更的起因繁多职责准则合乎"高内聚,低耦合"的思维繁多职责准则不只是面向对象编程思维所特有的,只有是模块化的程序设计,都实用繁多职责准则开闭准则(Open Close Principle)开闭准则 :对扩大凋谢,对批改敞开程序进行扩大的时候,不能批改原有的代码, 实现一个热插拔的成果为了使程序扩展性好,易于保护和降级:须要应用接口和抽象类里氏代换准则(Liskov Substitution Principle)里氏代换准则 :任何基类能够呈现的中央,子类肯定能够呈现LSP是继承复用的基石,只有当衍生类能够替换掉基类,软件单位的性能不受影响时, 基类能力真正被复用,衍生类也可能在基类的根底上减少新的行为里氏代换准则是对实现抽象化的具体步骤的标准: 里氏代换准则是对开闭准则的补充实现开闭准则的关键步骤就是抽象化基类与子类的继承关系就是抽象化的具体实现 依赖倒转准则(Dependence Inversion Principle)依赖倒转准则 :针对接口编程,依赖于形象而不依赖于具体依赖倒转准则是开闭准则的根底 接口隔离准则(Interface Segregation Principle)接口隔离准则 :应用多个隔离的接口,比应用单个接口要好,升高类之间的耦合度从接口隔离准则能够看出:设计模式就是一个软件的设计思维从大型软件架构登程,为了降级和保护不便 :升高依赖,升高耦合 迪米特法令(起码晓得准则)(Demeter Principle)迪米特法令:起码晓得准则 ,一个实体该当尽量少的与其它实体产生相互作用,使得功能模块互相独立 合成复用准则(Composite Reuse Principle)合成复用准则 :尽量应用合成或者聚合的形式,而不是应用继承 Java中23种设计模式创立型模式工厂办法模式(Factory Method)工厂办法模式分为三种 :一般工厂模式,多个工厂办法模式,动态工厂办法模式 一般工厂模式建设一个工厂类,对实现了同一接口的一些类进行实例的创立: 接口public interface Sender{ public void Send();}实现类public class MailSender implements Sender{ @Override public void Send(){ System.out.println("MailSender Method");} }public class SmsSender implements Sender{ @Override public void Send(){ ...

June 19, 2021 · 12 min · jiezi

关于设计模式:Java中23种设计模式六大设计原则的分析与介绍

设计模式介绍设计模式(Design Patterns): 一套被重复应用,少数人通晓,通过分类编目,代码设计的总结应用设计模式是为了可重用代码,让代码更容易了解,保障代码可靠性我的项目中正当使用设计模式能够完满的解决很多问题,每种模式都有相应的原理与之对应,每个模式形容了一个在咱们四周一直反复产生的问题,以及该问题的外围解决方案 # 设计模式分类 总体来说,设计模式分为三大类:创立型模式(5种): 工厂办法模式形象工厂模式单例模式建造者模式原型模式结构型模式(7种): 适配器模式装璜器模式代理模式外观模式桥接模式组合模式享元模式行为型模式(11种): 策略模式模板办法模式观察者模式迭代子模式责任链模式命令模式备忘录模式状态模式访问者模式中介者模式解释器模式其余两类模式: 并发型模式线程池模式 设计模式六大准则繁多职责准则(Single Responsibility Principle) - 这里的设计模式准则,次要探讨的是Java面向对象编程设计中设计准则,繁多职责准则因为其实用的普遍性,集体认为不放在六大准则之中 繁多职责准则 :一个类只负责一项职责不能存在多于一个导致类变更的起因繁多职责准则合乎"高内聚,低耦合"的思维繁多职责准则不只是面向对象编程思维所特有的,只有是模块化的程序设计,都实用繁多职责准则开闭准则(Open Close Principle)开闭准则 :对扩大凋谢,对批改敞开程序进行扩大的时候,不能批改原有的代码, 实现一个热插拔的成果为了使程序扩展性好,易于保护和降级:须要应用接口和抽象类里氏代换准则(Liskov Substitution Principle)里氏代换准则 :任何基类能够呈现的中央,子类肯定能够呈现LSP是继承复用的基石,只有当衍生类能够替换掉基类,软件单位的性能不受影响时, 基类能力真正被复用,衍生类也可能在基类的根底上减少新的行为里氏代换准则是对实现抽象化的具体步骤的标准: 里氏代换准则是对开闭准则的补充实现开闭准则的关键步骤就是抽象化基类与子类的继承关系就是抽象化的具体实现 依赖倒转准则(Dependence Inversion Principle)依赖倒转准则 :针对接口编程,依赖于形象而不依赖于具体依赖倒转准则是开闭准则的根底 接口隔离准则(Interface Segregation Principle)接口隔离准则 :应用多个隔离的接口,比应用单个接口要好,升高类之间的耦合度从接口隔离准则能够看出:设计模式就是一个软件的设计思维从大型软件架构登程,为了降级和保护不便 :升高依赖,升高耦合 迪米特法令(起码晓得准则)(Demeter Principle)迪米特法令:起码晓得准则 ,一个实体该当尽量少的与其它实体产生相互作用,使得功能模块互相独立 合成复用准则(Composite Reuse Principle)合成复用准则 :尽量应用合成或者聚合的形式,而不是应用继承

June 15, 2021 · 1 min · jiezi

关于设计模式:20-设计模式责任链模式

作为一个上班族,咱们可能会常常听到“治理流程凌乱”,“职责边界不清晰”等这样或那样的埋怨,这是当组织或零碎发展壮大后,一件事由一个人或者一个部门无奈独立实现时,不得不面对的问题。就拿平时销假来说,试想如果是一个只有几个人的小公司,很可能连请假条都不必写,间接跟老板说一下就OK了,然而如果公司有肯定规模,做为一个小小的螺丝钉,就未必有资格面见老板了,这时就不得不走审批流程了。咱们都晓得,通常状况下销假须要在OA上写请假单交由各级领导审批,不同级别的领导有权审批的天数不同,例如不超过1天的销假间接领导(TL)审批就能够了,而大于1天不超过3天就须要整个我的项目的负责人(PM)审批才能够,当然工夫更长的,如7天,则可能须要交由CTO甚至更高级的领导审批。 这个例子就曾经体现出责任的划分了,咱们先用代码模仿一下这个销假场景,而后由此引出咱们这次的配角---责任链模式。 示例既然是销假,当然先得有请假单,而请假单又由申请和审批后果两局部组成,别离由销假人和审批领导填写,这不难理解,代码如下: public class LeaveContext{ /// <summary> /// 申请 /// </summary> public LeaveRequest Request { get; set; } /// <summary> /// 审批后果 /// </summary> public LeaveResponse Response { get; set; }}而后再来几个领导,每个领导都有在肯定范畴内解决申请的能力。通过后面那么多设计模式的陶冶,针对不同级别的领导形象个管理者基类不难想到吧? public abstract class Manager{ public string Name { get; set; } public Manager(string name) { Name = name; } public abstract void HandleRequest(LeaveContext context);}/// <summary>/// 团队领导者/// </summary>public class TL : Manager{ public TL(string name) : base(name) { } public override void HandleRequest(LeaveContext context) { if (context.Request.LeaveDays <= 1) { context.Response = new LeaveResponse { Approver = "TL:" + Name, IsAgreed = true }; } }}/// <summary>/// 项目经理/// </summary>public class PM : Manager{ public PM(string name) : base(name) { } public override void HandleRequest(LeaveContext context) { if (context.Request.LeaveDays > 1 && context.Request.LeaveDays <= 3) { context.Response = new LeaveResponse { Approver = "PM:" + Name, IsAgreed = true }; } }}/// <summary>/// 首席技术官/// </summary>public class CTO : Manager{ public CTO(string name) : base(name) { } public override void HandleRequest(LeaveContext context) { if (context.Request.LeaveDays > 3 && context.Request.LeaveDays <= 7) { context.Response = new LeaveResponse { Approver = "CTO:" + Name, IsAgreed = true }; } }}每个领导都能对同一个申请进行解决,然而也各司其职,只做本人能力范畴内的事,并且解决申请的角度和形式也大不相同(即代码实现上有较大的差别,这个例子过于简略,所以这点体现并不显著)。 ...

June 13, 2021 · 4 min · jiezi

关于设计模式:设计模式总结

经典的设计模式有 23 种,分成三类,别离是: 创立型: 1、单例2、工厂3、建造者4、原型 结构型: 1、适配器2、装璜器3、门面4、享元5、代理6、组合7、桥接 行为型: 1、策略2、迭代器3、模板办法4、命令5、状态6、观察者7、责任链8、访问者9、中介者10、解释器11、备忘录 但其实很多模式都是新瓶换旧瓶。例如:策略模式、状态模式、解释器模式、命令模式根本大同小异。所以不必太刻意去记住这些设计模式,很多设计模式都很相似,有时容易与其余设计模式混同。尽管有些模式很相似,但通过这些模式都能够反映其中外围的设计准则,那就是: 1、繁多职责:性能要垂直 2、迪米特准则:起码晓得,不要裸露多余的信息给外界 3、里氏替换准则:但凡父类呈现的中央都能够用子类代替 4、组合复用:应用组合形式来代替继承,实现性能复用 5、凋谢闭合:对外部扩大凋谢,对外部批改敞开 6、接口隔离:大接口拆分成若干个小接口,每个接口之间只保留客户端须要的办法 7、依赖倒置:高层和低层模块都依赖形象模块 而这 7 个设计准则,或多或少与面向对象思维无关: 1、多态2、继承3、封装

June 13, 2021 · 1 min · jiezi

关于设计模式:初学-Java-设计模式二十实战状态模式-亲身实践简单高效的时间管理番茄工作法

一、状态模式介绍1. 解决的问题次要解决在对象一个外部状态发生变化时,扭转其行为的问题。 2. 定义状态模式是一种行为设计模式,让你能在一个对象的外部状态变动时扭转其行为,使其看上去就像扭转了本身所属的类一样。 3. 利用场景如果对象须要依据本身以后状态进行不同行为,同时状态的数量十分多且与状态相干的代码会频繁变更的话,可应用状态模式。如果某个类须要依据成员变量的以后值扭转本身行为,从而须要应用大量的条件语句时,可应用状态模式。当类似状态和基于条件的状态机转换中存在许多反复代码时,可应用状态模式。二、状态模式优缺点1. 长处繁多职责准则:将与特点状态相干的代码放在独自的类中。开闭准则:无需批改已有状态类和上下文就能引入新状态。通过打消臃肿的状态机条件语句简化上下文代码。2. 毛病如果状态机只有很少的几个状态,或者很少产生扭转,那么利用该模式可能会显得小题大做。三、状态模式利用实例:简略高效的工夫治理——番茄工作法1. 实例场景不晓得大家有没有常常想认真学习,却始终晚会再说的状况,我反正就是。 最近发现了个番茄工作法,找了个软件体验了一下,听着滴答滴答的工作背景音效,还是很有种工夫在哗啦哗啦流的紧迫感,能肯定水平上进步点效率,当然可能听习惯了就不当回事了。 具体的软件如果想要的话,评论留言通知我。 番茄工作法是弗朗西斯科·西里洛在 1922 年创立的一种工夫治理办法,有助于进步工作效率,养成良好的学习习惯。 它的基本原理就是把工作工夫分为多个番茄钟,一个番茄钟由 25 分钟工作工夫和 5 分钟休息时间组成。 25 分钟的工作工夫内,要放弃专一,防止烦扰。5 分钟的休息时间倡议来到工作区域,喝一杯茶,做一些简略的舒展静止。 这样看是不是还有点护眼,让咱们这些天天对着电脑的农民工能及时想起来本人的眼睛须要劳动。 很多时候,感觉忙了一天,也不晓得本人在忙啥,也能够用番茄工作法将本人的一天记录下来,剖析一下工夫都去哪了? 明天,就以番茄工作法的工作状态到劳动状态为例,介绍一下状态模式。 2. 状态模式实现2.1 工程构造state-pattern└─ src ├─ main │ └─ java │ └─ org.design.pattern.state │ ├─ model │ │ ├─ PomodoroState.java │ │ └─ impl │ │ ├─ WorkPomodoroState.java │ │ └─ RestPomodoroState.java │ └─ service │ ├─ PomodoroService.java │ └─ impl │ └─ PomodoroServiceImpl.java └─ test └─ java └─ org.design.pattern.state.test └─ PomodoroTest.java2.2 代码实现2.2.1 实体类番茄状态接口 ...

June 11, 2021 · 2 min · jiezi

关于设计模式:单例模式DCL

铁子们有段时间没有更新了,最近忙着筹备面试,筹备过程中发现自己还须要积攒的切实是太多太多,每每学到新货色的感觉真是美好而又能源十足啊,持续蜷缩腰杆、致力后退 单例模式-DCL双重查看判断,应用volatile关键字禁止指令重排,在多线程状况下创立平安的单例对象,间接上代码 public class Instance { /** * volatile 禁止指令重排,依照代码执行程序先赋值后创建对象 */ private volatile static Instance instance; private String instName; private Instance() { instName = "DCL"; } public static Instance getInstance() { if (instance == null) { synchronized (Instance.class) { if (instance == null) { instance = new Instance(); } } } return instance; }}单例模式-外部类应用外部类结构单例对象,JVM保障单例 public class Instance { private static class InstanceObj { private static final Instance INSTANCE = new Instance(); } public static Instance getInstance() { return InstanceObj.INSTANCE; }}

June 10, 2021 · 1 min · jiezi

关于设计模式:设计模式之观察者模式

[toc]设计模式之观察者模式## 1. 再谈设计准则 1.1 可维护性(Maintainability):可扩展性;灵活性;可插拔;1.2 可复用性(Reuseability):代码复用;算法复用;数据结构复用;1.3 可维护性与可复用性的关系: 1.4 六大设计准则1. 开闭准则-OCP(open-close-Principle)软件系统的设计, 应答扩大凋谢, 对批改敞开;2. 里氏代换准则-LSP(Liskov-Substitution-Principle)所有基类呈现的中央, 都能够被子类替换;3. 依赖倒置准则-DIP(Dependence-Inversion-Principle)应该依赖于形象而非具体;4. 接口隔离准则-ISP(Interface-Segregation-Principle)多个专门的接口好于繁多的总接口;5.合成/聚合复用准则-CARP(Composite/Aggregate-Reuse-Principle)应用合成/聚合的形式复用, 而不是继承;聚合: 更强的合成;6. 迪米特法令-LoD(Law-of-Demeter)若非必要,不要裸露(起码晓得准则);2. 观察者模式2.1 始于回调(回调模式)public class App { // 主业务流程 public void doBusiness(ICallback callback){ System.out.println("主流程工作..."); callback.call(); }}public interface ICallback { void call();}// 0. 回调操作随主流程执行@Testvoid callbackTest() { App app = new App(); app.doBusiness(() -> { System.out.println("回调操作..."); });} 2.2 观察者模式-类图Subject/OneSubject: 被察看对象(发布者)Observer: 观察者(订阅者) 观察者接口(订阅者) /** * 观察者(订阅者) */public interface Observer { void update(String msg);}观察者/订阅者1(实现类) /** * 观察者/订阅者1 * @author nieweijun * @since 2021/6/1 22:09 */public class OneObserver implements Observer{ @Override public void update(String msg) { System.out.println("OneObserver收到音讯:["+msg+"]"); }}观察者实现类2 ...

June 9, 2021 · 6 min · jiezi

关于设计模式:设计模式责任链

责任链:将每个模块负责的解决流程链接起来,造成一条链子,所有申请的数据进入这条链子时,都会由链头到链尾被链子上的各个模块解决。 例如:Java EE 的 Filter(过滤链)就是责任链,所有申请都必须通过这条过滤链,每通过一个节点都会被这个节点进行解决。如果申请满足过滤条件,那么就会进入下一个过滤节点,直到达到过滤链的尾部。 因为是过滤链是链表的构造,那么也就是说如果我须要减少一个过滤条件,那么就往过滤链退出一个过滤节点;同理,要缩小一个过滤条件,那么就从链表移除即可。这样就能够轻松实现动静治理过滤规定,并且每个过滤节点层层过滤。 模式分析: 1、如果一个解决规定和流程过于宏大,那么能够将其拆分成若干个规定和流程,而后将它们串起来造成一条责任链。这样每个节点只负责一部分规定和流程,保护和改变十分敌对。同时如果不须要某个规定和流程,那么就将对应的节点移除即可。同样减少规定和流程也是如此。

June 6, 2021 · 1 min · jiezi

关于设计模式:初学-Java-设计模式十九实战观察者模式-您的快递已到达蜂站请及时签收

一、观察者模式介绍1. 解决的问题次要解决将一个对象的状态扭转告诉给其余对象的问题。 2. 定义观察者模式是一种行为设计模式,容许你定义一种订阅机制,可在对象事件产生时告诉多个 “察看” 该对象的其余对象。 3. 利用场景当一个对象的扭转须要扭转其余对象,或理论对象时是当时未知的或动态变化时,可应用观察者模式。当利用中的一些对象必须察看其余对象时,可应用观察者模式,但仅能在无限工夫内或特定状况下应用。二、观察者模式优缺点1. 长处开闭准则:无需批改发布者代码就能引入新的订阅者(如果是发布者接口,则可轻松引入发布者类)。能够在运行时建设与对象之间的分割。2. 毛病订阅者的告诉程序是随机的。三、观察者模式利用实例:您的快递已达到蜂站,请及时签收1. 实例场景当初大部分快递都不会交付到手上了,除非咱们特意选了上门服务。 个别都是买完两三天,收到条短信:您好,您的快递已到蜂站,请凭取件码K16888取件,取件工夫09:30-21:00,请及时取件。 刚看完短信,APP也跳出一则告诉:您的快递已被蜂站签收,请及时取件。 明天,就以快递达到,同时收到APP和短信告诉为例,介绍一下观察者模式。 2. 观察者模式实现2.1 工程构造observer-pattern└─ src ├─ main │ └─ java │ └─ org.design.pattern.observer │ ├─ model │ │ ├─ ExpressPackage.java │ │ ├─ Courier.java │ │ └─ User.java │ ├─ subscriber │ │ ├─ ExpressEventSubscriber.java │ │ └─ impl │ │ ├─ AppExpressEventListener.java │ │ └─ SmsExpressEventSubscriber.java │ ├─ publisher │ │ └─ ExpressEventPublisher.java │ └─ service │ ├─ ExpressService.java │ └─ impl │ └─ ExpressServiceImpl.java └─ test └─ java └─ org.design.pattern.observer.test └─ ExpressEventTest.java2.2 代码实现2.2.1 实体类快递实体类 ...

June 6, 2021 · 3 min · jiezi

关于设计模式:戏说代理模式

你看到的是我想让你看到的,你听到的是我想让你听到的! ——代理模式的自白前戏不能少前戏一:在生活中,咱们经常会见到这么一种景象:有些父母抱着”望子成龙,望女成凤“的心态,将孩子所有的事务(衣食住行,吃喝拉撒)全都包圆了,能够说事无巨细。 前戏二:在现代,男女成婚之前是不能互相见面的,他们之间的很多信息都是通过媒人互相传递的,是丑是美,是高是矮还不是靠媒人的那张嘴。 通过下面这两个前戏,大家有没有一些感觉? 这孩子废了…… 万恶的封建社会…… 咳咳!!敲黑板了,请留神:咱们明天探讨的是科学知识之代理模式,不是社会话题! 言归正传我之所以来段前戏,绝不是为了哗众取宠,我是有深意的! 咱们先来看看 代理*模式的定义: 因为某些起因须要给某对象提供一个代理以管制对该对象的拜访。这时,拜访对象不适宜或者不能间接援用指标对象,代理对象作为拜访对象和指标对象之间的中介。如果咱们把文章结尾两个例子看做代理模式,那么联合定义,咱们能够将上图中的父母和媒人当做”代理对象“。 对于代理模式 长处 代理模式在客户端与指标对象之间起到一个中介作用和爱护指标对象的作用。代理对象能够扩大指标对象的性能。代理模式能将客户端与指标对象拆散,在肯定水平上升高了零碎的耦合度,减少了程序的可扩展性。毛病 代理模式会造成零碎设计中类的数量减少。在客户端和指标对象之间减少一个代理对象,会造成申请处理速度变慢。减少了零碎的复杂度。分类 动态代理 由程序员创立代理类或特定工具主动生成源代码再对其编译,在程序运行前代理类的 .class 文件就曾经存在了。动静代理 在程序运行时,使用反射机制动态创建而成组成 形象主题(Subject)类:通过接口或抽象类申明实在主题和代理对象实现的业务办法。实在主题(Real Subject)类:实现了形象主题中的具体业务,是代理对象所代表的实在对象,是最终要援用的对象。代理(Proxy)类:提供了与实在主题雷同的接口,其外部含有对实在主题的援用,它能够拜访、管制或扩大实在主题的性能。结尾明天咱们次要是对代理模式有个比较简单的认知,后续会开展来说,感激浏览! 学习乏味的常识,结识乏味的敌人,塑造乏味的灵魂! 大家好!我是〖编程三昧〗的作者 隐逸王,我的公众号是『编程三昧』,欢送关注,心愿大家多多指教! 常识与技能并重,内力和外功兼修!

June 5, 2021 · 1 min · jiezi

关于设计模式:设计模式观察者模式

观察者(Observer)模式的定义:指多个对象间存在一对多的依赖关系,当一个对象的状态产生扭转时,所有依赖于它的对象都失去告诉并被自动更新。这种模式有时又称作公布-订阅模式、模型-视图模式,它是对象行为型模式。 观察者模式是一种对象行为型模式,其次要长处如下: 升高了指标与观察者之间的耦合关系,两者之间是形象耦合关系。合乎依赖倒置准则。指标与观察者之间建设了一套触发机制。它的次要毛病如下: 指标与观察者之间的依赖关系并没有齐全解除,而且有可能呈现循环援用。当观察者对象很多时,告诉的发布会破费很多工夫,影响程序的效率。模式的构造观察者模式的次要角色如下。 形象主题(Subject)角色:也叫形象指标类,它提供了一个用于保留观察者对象的汇集类和减少、删除观察者对象的办法,以及告诉所有观察者的形象办法。具体主题(Concrete Subject)角色:也叫具体指标类,它实现形象指标中的告诉办法,当具体主题的外部状态产生扭转时,告诉所有注册过的观察者对象。形象观察者(Observer)角色:它是一个抽象类或接口,它蕴含了一个更新本人的形象办法,当接到具体主题的更改告诉时被调用。具体观察者(Concrete Observer)角色:实现形象观察者中定义的形象办法,以便在失去指标的更改告诉时更新本身的状态。 //形象指标abstract class Subject { protected List<Observer> observers = new ArrayList<Observer>(); //减少观察者办法 public void add(Observer observer) { observers.add(observer); } //删除观察者办法 public void remove(Observer observer) { observers.remove(observer); } public abstract void notifyObserver(); //告诉观察者办法}//具体指标class ConcreteSubject extends Subject { public void notifyObserver() { System.out.println("具体指标产生扭转..."); System.out.println("--------------"); for (Object obs : observers) { ((Observer) obs).response(); } }}//形象观察者interface Observer { void response(); //反馈}//具体观察者1class ConcreteObserver2 implements Observer { public void response() { System.out.println("具体观察者2作出反应!"); }}public class ObserverPattern { public static void main(String[] args) { Subject subject = new ConcreteSubject(); Observer obs1 = new ConcreteObserver1(); Observer obs2 = new ConcreteObserver2(); subject.add(obs1); subject.add(obs2); subject.notifyObserver(); }}理论案例 ...

June 3, 2021 · 1 min · jiezi

关于设计模式:设计模式工厂方法

1.简略工厂(一个工厂生产多种种产品)2.工厂办法(对工厂形象,不同工厂实现类生产不同产品)3.形象工厂(对产品进行形象,不同工厂能够生产多种产品(同一个产品族)),相对而言,形象工厂是前两种的合体,多了一个维度.

June 2, 2021 · 1 min · jiezi

关于设计模式:设计模式策略模式

策略模式:定义一组算法,将每个算法都封装起来,并且使他们之间能够调换 简略点了解为定义公共办法,调用公共办法 public class Person { private int age; private int num; public Person(int age, int name) { this.age = age; this.num = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public int getNum() { return num; } public void setNum(int name) { this.num = name; }}//定义公共办法@FunctionalInterfacepublic interface Comparator<T> { int compareTo(T o1,T o2);}//调用时应用接口public class Sorter<T> { public void sort(T[] arr, Comparator<T> comparator) { //冒泡排序 for (int i = 0; i < arr.length - 1; i++) { int pos = i; for (int j = i + 1; j < arr.length; j++) { pos = comparator.compareTo(arr[j], arr[pos]) == -1 ? j : pos; } swap(arr, i, pos); } } void swap(T[] arr, int i, int j) { T temp = arr[i]; arr[i] = arr[j]; arr[j] = temp; }}//main办法,对于不同策略只须要实现comparator接口就行public class Main { public static void main(String[] args) { Person[] arr = {new Person(20, 3), new Person(19, 1), new Person(21, 2)}; Sorter<Person> sorter = new Sorter<>(); //按年龄排序 sorter.sort(arr, (o1, o2) -> { if (o1.getAge() > o2.getAge()) { return 1; } else if (o1.getAge() < o2.getAge()) { return -1; } else { return 0; } }); //按num排序 sorter.sort(arr, (o1, o2) -> { if (o1.getNum() > o2.getNum()) { return 1; } else if (o1.getNum() < o2.getNum()) { return -1; } else { return 0; } }); //由此可见,策略模式能够随便扩大,只有实现对应接口就行 }}

June 2, 2021 · 2 min · jiezi

关于设计模式:设计模式单例模式

//单例饿汉public class Singleton01 { private static final Singleton01 INSTANCE = new Singleton01(); private Singleton01() { } public static Singleton01 getInstance() { return INSTANCE; }}public class Singleton02 { private volatile static Singleton02 INSTANCE; //为什么要应用volatile //执行构造方法和赋值的操作可能会指令重排序,并发状况下可能有两个对象被初始化 //故应用volatile,禁止指令重排序,保障线程平安 private Singleton02() {} public static Singleton02 getInstance() { if (INSTANCE == null) { synchronized (Singleton02.class) { if (INSTANCE == null) { INSTANCE = new Singleton02(); } } } return INSTANCE; }}public class Singleton03 { private Singleton03() { } //动态外部类自带懒加载 private static class SingletonHolder { private static Singleton03 INSTANCE = new Singleton03(); } public static Singleton03 getInstance() { return SingletonHolder.INSTANCE; }}public enum Singleton04 { //枚举 INSTANCE;}

June 2, 2021 · 1 min · jiezi

关于设计模式:还没对象生产你的对象你只需要一个简单工厂

前言简略工厂在我的项目中使用的十分多,如果你使用切当,能够晋升我的项目的可浏览性。 工厂模式的定义定义一个创立产品对象的工厂接口,将产品对象的理论创立工作推延到具体子工厂类当中。这满足创立型模式中所要求的“创立与应用相拆散”的特点。 简略工厂如果要创立的产品不多,只有一个工厂类就能够实现,这种模式叫“简略工厂模式”。 简略工厂通常为静态方法,因而又叫动态工厂办法模式 长处:工厂类蕴含必要的逻辑判断,能够决定在什么时候创立哪一个产品的实例。客户端能够罢黜间接创立产品对象的职责,很不便的创立出相应的产品。工厂和产品的职责辨别明确。客户端无需晓得所创立具体产品的类名,只需晓得参数即可。也能够引入配置文件,在不批改客户端代码的状况下更换和增加新的具体产品类。 毛病:简略工厂模式的工厂类繁多,负责所有产品的创立,职责过重,一旦异样,整个零碎将受影响。且工厂类代码会十分臃肿,违反高聚合准则。应用简略工厂模式会减少零碎中类的个数(引入新的工厂类),减少零碎的复杂度和了解难度零碎扩大艰难,一旦减少新产品不得不批改工厂逻辑,在产品类型较多时,可能造成逻辑过于简单简略工厂模式应用了 static 工厂办法,造成工厂角色无奈造成基于继承的等级构造。利用场景对于产品种类绝对较少的状况,思考应用简略工厂模式。应用简略工厂模式的客户端只须要传入工厂类的参数,不须要关怀如何创建对象的逻辑,能够很不便地创立所需产品。 代码实现简略工厂模式的次要角色如下: 简略工厂:是简略工厂模式的外围,负责实现创立所有实例的外部逻辑。工厂类的创立产品类的办法能够被外界间接调用,创立所需的产品对象。形象产品:是简略工厂创立的所有对象的父类,负责形容所有实例共有的公共接口。具体产品:是简略工厂模式的创立指标。其结构图如下图所示。kotlin代码实现 interface IProduct{ fun showName() :String}class Dog : IProduct{ override fun showName() = "dog"}class Cat : IProduct{ override fun showName() = "cat"}object AnimalFactory{ fun createAnimal(type:Int):IProduct{ return when(type){ 1-> Dog() 2-> Cat() else -> throw NullPointerException() } }}简略工厂模式在Android中的理论利用 fragment 的构建有时候,为了简化简略工厂模式,咱们能够将形象产品类和工厂类合并,将动态工厂办法移至形象产品类中。Fragment的创立应用简略工厂办法没有形象产品类,所以工厂类放到了实现产品类中。 class ListWorkFragment : BMvpFragment<ListWorkView ,ListWorkPresenter>(),ListWorkView,ISubjectView{ companion object { @JvmStatic fun newInstance(recommendTypeId: Int, termCode: String = "") = ListWorkFragment().apply { arguments = Bundle().apply { putInt("type", recommendTypeId) putString("code", termCode) } } }长处 ...

May 31, 2021 · 3 min · jiezi

关于设计模式:设计模式模板方法

模板办法:定义好一个执行模板(骨架),而后将一些动静的流程和数值参数化,这样就能够依据不同的参数产生不同的后果。 例如:JDK 的 AQS(AbstractQueueSynchronizer) 就是采纳了模板办法模式。AQS 曾经定义好线程同步的流程和细节,只有五个办法是没有实现的,由子类负责具体实现,这 5 各形式如下: 这 5 个办法的作用就是束缚线程应该以什么样的形式来获取和开释 “资源”。多线程运行时,必然面临资源不够的状况,此时 AQS 的 四个办法(try 结尾)就是用于以独占还是共享的形式来获取资源。因为 AQS 不负责实现这四个办法,我就以 AQS 的一个子类 CountDownLatch 为例,如下: CountDownLatch 继承 AQS,并实现 tryAcquireShared 和 tryRealseShared 两个办法,定义了资源该如何获取,最初 AQS 就会依据 CountDownLatch 的这两个办法从而决定前面的执行流程。如下 AQS 的 doAcquireShared 办法: 模式分析: 1、将不变与变动的拆散,并将不变的模板化,变动的参数化,造成一个模板,极大地提高模板利用率的同时,还可能联合具体的参数产生不同的后果。

May 30, 2021 · 1 min · jiezi

关于设计模式:代码质量好坏如何评判

代码品质"好"和"坏"指什么?"好"能够示意代码的品质高,"坏"示意代码的品质低。 代码品质"高"又是指什么?代码品质高指代码:可维护性、可读性、可扩展性、灵活性、简洁性、可复用、可测试性。其中可维护性、可读性、可扩展性是最重要的三个指标。 可维护性可维护性是一个主观性很强的评判规范,因为相熟零碎的资深工程师可能会工作易保护,然而资格浅的工程师就会认为难保护。 所谓可维护性就是指,在不毁坏原有代码设计、不引入新的BUG的状况下,可能疾速地批改或者增加代码。所谓代码不易保护就是值,批改或者增加代码须要冒着极大的引入新bug的危险,并且须要破费很长的工夫能力实现。可读性代码的可读性从如下几个方面来进行评估。 是否合乎编码标准、命名是否达意、正文是否详尽、函数是否长短适合、模块划分是否清晰、是否合乎高内聚低耦合等。然而最简略的评估规范就是让共事来做Code Receive,如果共事可能轻松的读懂你的代码,那就是可读性很好,反之就是须要改善代码了。 可扩展性可扩展性示意,咱们在不批改或大量批改原有代码的状况下,通过扩大的形式增加新的性能代码。灵活性代码灵活性次要提当初易扩大方面。 简洁性咱们要听从KISS准则,代码要尽可能的简略;然而思从深而行从简,真正的高手能云淡风轻地用最简略的办法解决最简单的问题。这也是一个编程新手跟编程老手的本质区别之一。 可复用性可复用性是很多设计模式、思维、准则所要达到的最终成果。可测试性可测试就能从侧面上十分精确地反馈代码品质的好坏。要写出满足上述评估规范的高质量代码,咱们须要把握一些更加细化、更加能落地的编程方法论,包含面向对象设计思维、设计准则、设计模式、编码标准、重构技巧等。 如: 面向对象中的继承、多态能让咱们写出可复用的代码;编码标准能让咱们写出可读性好的代码。设计准则中的繁多职责、DRY、基于接口而非实现、里氏替换准则等能够写出易复用、灵便、可读性好、易扩大、易保护的代码;设计模式能够写出易扩大的代码。继续重构能够时刻放弃代码的可维护性。

May 24, 2021 · 1 min · jiezi

关于设计模式:代理模式

核心思想:应用代理对象来代替原始对象实现对象拜访,这样就能够在不批改原始对象代码的前提下,拓展原始对象的额定性能。 1. 动态代理动态代理实现步骤: 定义一个接口和实现类。定义一个代理类也实现该接口。将指标对象注入到代理类中,而后在代理类的办法中调用对应指标类中的办法。例子: 定义发短信的接口及其实现类 public interface SmsService { String send(String message);}public class SmsServiceImpl implements SmsService { @Override public String send(String message) { System.out.println("send message:" + message); return message; }}创立代理类 public class SmsProxy implements SmsService { private final SmsServiceImpl smsServiceImpl; public SmsProxy(SmsService smsService) { this.smsService = smsService; } @Override public String send(String message) { //调用办法之前,咱们能够增加本人的操作 System.out.println("before method send()"); smsService.send(message); //调用办法之后,咱们同样能够增加本人的操作 System.out.println("after method send()"); return null; }}测试 public class Main { public static void main(String[] args) { SmsService smsService = new SmsServiceImpl(); SmsProxy smsProxy = new SmsProxy(smsService); smsProxy.send("java"); }}// 输入// before method send()// send message:java// after method send()毛病: ...

May 24, 2021 · 2 min · jiezi

关于设计模式:单例模式

1. 饿汉式// 饿汉式public class Singleton { private static Singleton INSTANCE = new Singleton(); private Singleton() {} public static Singleton getInstance() { return INSTANCE; }}2. 懒汉式public class Singleton { private static Singleton INSTANCE; private Singleton() {} public static Singleton getInstance() { if (INSTANCE == null) { INSTANCE = new Singleton(); } return INSTANCE; }}3. 线程平安懒汉式-双重查看public class Singleton { private static Singleton INSTANCE; private Singleton() {} public static Singleton getInstance() { if (INSTANCE == null) { synchronized(Singleton.class) { if (INSTANCE == null) { INSTANCE = new Singleton(); } } } return INSTANCE; }}4. 双重查看的不足之处以下三种状况会毁坏双重查看的单例模式:指令重排序、序列/反序列化、反射 ...

May 24, 2021 · 1 min · jiezi

关于设计模式:初学-Java-设计模式十八实战备忘录模式-线上刚发布就出问题怎么办

一、备忘录模式介绍1. 解决的问题次要解决在不毁坏封装性的前提下,捕捉一个对象的外部状态,并在该对象之外保留这个状态,从而能够复原原先保留的状态。 2. 定义备忘录模式是一种行为设计模式,容许在不裸露对象实现细节的状态下保留和复原对象之前的状态。 3. 利用场景当你须要创建对象状态快照来复原其之前的状态时,能够应用备忘录模式。当间接拜访对象的成员变量、获取器或设置器将导致封装被冲破时,能够应用备忘录模式。二、备忘录模式优缺点1. 长处能够在不毁坏对象封装状况的前提下创建对象状态快照。能够通过让负责人保护原发器状态历史记录来简化原发器代码。2. 毛病如果客户端过于频繁地创立备忘录,程序将耗费大量内存。负责人必须残缺跟踪原发器的生命周期,这样能力销毁弃用的备忘录。绝大部分动静编程语言(例如PHP、Python 和 JavaScript)不能确保备忘录中的状态不被批改。三、备忘录模式利用实例:线上刚公布就出问题怎么办?1. 实例场景搬砖的咱们常常会遇到这个状况: 老代码出了 bug ,先看文档手册,我去,这代码连个文档都没有,只能看源码了。 看完一遍逻辑,再调试个半天,应该是这里出问题了,疾速批改结束,验证一遍,nice,没什么问题。 开始分割测试验证,测试环境验证通过! 激动人心的时刻来了:提交代码合并申请 -> 编译 -> 公布。 哎,怎么回事,线上公布的容器疯狂报错,起都起不来,我的天,怎么办? 旁边的共事:别慌,先把公布回滚吧,保障线上没问题! 明天,咱们就以公布回滚为例,介绍一下备忘录模式。 2. 备忘录模式实现2.1 工程构造└─ src ├─ main │ └─ java │ └─ org.design.pattern.memento │ └─ model │ ├─ ReleaseRecord.java │ ├─ ReleaseRecordOriginator.java │ ├─ ReleaseRecordMemento.java │ └─ ReleaseRecordCaretaker.javaa └─ test └─ java └─ org.design.pattern.memento └─ MementoTest.java2.2 代码实现2.2.1 实体类公布记录 /** * 公布记录 */@Getter@Setter@AllArgsConstructorpublic class ReleaseRecord { /** * 公布记录号 */ private Integer id; /** * 公布版本 */ private String version; /** * 公布容器 */ private String cloudName; /** * 开发 */ private String developerName; /** * 测试 */ private String testerName;}2.2.2 备忘录模式相干类公布记录原生器 ...

May 23, 2021 · 2 min · jiezi

关于设计模式:设计模式命令

命令模式:将须要执行的流程封装成一个工作(命令),而后提交给执行器(命令执行者)执行。 例如:JDK 线程池里的 Execultor 就是采纳了命令模式,Executor 是命令执行者,Runnable 是命令,Executor 里的 execute 办法传入的参数就是 Runnable,如下: Runnable 负责定义工作的流程,Execultor 负责执行工作命令。 模式分析: 1、命令模式和策略模式,我感觉齐全能够作为一种模式。根本就是新瓶换旧酒。同样都是就解决流程集中并封装到一个对象里(策略和工作),而后由执行器负责执行。 2、将执行动作和各种解决流程拆散,便于问题定位和保护。

May 23, 2021 · 1 min · jiezi

关于设计模式:组合模式

组合模式组合模式属于结构型模式,组合多个对象造成树形构造以示意具备局部-整体关系的层次结构。组合模式让零碎能够对立看待单个对象和组合对象。 组合模式关注那些蕴含叶子构件和容器构件的构造以及它们的组织模式,在叶子构件中不蕴含成员对象,而容器构件中能够蕴含成员对象,这些对象通过递归组合可形成一个树形构造。 组合模式的构造 Component(形象构建):接口或抽象类,为叶子构件和容器构件提供接口,能够蕴含所有子类共有行为的申明。在形象构件中申明了拜访以及治理它的子构件的办法。Leaf(叶子构件):叶子节点对象,叶子节点不存在子节点,它只实现了形象构件中定义的行为。对于其它办法能够采取抛出错误信息来解决。Composite(容器构件):容器节点对象,容器节点蕴含子节点,子节点能够是叶子节点也能够是容器节点。它提供一个汇合用来存储子节点,实现了形象构件中申明的所有办法。组合模式的实现组合模式的实现关键点在于定义了一个既能够示意叶子构件又能够示意容器构件的形象层,通过对形象层进行编程,毋庸晓得对象具体是什么构件,能够对立进行解决。其次容器对象与形象构件之间是聚合关联关系,在容器对象中既能够蕴含叶子又能够蕴含容器,以此实现递归组合,造成树形构造。 组合模式设计代码如下 //形象层abstract class Component{ public abstract void Add(Component c); public abstract void Remove(Component c); public abstract Component GetChild(int i); public abstract void Operation();}//叶子节点class Leaf : Component{ //实现这些叶子节点不须要的办法减少实现复杂度 public override void Add(Component c) { //...异样解决或谬误提醒 } public override Component GetChild(int i) { //...异样解决或谬误提醒 return null; } public override void Remove(Component c) { //...异样解决或谬误提醒 } public override void Operation() { //具体业务办法的实现 Console.WriteLine("叶子节点具体业务办法的实现"); }}//容器节点class Composite : Component{ private List<Component> m_Childs = new List<Component>(); public override void Add(Component c) { this.m_Childs.Add(c); } public override Component GetChild(int i) { return this.m_Childs[i]; } public override void Remove(Component c) { this.m_Childs.Remove(c); } public override void Operation() { foreach (var item in this.m_Childs) item.Operation(); }}示例场景应用组合模式设计一个界面控件库,界面控件分为两类,单元控件和容器空间,单元空间包含文本、按钮等,容器空间包含窗体、面板等。 ...

May 18, 2021 · 2 min · jiezi