说明
框架开发
讲师:李智慧
对扩展是开发,对现有修改是关闭。
使用多态,使用抽象。策略模式,适配器模式,观察者模式。
高层不依赖低层,低层也不依赖高层。高层定义抽象接口,低层实现高层定义的接口。
比如 Tomcat,Spring,JUnit,我们不需要调用框架的代码。我们基于框架提供的接口来编程。 架构师要有开发框架的能力和思维,这才能区别于普通的工程师。
正常的调用顺序
依赖倒置以后
所有的父类,都可以替换为子类。 子类比父类更严格,子类方法约束开放性要比父类大。比如父类是 protected 修饰,子类只能是 protected 或者 public。
不是为继承而设计的类,那么就不要继承该类。
一个类只有一个引起其变化的原因。
如果一个类会有多个原因引起变化,则要分为多个类。
隐藏用户不需要的接口,以免被误操作。
反应式编程框架 Flower 设计
程序是如何运行又是如何崩溃的
方法调用都是同步的,很快就会把线程池里面的线程给消费完了,导致排队阻塞。
Flower 可以显著提升系统性能
异步处理,通过消息来通信。
Flower 反应式重构前后性能对比
Flower 可以显著提升系统性能 架构图
Flower 实现异步的基础是 Akka 的 Actor
Sender 到 Actor 的通信是异步的,通过消息 Message 进行通信。
5 分钟上手 Flower 反应式编程
Akka 编程实例(Java)
public class Hello extends UntypedActor {
@Override
public void onReceive(Object message) {
System.out.println("Hello, world!");
}
}
复制代码
调用
ActorRef hello = ...
hello.tell("Hi!");
复制代码
1 开发异步服务 Service
public class ServiceA implements Service<String, String> {
public String process(String message, ServiceContext context) {
return ((String) message).trim();
}
return "";
}
复制代码
2. 编排 Service 流程 serviceA -> serviceB -> serviceC
ServiceFlow.getOrCreate(flowName, servcieFactory).buildFlow(ServiceA.class, ServiceB.class).buildFlow(ServiceB.class, ServiceC.class);
复制代码
3. 调用异步服务
flowerFactory.getServiceFacade().asyncCallService(flowName, "Hello World!");
复制代码
Flower 可视化流程编排
// -> Service1 -> Service2 -> Service5 -> Service4
// ^ | ^ |
// | -> Service3 -| |
// |____________________________________________|
Service1 -> Service2
Service1 -> Service3
Service2 -> Service5
Service3 -> Service5
Service5 -> Service4
Service4 -> Service1
复制代码
兼容 Spring 的 Flower Web 开发
@RestController
@RequestMapping("/order/")
@Flower(value = "createOrderFlow", flowNumber = 32)
public class CreateOrderController extends FlowerController {
@RequestMapping(value = "createOrder")
public void createOrder(OrderExt orderDTO, HttpServletRequest req) throws IOException {
doProcess(orderDTO, req);
}
}
复制代码
protected void doProcess(Object param, HttpServletRequest req) throws IOExeption {
AsyncContext context = null;
if (req != null) {
context = req.startAsync();
}
flowRouter.asyncCallService(param, context);
}
复制代码
Flower 异步数据库访问
@FlowerService
public class UserService implements Service<User, CompletableFuture<Serializable>> {
@Autowired
private UserDao userDao;
@override
public CompletableFuture<Serializable> process(User message, ServiceContext context) throws Throwable {
System.out.println("handle user message: " + message);
return userDao.insert(message);
}
}
复制代码
Flower 核心模块
publci class ServiceActor extends UntypedActor {
Service service;
Set<ActorRef> nextServiceActors;
public ServiceActor(String serviceName) throws Exception {
this.service = ServiceFactory.getService(serviceName);
nextServiceActors = new HashSet<ActorRef>();
Set<String> nextServiceNames = ServiceFlow.getNextFlow(serviceName);
if (nextServiceNames != null && !nextServiceNames.isEmpty()) {
for (String str : nextServiceNames) {
nextServiceActors.add(ServiceActorFactory.buildServiceActor(str));
}
}
}
@Override
public void onReceive(Object arg0) throws Throwable {
Object 0 = service.process(arg0);
if (nextServiceActors != null && !nextServiceActors.isEmpty()) {
for (ActorRef actor : nextServiceActors) {
actor.tell(o, getSelf());
}
}
}
}
复制代码
package com.ly.train.flower.common.actor;
public class ServiceFacade {
public static void callService(String serviceName, Object o) throws Exception {
ServiceActorFactory.buildServiceActor(serviceName).tell(o, null);
}
}
public class ServiceActorFactory {
final static ActorSystem system = ActorSystem.create("LocalFlower");
private static FiniteDuration duration = Duration.create(3, SECONDS);
public static Map<String, ActorRef> map = new HashMap<String, ActorRef>();
public static ActorRef buildServiceActor(String serviceName) throws Exception {
ActorRef actor = map.get(serviceName);
if (actor != null) {
return actor;
}
actor = system.actorOf(Props,create(ServiceActor.class, serviceName));
return actor;
}
}
复制代码
Flower 的分布式异步微服务解决方案
为什么选择 Flower
Flower 与 WebFlux、RxJava 的比较优势
更好的性能与更低的成本
更高的可用性
开源地址:
https://github.com/zhihuili/flower
面向对象的设计模式
设计模式的作用
设计模式的定义
什么是设计模式?
一个设计模式的四个部分:
模式的名称 - 由少量的字组成的名称,有助于我们表达我们的设计。
待解问题 - 描述了何时需要运用这种模式,以及运用模式的环境(上下文)。
解决方案 - 描述了组成设计的元素(类和对象)、它们的关系、职责以及合作。但这种解决方案是抽象的,它不代表具体的实现。
结论 - 运用这种方案所带来的利和弊。主要是指它对系统的弹性、扩展性和可移植性的影响。
设计模式的分类
从功能分
☞ 对类的实例化过程的抽象。
☞ 将类或对象结合在一起形成更大的结构。
☞ 对在不同的对象之间划分责任和算法的抽象化。
从方式分
☞ 以继承的方式实现模式,静态的。
☞ 以组合的方式实现模式,动态的。
排序问题 -- 如何创建一个对象?
利用 简单工厂
简单工厂及 Client 程序
public class SorterFactory {
public static <T> Sorter<T> getSorter() {
return new BubbleSorter<T>();
}
}
public class Client {
public static void main() {
Integer[] array = { 5, 4, 9, 7, 6, 3, 8, 1, 0, 2};
Sorter<Integer> sorter = SorterFactory.getSorter();
Sortable<Integer> sortable = SortableFactory.getSortable(array);
Comparator<Integer> comparator = ComparatorFactory.getComparator();
sorter.sort(sortable, comparator);
......
}
}
复制代码
简单工厂的优缺点
优点:
缺点:
对简单工厂的改进一
class SorterFactory_2 {
@SuppressWarnings("unchecked")
public static <T> Sorter<T> getSorter (String implClass) {
try {
Class impl = Class.forName(implClass);
return (Sorter<T>) impl.newInstance();
} catch (Exception e) {
throw new IllegalArgumentException("Illegal class name:" + implClass, e);
}
}
}
Sorter<Integer> sorter = SorterFactory_2.getSorter("demo.sort.impl.BubbleSorter");
复制代码
改进一所存在的问题
解决了 Factory 的 OCP 问题吗?
其它问题
☞ Client 和 Factory 均类型不安全。
对简单工厂的改进二
class SorterFactory_3 {
private final static Properties IMPLS = loadImpls();
private static Properties loadImpls() {
Properties defaultImpls = new Properties();
Properties impls = new Properties(defaultImpls);
defaultImpls.setProperty("sorter", "demo.sort.impl.BubbleSorter");
try {
impls.load(SorterFactory_3.class.getResourceAsStream("sort.properties"));
} catch ( IOException e) {
throw new RuntimeException(e);
}
return impls;
}
@SuppressWarning("unchecked")
public static <T> Sorter<T> getSorter() {
String implClassName = IMPLS.getProperty("sorter");
try {
Class implClass = Class.forName(implClassName);
return (Sorter<T>) implClass.newInstance();
} catch (Exception e) {
throw new IllegalArgumentException("Illegal class name: " + implClassName, e);
}
}
}
复制代码
创建 sort.proproties
文件
sorter=demo.sort.impl.BubbleSorter
复制代码
改进二的优缺点
优点
☞ 对 Client 和 Factory 均满足
☞ 满足 OCP 方法
☞ 抽象
☞ 动态编程(即将编译时类型检查转变成运行时检查)
缺点
☞ 假如需要传递参数?
简单工厂改进做法其实相当重要
简单工厂非常重要,是许多其它模式的基础
而该机制解决了简单工厂模式最致命的问题
Singleton 单例模式
问什么要试用 Singleton
Singleton 模式保证产生单一实例,就是说一个类只产生一个实例。试用 Singleton 有两个原因
前者是性能需求,后者是功能需求。
饿汉式 Singleton
public class HungrySingleton {
private static HungrySingleton instance = new HungrySingleton();
private HungrySingleton() {
}
public static HungrySingleton getInstance() {
return instance;
}
}
复制代码
注意:一定要有私有的构造函数,保证实例只能通过getInstance()
方法获得。
尽量使用饿汉式构造单实例。单例中的成员变量是多线程重用的,可能会产生意想不到的结果,因此尽量将单例设计为无状态对象(只提供服务,不保存状态)。
饿汉式 Singleton 的问题是,应用一启动就加载对象进内存,就算从来未被用过。
懒汉式 Singleton
publci class LazySingleton {
private static LazySingleton instance = null;
private LazySingleton() {
}
public static synchronized LazySingleton getInstance() {
if (instance == null) {
instance = new LazySingleton();
}
return instance;
}
}
复制代码
注意: getInstance()
的修饰符 synchronized
一定要加上,否则可能会产生多重实例。
懒汉式 Singleton 解决了饿汉式 Singleton,当调用的时候才去加载对象到内存。但是引发了另外一个性能问题,每次访问对象都要加锁。
提升性能的 懒汉式 Singleton
publci class LazySingleton {
private static LazySingleton instance = null;
private LazySingleton() {
}
public static LazySingleton getInstance() {
if (instance == null) {
instance = LazySingleton.buildInstance();
}
return instance;
}
private static synchronized LazySingleton buildInstance() {
if (instance == null) {
instance = new LazySingleton();
}
return instance;
}
}
复制代码
只有当对象为null
的时候,才去加锁创建对象。
适配器模式
适配器的作用:
系统需要使用现有的类,而这个类的接口与我们所需要的不同。
类的适配器
由于原 Sortable
接口和 ArrayList
不兼容,只好定义一个 NewSortable
public class Sortable<T> extends ArrayList<T> implements NewSortable<T> {
public T getElement(int i) {
return get(i);
}
public void setElement(int i, T o) {
set(i, o);
}
}
public interface NewSortalbe<T> {
int size();
T getElement(int i);
void setElement(int i, T o);
}
复制代码
对象适配器
public class ListSortable<T> implements Sortable<T> {
private final List<T> list;
public ListSortable(List<T> list) {
this.list = list;
}
public int size() {
return list.size();
}
public T get(int i) {
return list.get(i);
}
public void set(int i, T o) {
list.set(i, o);
}
}
复制代码
适配器的应用
JDBC Driver
是对具体数据库的适配器
例如,将 Oracle 适配到 JDBC 中
JDBC-ODBC Bridge
注意:以上信息如有侵权,请联系作者删除,谢谢。
评论