Skip to content

Translated Abstract document to Chinese #2313

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 42 additions & 49 deletions abstract-document/README.md
Original file line number Diff line number Diff line change
@@ -1,41 +1,35 @@
---
title: Abstract Document
category: Structural
language: en
tag:
- Extensibility
---

## Intent

Use dynamic properties and achieve flexibility of untyped languages while keeping type-safety.
---

## Explanation
## 意图

The Abstract Document pattern enables handling additional, non-static properties. This pattern
uses concept of traits to enable type safety and separate properties of different classes into
set of interfaces.
使用动态属性并实现无类型语言的灵活性,同时保持类型安全。

Real world example
## 解释

> Consider a car that consists of multiple parts. However we don't know if the specific car really has all the parts, or just some of them. Our cars are dynamic and extremely flexible.
抽象文档模式可以处理额外的非静态属性。这种模式
使用特征的概念来实现类型安全并将不同类的属性分离到
一组接口。

In plain words
现实世界的例子
> 考虑一辆由多个零件组成的汽车。但是,我们不知道具体的汽车是否真的拥有所有零件,或者只是其中的一部分。我们的汽车充满活力且极其灵活。

> Abstract Document pattern allows attaching properties to objects without them knowing about it.
简单来说

Wikipedia says
> 抽象文档模式允许在对象不知道的情况下将属性附加到对象。

> An object-oriented structural design pattern for organizing objects in loosely typed key-value stores and exposing
the data using typed views. The purpose of the pattern is to achieve a high degree of flexibility between components
in a strongly typed language where new properties can be added to the object-tree on the fly, without losing the
support of type-safety. The pattern makes use of traits to separate different properties of a class into different
interfaces.
维基百科说

**Programmatic Example**
> 一种面向对象的结构设计模式,用于在松散类型的键值存储中组织对象并公开
使用类型化视图的数据。模式的目的是实现组件之间的高度灵活性
在强类型语言中,可以动态地将新属性添加到对象树中,而不会丢失
支持类型安全。该模式利用特征将一个类的不同属性分成不同的
接口
**程序示例**

Let's first define the base classes `Document` and `AbstractDocument`. They basically make the object hold a property
map and any amount of child objects.
让我们首先定义基类 `Document` `AbstractDocument`。他们基本上使对象拥有一个属性
地图和任意数量的子对象。

```java
public interface Document {
Expand Down Expand Up @@ -80,8 +74,8 @@ public abstract class AbstractDocument implements Document {
...
}
```
Next we define an enum `Property` and a set of interfaces for type, price, model and parts. This allows us to create
static looking interface to our `Car` class.
接下来我们定义一个枚举“Property”和一组用于类型、价格、型号和零件的接口。这允许我们创建
我们的“汽车”类的静态界面。

```java
public enum Property {
Expand Down Expand Up @@ -117,7 +111,7 @@ public interface HasParts extends Document {
}
```

Now we are ready to introduce the `Car`.
现在我们准备介绍“汽车”。

```java
public class Car extends AbstractDocument implements HasModel, HasPrice, HasParts {
Expand All @@ -128,8 +122,7 @@ public class Car extends AbstractDocument implements HasModel, HasPrice, HasPart
}
```

And finally here's how we construct and use the `Car` in a full example.

最后,这是我们如何在完整示例中构建和使用“汽车”的方式。
```java
LOGGER.info("Constructing parts and car");

Expand Down Expand Up @@ -160,29 +153,29 @@ And finally here's how we construct and use the `Car` in a full example.
p.getPrice().orElse(null))
);

// Constructing parts and car
// Here is our car:
// model: 300SL
// price: 10000
// parts:
// wheel/15C/100
// door/Lambo/300
// 构建零件和汽车
// 这是我们的车:
// 型号:300SL
// 价格:10000
// 部分:
// 轮子/15C/100
// 门/兰博/300
```

## Class diagram
##类图

![alt text](./etc/abstract-document.png "Abstract Document Traits and Domain")
![alt text](./etc/abstract-document.png "抽象文档特征和域")

## Applicability
## 适用性

Use the Abstract Document Pattern when
在以下情况下使用抽象文档模式

* There is a need to add new properties on the fly
* You want a flexible way to organize domain in tree like structure
* You want more loosely coupled system
* 需要动态添加新属性
*您想要一种灵活的方式来组织树状结构中的域
* 你想要更松耦合的系统

