美文网首页微服务架构和实践
六边形架构入门与实践

六边形架构入门与实践

作者: 核子飞弹 | 来源:发表于2018-06-05 14:26 被阅读16次

    说明

    六边形架构又称“端口和适配器模式”,是Alistair Cockburn提出的一种具有对称性特征的架构风格。在这种架构中,系统通过适配器的方式与外部交互,将应用服务于领域服务封装在系统内部。

    • 架构图

      每一种外部系统都有一个适配器与之对应,外界通过应用层API与内部交互

    六边形架构还是一种分层架构,如上图所示,它被分为了三层:端口适配器、应用层与领域层。而端口又可以分为输入端口输出端口

    • 输入端口
      用于系统提供服务时暴露API接口,接受外部客户系统的输入,并客户系统的输入转化为程序内部所能理解的输入。系统作为服务提供者是对外的接入层可以看成是输入端口。

    • 输出端口
      为系统获取外部服务提供支持,如获取持久化状态、对结果进行持久化,或者发布领域状态的变更通知(如领域事件)。系统作为服务的消费者获取服务是对外的接口(数据库、缓存、消息队列、RPC调用)等都可以看成是输入端口。

    • 应用层
      定义系统可以完成的工作,很薄的一层。它并不处理业务逻辑通过协调领域对象或领域服务完成业务逻辑,并通过输入端口输出结果。也可以在这一层进行事物管理。

    • 领域层
      负责表示业务概念、规则与状态,属于业务的核心。

    应用层与领域层的不变性可以保证核心领域不受外部的干扰,而端口的可替换性可以很方便的对接不用的外部系统。

    • 序列图

      业务处理过程

    源码演示

    通过一个简单客户信息管理(增删改查)来演示以上叙述中的一些概念。这里使用spring-web实现REST API,通过内存HashMap实现领域对象存储与检索。

    • 新建Customer领域模型

    public class Customer {
    
        private String id;
    
        private String firstName;
    
        private String lastName;
    
        protected Customer() {
    
        }
    
        public Customer(String id, String firstName, String lastName) {
            this.id = id;
            this.firstName = firstName;
            this.lastName = lastName;
        }
    
        public String getId() {
            return id;
        }
    
        public String getFirstName() {
            return firstName;
        }
    
        public String getLastName() {
            return lastName;
        }
    
        public void changeFirstName(String firstName) {
            this.firstName = firstName;
        }
    
    }
    
    • 定义仓储接口

    public interface CustomerRepository {
    
        Customer get(String id);
    
        void add(Customer customer);
    
        void update(Customer customer);
    
        Collection<Customer> all();
    
    }
    
    • 实现应用层服务

    @Component
    public class CustomerApplication {
    
        private CustomerRepository repository;
    
        @Autowired
        public CustomerApplication(CustomerRepository repository) {
            this.repository = repository;
        }
    
        public void create(CreateCustomerCommand command) {
            Customer customer = new Customer(UUID.randomUUID().toString(),
                    command.getFirstName());
            repository.add(customer);
        }
    
        public Object fetch(String id) {
            return repository.get(id);
        }
    
        public void changeFirstName(String id, String firstName) {
            Customer customer = repository.get(id);
            assert customer != null;
            customer.changeFirstName(firstName);
            repository.update(customer);
        }
    
        public Collection<?> all() {
            return repository.all();
        }
    
    }
    
    • 实现输入接口

    @RestController
    public class CustomerController {
    
        private CustomerApplication application;
    
        @Autowired
        public CustomerController(CustomerApplication application) {
            this.application = application;
        }
    
        @PostMapping("/customer")
        public ResponseEntity<Object> create(@RequestParam String firstName) {
            application.create(new CreateCustomerCommand(firstName));
            return ResponseEntity.ok(null);
        }
    
        @GetMapping("/customer/{id}")
        public ResponseEntity<Object> get(@PathVariable("id") String id) {
            return ResponseEntity.ok(application.fetch(id));
        }
    
        @PatchMapping("/customer/{id}")
        public ResponseEntity<Object> changeFirstName(@PathVariable("id") String id,
                                                      @RequestParam String firstName) {
            application.changeFirstName(id, firstName);
            return ResponseEntity.ok(null);
        }
    
        @GetMapping("/customers")
        public ResponseEntity<Object> all() {
            return ResponseEntity.ok(application.all());
        }
    
    }
    
    • 实现仓储接口

    @Component
    public class InMemoryCustomerRepository implements CustomerRepository {
    
        Map<String, Customer> customerMap = new ConcurrentHashMap<>();
    
        @Override
        public Customer get(String id) {
            return customerMap.get(id);
        }
    
        @Override
        public void add(Customer customer) {
            customerMap.put(customer.getId(), customer);
        }
    
        @Override
        public void update(Customer customer) {
            customerMap.put(customer.getId(), customer);
        }
    
        @Override
        public Collection<Customer> all() {
            return Collections.unmodifiableCollection(customerMap.values());
        }
    
    }
    

    源码下载

    https://github.com/hziee514/Hexagonal-Architecture-Sample

    参考资料

    《实现领域驱动设计》

    相关文章

      网友评论

        本文标题:六边形架构入门与实践

        本文链接:https://www.haomeiwen.com/subject/lsmpsftx.html