## Credits
## 学分

* [Wikipedia: Abstract Document Pattern](https://en.wikipedia.org/wiki/Abstract_Document_Pattern)
* [Martin Fowler: Dealing with properties](http://martinfowler.com/apsupp/properties.pdf)
* [Pattern-Oriented Software Architecture Volume 4: A Pattern Language for Distributed Computing (v. 4)](https://www.amazon.com/gp/product/0470059028/ref=as_li_qf_asin_il_tl?ie=UTF8&tag=javadesignpat-20&creative=9325&linkCode=as2&creativeASIN=0470059028&linkId=e3aacaea7017258acf184f9f3283b492)
* [维基百科:抽象文档模式](https://en.wikipedia.org/wiki/Abstract_Document_Pattern)
* [Martin Fowler:处理属性](http://martinfowler.com/apsupp/properties.pdf)
* [面向模式的软件架构第 4 卷:分布式计算的模式语言 (v. 4)](https://www.amazon.com/gp/product/0470059028/ref=as_li_qf_asin_il_tl?ie=UTF8&tag=javadesignpat-20&creative =9325&linkCode=as2&creativeASIN=0470059028&linkId=e3aacaea7017258acf184f9f3283b492)
65 changes: 63 additions & 2 deletions typeobjectpattern/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,69 @@ As explained in the book Game Programming Patterns by Robert Nystrom, type objec
> Allowing flexible creation of new “classes” by creating a single class, each instance of which represents a different type of object

## Explanation
Say, we are working on a game which has a hero and many monsters which are going to attack the hero. These monsters have certain attributes like attack, points etc. and come in different 'breeds' like zombie or ogres. The obvious answer is to have a base Monster class which has some fields and methods, which may be overriden by subclasses like the Zombie or Ogre class. But as we continue to build the game, there may be more and more breeds of monsters added and certain attributes may need to be changed in the existing monsters too. The OOP solution of inheriting from the base class would not be an efficient method in this case.
Using the type-object pattern, instead of creating many classes inheriting from a base class, we have 1 class with a field which represents the 'type' of object. This makes the code cleaner and object instantiation also becomes as easy as parsing a json file with the object properties.

Real-world example

>Say, we are working on a game which has a hero and many monsters which are going to attack the hero. These monsters have certain attributes like attack, points etc. and come in different 'breeds' like zombie or ogres. The obvious answer is to have a base Monster class which has some fields and methods, which may be overriden by subclasses like the Zombie or Ogre class. But as we continue to build the game, there may be more and more breeds of monsters added and certain attributes may need to be changed in the existing monsters too. The OOP solution of inheriting from the base class would not be an efficient method in this case.
>Using the type-object pattern, instead of creating many classes inheriting from a base class, we have 1 class with a field which represents the 'type' of object. This makes the code cleaner and object instantiation also becomes as easy as parsing a json file with the object properties.

In plain words

>This pattern is useful anytime you need to define a variety of different “kinds” of things, but baking the kinds into your language’s type system is too rigid. In particular, it’s useful when either of these is true:

**Programmatic Example**

With that game design in mind, we fire up our text editor and start coding. According to the design, a `dragon` is a kind of `monster`, a troll is another kind, and so on with the other breeds. Thinking object-oriented, that leads us to a `Monster` base class:

```java

class Monster
{
public:
virtual ~Monster() {}
virtual const char* getAttack() = 0;

protected:
Monster(int startingHealth)
: health_(startingHealth)
{}

private:
int health_; // Current health.
};
```
The public getAttack() function lets the combat code get the string that should be displayed when the monster attacks the hero. Each derived breed class will override this to provide a different message.

The constructor is protected and takes the starting health for the monster. We’ll have derived classes for each breed that provide their own public constructors that call this one, passing in the starting health that is appropriate for that breed.

Now let’s see a couple of breed subclasses:

```java
class Dragon : public Monster
{
public:
Dragon() : Monster(230) {}

virtual const char* getAttack()
{
return "The dragon breathes fire!";
}
};

class Troll : public Monster
{
public:
Troll() : Monster(48) {}

virtual const char* getAttack()
{
return "The troll clubs you!";
}
};

```



## Class diagram
![alt text](./etc/typeobjectpattern.urm.png "Type-Object pattern class diagram")
Expand Down