问题

设计模式描写的太局部,怎么用oo思维从头开发程序?

回答
好的,我们来聊聊如何用面向对象的思维,从头构建一个程序,而不是仅仅套用设计模式。设计模式固然重要,但它们更多的是“如何解决特定问题”,而面向对象思维则更像是“如何思考和组织整个世界”。

很多时候,我们学习设计模式,像是学做一道菜的某个技巧,比如如何炒出嫩滑的鸡蛋。但如果我们连怎么洗菜、怎么切菜、怎么放调料、怎么控制火候都不知道,那这道菜也做不好。面向对象思维,就是那个“从头开始准备食材、烹饪全过程”的指导思想。

首先,我们得放下“模式”的念头,回归到最本真的问题:我们要解决什么?

想象一下,我们要开发一个简单的“图书馆管理系统”。这个系统要做什么?

管理图书(添加、删除、查找、借出、归还)
管理读者(添加、删除、查找、记录借阅信息)
处理借阅和归还的流程

第一步:观察现实世界,识别“事物”和“行为”。

这是面向对象思维的核心。别急着想什么“工厂模式”、“单例模式”,先看看我们正在管理的东西,它们是什么?

1. 图书 (Book):
它有什么属性?书名、作者、ISBN号、状态(是否被借出)。
它能做什么?被借出、被归还。

2. 读者 (Reader):
他有什么属性?姓名、读者ID、借阅列表(他借了哪些书)。
他能做什么?借书、还书。

3. 图书馆 (Library):
它有什么属性?它拥有所有的图书、它拥有所有的读者。
它能做什么?添加图书、删除图书、查找图书、添加读者、删除读者、查找读者、处理借阅请求、处理归还请求。

你看,我们自然而然地就识别出了几个关键的“事物”——图书、读者、图书馆。这三个事物,在面向对象的世界里,就对应着三个类 (Class)。

第二步:定义“类”的属性和行为(方法)。

现在,我们把刚才识别出来的属性和行为,翻译成类的定义:

`Book` 类:
属性 (Fields/Properties): `title` (String), `author` (String), `isbn` (String), `isBorrowed` (boolean, 默认为 false)。
行为 (Methods):
`borrow()`: 将 `isBorrowed` 设为 `true`。
`returnBook()`: 将 `isBorrowed` 设为 `false`。
`displayInfo()`: 显示图书的详细信息。

`Reader` 类:
属性: `name` (String), `readerId` (String), `borrowedBooks` (List, 初始为空列表)。
行为:
`borrowBook(Book book)`: 将一本图书添加到 `borrowedBooks` 列表。
`returnBook(Book book)`: 从 `borrowedBooks` 列表中移除一本图书。
`displayInfo()`: 显示读者的详细信息,包括他借阅的书。

`Library` 类:
属性: `books` (Map, 用 ISBN 作为 Key,方便查找), `readers` (Map, 用 ReaderId 作为 Key)。
行为:
`addBook(Book book)`: 将图书添加到 `books` 集合。
`removeBook(String isbn)`: 从 `books` 集合中移除图书。
`findBookByIsbn(String isbn)`: 在 `books` 集合中查找图书。
`addReader(Reader reader)`: 将读者添加到 `readers` 集合。
`removeReader(String readerId)`: 从 `readers` 集合中移除读者。
`findReaderById(String readerId)`: 在 `readers` 集合中查找读者。
`processBorrow(String readerId, String isbn)`:
找到读者 (`reader`) 和图书 (`book`)。
检查图书是否已被借出 (`book.isBorrowed`)。
如果未借出,则让图书被借出 (`book.borrow()`),让读者记录借阅 (`reader.borrowBook(book)`)。
返回操作结果(成功或失败)。
`processReturn(String readerId, String isbn)`:
找到读者 (`reader`) 和图书 (`book`)。
检查图书是否被该读者借阅(可以放在Reader类里检查)。
如果被借阅,则让图书归还 (`book.returnBook()`),让读者移除借阅记录 (`reader.returnBook(book)`)。
返回操作结果。

第三步:思考对象间的“交互”和“关系”。

我们已经定义了各个“事物”是什么,以及它们能做什么。现在要考虑的是,它们之间如何协同工作。

“一个图书馆包含很多图书和很多读者” — 这是一种组合 (Composition) 或聚合 (Aggregation) 的关系。`Library` 对象“拥有” `Book` 和 `Reader` 对象。我们用集合(如 Map 或 List)来表示这种包含关系。
“一个读者可以借阅多本图书” — 这是`Reader`对象和`Book`对象之间的关联 (Association)。`Reader`对象内部维护一个`List`。
“借阅和归还” — 这是`Reader`和`Book`之间发生的行为,但这个“过程”的协调者是`Library`。`Library`对象调用`Book`对象的`borrow()`/`returnBook()`方法,并调用`Reader`对象的`borrowBook()`/`returnBook()`方法。

关键点:关注“行为”的责任划分。

谁负责改变图书的状态(是否被借出)? 是`Book`对象自己。
谁负责记录读者借了什么书? 是`Reader`对象自己。
谁负责判断一次借阅是否合法(图书是否被借出,读者是否存在)? 是`Library`对象,因为它是整个系统的“管理者”。

在 OO 思维中,我们优先考虑:

封装 (Encapsulation): 每个对象都包裹好自己的数据(属性)和操作这些数据的方法。外部代码不需要关心`Book`对象内部是如何存储`isBorrowed`状态的,只需要调用`borrow()`或`returnBook()`方法。
继承 (Inheritance): 虽然在这个简单的例子里用不上,但如果将来我们有不同类型的图书(比如电子书、纸质书)或者不同类型的读者(普通读者、VIP读者),我们就可以用继承来共享通用属性和行为。
多态 (Polymorphism): 同样,在这个例子里不是非常明显。但如果`displayInfo()`方法在不同类型的`Book`(比如`EBook`, `PaperBook`)中有不同的实现,我们就可以通过多态调用 `library.displayAllBooks()`,然后系统会根据具体图书类型调用各自的`displayInfo()`。
抽象 (Abstraction): 我们将复杂的现实世界事物(图书、读者)简化为对象模型,只保留了与系统功能相关的关键属性和行为。

第五步:构建“主入口”或“应用逻辑”。

我们有了`Book`, `Reader`, `Library` 这些“零件”,还需要一个“组装工”来让它们动起来。这通常是一个主函数(`main` 方法)或者一个专门的“应用服务”类。

```java
public class LibrarySystem {
public static void main(String[] args) {
// 1. 创建图书馆对象
Library myLibrary = new Library();

// 2. 创建图书对象
Book book1 = new Book("The Lord of the Rings", "J.R.R. Tolkien", "9780618260275");
Book book2 = new Book("Pride and Prejudice", "Jane Austen", "9780141439518");

// 3. 将图书添加到图书馆
myLibrary.addBook(book1);
myLibrary.addBook(book2);

// 4. 创建读者对象
Reader reader1 = new Reader("Alice", "R001");
Reader reader2 = new Reader("Bob", "R002");

// 5. 将读者添加到图书馆
myLibrary.addReader(reader1);
myLibrary.addReader(reader2);

// 6. 进行借阅操作
System.out.println(" 尝试借阅 ");
myLibrary.processBorrow("R001", "9780618260275"); // Alice 借《指环王》
myLibrary.processBorrow("R002", "9780141439518"); // Bob 借《傲慢与偏见》
myLibrary.processBorrow("R001", "9780618260275"); // Alice 再次尝试借《指环王》 (应该失败)

// 7. 显示信息
System.out.println(" 图书馆状态 ");
myLibrary.books.values().forEach(Book::displayInfo); // 显示所有图书状态

System.out.println(" 读者状态 ");
myLibrary.readers.values().forEach(Reader::displayInfo); // 显示所有读者借阅信息

// 8. 进行归还操作
System.out.println(" 尝试归还 ");
myLibrary.processReturn("R001", "9780618260275"); // Alice 归还《指环王》
myLibrary.processReturn("R002", "9780141439518"); // Bob 归还《傲慢与偏见》
myLibrary.processReturn("R001", "9780141439518"); // Alice 尝试归还她未借的书 (应该失败)

// 9. 再次显示信息
System.out.println(" 归还后状态 ");
myLibrary.readers.values().forEach(Reader::displayInfo);
}
}
```

设计模式在哪里?

你会发现,在这个过程中,我们没有刻意去套用“哪个设计模式”。但是,如果你的系统变得更复杂,比如:

有多种方式创建图书对象,或者创建过程很复杂 > 可能会考虑工厂模式 (Factory Method, Abstract Factory)。
当你需要记录每次借阅的操作日志,并且希望灵活地添加不同的日志记录方式(数据库、文件、控制台) > 可能会想到观察者模式 (Observer) 或者策略模式 (Strategy)。
如果你要实现一个非常高效的图书查找机制,并且图书数量巨大,你可能需要一个更加优化的查找结构,而不是简单的 Map > 这时候你可能会考虑适配器模式 (Adapter) 来包装现有的查找算法,或者外观模式 (Facade) 来简化对复杂查找组件的访问。
如果一个对象的创建成本非常高,你想复用已经创建的对象 > 可能会考虑享元模式 (Flyweight)。

关键是,设计模式是解决“具体问题”的“工具”和“经验”。而面向对象思维,是“如何看待和拆解问题”的“方法论”。

总结一下用 OO 思维从头开发的过程:

1. 理解需求,聚焦“做什么”: 弄清楚系统需要完成哪些功能。
2. 识别“事物”: 从需求中提取出核心的“名词”,它们是潜在的对象或类。
3. 定义“属性”: 确定每个“事物”拥有哪些数据。
4. 定义“行为”: 确定每个“事物”能做什么操作。
5. 思考“关系”和“交互”: 对象之间如何关联,如何协同工作。
6. 划分“职责”: 明确每个对象应该负责哪些行为,保持低耦合。
7. 逐步细化: 从宏观的类设计到具体方法的实现。
8. 在遇到具体问题时,再考虑是否使用设计模式来优化或解决。

这个过程更像是“从模糊到清晰”,而不是“从模式到代码”。设计模式是锦上添花,而面向对象思维是构建整个“花园”的土壤和阳光。希望这样的解释能帮助你理解如何用 OO 的思想来“创造”程序,而不是仅仅“组装”模式。

网友意见

user avatar

为啥你会相信“用OO思维从头开发程序”是正确的?

OO编程、设计模式、各种设计原则是入门级开发者经常遇到的概念。实际上被这些内容打上了思想钢印的人总会坚持如何如何写代码是正确的。但到了实际,似乎完全不是那么回事。在真的项目中应用那些“正确的理念”,总会出现这样或那样的别扭,甚至起完全相反的效果。这时,被打上钢印的人往往会认为“不是这些理念不对,而是还没学到家。如果再获取到更多“高级”的资料,就一定可以解决问题!“

然后……一次又一次的被打脸。

这类事情OO算是影响力比较大的一个。如果你足够关心周围的事情,类似的其实还有好多:

  • Restful接口是最理想的接口形式(但实际上市面上开放接口的形式五花八门,比如微信的接口)
  • FP远胜于传统编码方式(但实际上大多数业务场景都会存在各种状态,业务逻辑的意义就是维护这些状态。因此不管是不是FP最终还是要处理状态,只是风格不太一样。)
  • NoSQL最重要替换掉SQL数据库,最终统治存储行业标准(最终支持SQL的分布式存储还是杀了回来,OLTP/OLAP的各种存储和分析工具都支持SQL的某种方言)
  • NIO对实现高并发至关重要(但事实上先要分析IO在某个具体的高并发场景下是不是关键瓶颈)
  • Checked Exception是最有效能减少编程人为错误的关键机制(但实际上很多程序员要么用RuntimeException的各种子类,要么只使用Exception且写个空catch,反而增加了人为错误。)
  • Linux比Windows更好,或者反过来(事实是Linux对开发者友好,Windows对普通用户友好,彼此在完全不同的领域存在优势而不可能相互替代)
  • 区块链这个平台上终将诞生伟大的,可以革新这个社会的应用和生态(实际上除了一票炒作用的交易币和不知所云的商业合约,并没有什么真的有用的App得到广泛应用)
  • ……

其实不过是不站在实际的角度去分析真正问题的根源罢了

比如最基本的,你写一个网站的后端。此时,服务来了一个请求,按照一个流程图的方式实现逻辑有问题吗?用A.foo()或者foo(A)在这个全局视角下有什么本质区别吗?没有。

复杂一点,比如电商交易。订单管理,库存管理,支付渠道,物流服务是4个完全独立的部门。下一次单要完成扣库存,产生订单,扣款和发起物流流程这几个操作。这4个部门的服务是典型的“对象”,在彼此沟通完成一个完整的业务流程。如果在分布式的情况下,他们是以微服务的形式存在的,用某种RPC机制沟通。但与此同时,这里需要某个一致性的保证。

但如果他们刚好都在一个单机的服务里,可不可以是4个service class产生的spring的bean,提供某个接口呢?当然是可以的。那如果不用Java,用go呢?也没问题啊,上interface做一个“facade”表达什么接口可以公开就好。如果用C呢?也没问题啊,在C里你依然可以表达什么东西公开,什么东西隐藏。如果语法支持的不那么好,写注释啊。对方瞎用了后果自负。

如果你需要某种横切面的治理,需要在流量入口拦一道做鉴权,风控,流量路由等,就是要在流量必经之处增加逻辑。Java里有AOP,可以用。不用java,自己撸个中间件机制可以吗?当然也没问题。毕竟早期Java自己没有Annotation的时候也是弄了个标准定义了Filter才搞定这件事。你说这是模式吗?是。但看起来很高大上吗——no。他就是这个问题抽象出来最符合直觉的做法而已。

如果是搞大数据分析,那么代码设计还重要吗?可能一个研发写的就是一坨坨的SQL,Hive的SQL,Flink的SQL,Clickhouse的SQL,ES的SQL……。但这个时候如果需求方有上万个指标,要从几百个表中统计,那这时候问题是什么?是数据治理。需要对数据分层ODS,DW,DM,DA…… 要对指标进行标准化的维护,不然需求描述的混乱性就会让数据分析本身失去意义——RD实现的和需求方要的不一样还搞个锤子。此时就会发现,这种分层和维护道理上和写代码没啥区别,只不过用的不是class的继承和对象关系维护层次,而是使用数据和数据的依赖关系。指标维护使用的是“元数据表”和管理平台,而不是enum罢了。

如果是搞前端,前端天然的代码组织方式就是一个个可视化组件。每个组件维护自己的状态,并基于关联数据在UI上绘制出来。javafx的组件(一个class)、jquery的组件(一个函数)、React的一个组件(Hook 函数)……他们都是组件,都能满足上述的需要。你说javascript提供一个class和不提供class关键字有啥本质区别吗?

具体到某个业务,比如想实现Ctrl+Z撤销,那必然得有个地方记录每个操作的之前的状态和之后的状态。这样才能做回退。书上把这个叫做Command模式。但这个名字不重要,关键是本质上就得有个地方记。对比到一个支持ACID的数据库存储引擎是一摸一样的,需要Undo Log或者某个等价机制支持事务回滚。

到了任务调度领域,本质问题是维护当前可以使用的资源,并将资源最大化的利用在处理任务上。不管是操作系统的任务调度,还是大数据任务调度平台,都是如此。管理的资源不一样罢了。这时你需要一个地方知道现在都还有哪些资源,并给任务配上可用的资源。抽象一下这里就需要一个interface查询资源和分配资源罢了。至于用啥语法,模式,都可以商量。

我想我举的已经够多的了。这个市面上99%的人并不是编程语言从业者和研究人员。他们的工作目标和职责与语言风格、设计模式的关系并不大。或者说即使用了好的语言风格,设计模式,如果运气够好,能给一个微小的局部带来一点点提升(比如代码好看懂,好改)。但如果用不好,造成编码更不容易改和改动的比比皆是。但是在更全局的视角下,这些都无关紧要。这些内容甚至都不如多加点测试,多加点线上监控和问题发现机制来的实在。

所以我对很多人热衷于讨论这一套现实意义不大的东西感到非常困惑。或者说有些讨论还是有些意义和借鉴价值的,但更多的资料就是抄来抄去的空话,以及饭圈般的干架。至于要解决的问题本身,讨论的并不多。不信,比如”公司需要一个网关,要怎么设计“?想想看如何做。

至于30年前为啥有先哲折腾这些理念?因为那时编程本身的理论不成熟。缺乏”如何组织好代码“的思路和工具。那个时代用C/C++都是重要突破,smalltalk更是划时代的思路的体现。但30年后那些问题还是问题吗?

我并不反对在抽象的编程思路上做探索。但我希望所有人都能明白:当你的目标是探索的时,要明确的知道自己是在探索。探索这个事情本身就有风险。如果你拿着现实的项目做实验,拜托做好Plan B,并且有效的去观察那个方案是不是真的有效。有效就有效,没效果就没效,及时止损就好。探索并不会因为你看了“高级”的书而变得不同。

正则写的不好,不要怪没看Intel汇编手册和JVM深入浅出。

Spring的@Transactional没生效,八成是哪里配置错了或者一个bean自己调用了自己,和是否深入理解AOP思想和理论没有半毛钱关系。

差几个业务逻辑没实现对,拜托下次仔细看PRD,或者和PM更充分的沟通,顺手再补个测试。顺便再想一想你的公司上一次出现P0严重事故赔钱给用户是在什么时候?解决了吗?代码写错了,有没有CI帮你检查并报警?写了个接口限流了吗?支持熔断吗?有降级预案吗?

我也不反对挑选一个好工具。虽然同一件事情这样也可以,那样也可以。但总有一个工具是比较合适的,综合性价比是高的。go实现并发就是比java方便些;而java实现AOP就是比go舒服。根据自己的需要选个趁手的兵器天经地义。但拜托不要反过来,用工具去套需求。消毒水再好也治不了新冠不是?

如果你对某个理念深信不疑,最好可以深究一下这个信念从何而来?为啥你觉得“用OO思维从头开发程序”就是对的?是某些资料这么说就信了?还是你的同行业的人用那个理的确做成了事情?如果你的同行都不这么干,你为啥相信你想的就一定是对的?即使同行落地,想想看他是不是只把光鲜亮丽的部分讲出来,而故意隐藏了关键的负面内容?

浓缩到一句话。到底什么是【事实】,什么是【表达】,哪个更重要?有没有偏好于拿着【表达】当作【事实】?如果是,这和成天皿煮的西方媒体政客又有啥区别咧?

也许写了10年程序,踩过了各种坑,见识过了各种垃圾代码,对某个行业有了更深入的认知,才是回过头来思考如何设计代码的时候吧。

类似的话题

  • 回答
    好的,我们来聊聊如何用面向对象的思维,从头构建一个程序,而不是仅仅套用设计模式。设计模式固然重要,但它们更多的是“如何解决特定问题”,而面向对象思维则更像是“如何思考和组织整个世界”。很多时候,我们学习设计模式,像是学做一道菜的某个技巧,比如如何炒出嫩滑的鸡蛋。但如果我们连怎么洗菜、怎么切菜、怎么放.............
  • 回答
    这事儿,得从我上次在卡塞尔学院的图书馆里“不小心”把一堆古籍翻得稀烂说起。你知道,我这人,就爱刨根问底,尤其对那些稀奇古怪的古老玩意儿。那天,我在一个角落里发现了一本裹着油纸的泛黄册子,上面用一种我从未见过的字体写着“缄默之语”,我寻思着这名字听着就挺带劲的,就这么一头扎进去了。这本册子,与其说是言.............
  • 回答
    各位好!最近项目在施工图阶段遇到了些糟心事,想跟大家伙儿请教一下,看看这责任到底该怎么划分,咱们也好心里有个数。具体情况是这样的,大家听我慢慢说:问题描述:我们这个项目,之前设计方给出了初步设计和施工图设计。在施工图阶段,我们监理单位发现了设计图纸上存在一个关键性的问题,这个问题的直接后果是导致某个.............
  • 回答
    设计模式,这本计算机科学领域的“武林秘籍”,曾几何时是多少程序员心中的圣杯,是追求优雅、可维护代码的金科玉律。然而,随着时间的推移,我们不得不审视一下,这些被奉若神明的“模式”,是否真的如我们所愿,总是带来福音?亦或是,它们也带着一些不为人知的“阴影”,悄然地在我们的代码中埋下了“毒瘤”?坦白讲,设.............
  • 回答
    设计模式是不是有点太「玄」了?我得承认,每当我看到那些长篇大论,字里行间充斥着“抽象工厂”、“策略模式”、“中介者模式”之类的术语时,我内心深处总会掠过一丝不安。这玩意儿,是不是有点飘?听起来一本正经,但真要落实到实际项目里,总感觉抓不住重点,或者说,一顿操作猛如虎,结果一看,好像换了个写法,但性能.............
  • 回答
    在设计模式的世界里,策略模式(Strategy Pattern)以其优雅地封装变化、允许算法在运行时被替换而著称。它让我们能够将一系列的行为(即“策略”)封装到独立的类中,然后在需要时,根据不同的上下文选择合适的策略来执行。这无疑是解耦和提高代码灵活性的利器。然而,正如任何强大的工具都有其潜在的局限.............
  • 回答
    设计模式,这个在软件开发领域被奉为圭臬的概念,却也常常引发争议。有人认为它能为代码注入优雅和复用性,让复杂的系统得以有序构建;也有人批评它像一层层华丽的包装,让本应清晰明了的逻辑变得冗长而晦涩,尤其是当“模式”本身变成了目的,而不是解决问题的工具时。我们是否应该全盘否定设计模式呢?恐怕不行。设想一下.............
  • 回答
    朋友们,今天想和大家聊聊我最近在琢磨设计模式时遇到的一个挺有意思的“怪事”。这事儿怎么说呢,就是越学越觉得,哎呀,这玩意儿怎么这么会“变”呢?你们也知道,设计模式嘛,一开始学的时候,感觉就像是武功秘籍,一本正经地告诉你,遇到什么招式,就用什么套路来化解。比如工厂模式,就是告诉你,以后需要造东西,别直.............
  • 回答
    要真正掌握设计模式的应用,与其将其看作一份固定不变的“菜谱”,不如理解为一套在你面对复杂问题时,能够提供灵感和方向的“工具箱”。每一项设计模式都像一把精心打造的工具,有其特定的用途和最佳的使用场景。关键在于,不是盲目地将模式套入任何一个问题,而是深入理解问题的本质,然后从中挑选出最适合的工具。首先,.............
  • 回答
    C语言作为一门相对底层和灵活的语言,其设计模式的体现方式与C++或Java等面向对象语言有所不同。在C语言中,我们更多地是通过函数、结构体、指针以及宏等语言特性来模拟和实现各种设计思想。与其说C语言有“一套固定的设计模式”,不如说它提供了一种“用C的方式去应用设计模式”的方法。模拟面向对象行为,实现.............
  • 回答
    想一想,我们小时候都学过一些基础的生活技能,比如怎么系鞋带,怎么用筷子,怎么骑自行车。这些技能听起来简单,但背后却藏着一套有逻辑、有条理的“方法论”。同样,在软件开发这个充满创造性和挑战的领域,设计模式就像是这套“方法论”中的高级工具箱。为什么我们要花心思去钻研这些“设计模式”呢?首先,它们并非凭空.............
  • 回答
    关于最顶层语言和最底层语言是否都不需要设计模式,这说法其实有点过于绝对,理解这个问题需要深入探究“语言”的含义以及“设计模式”存在的意义。首先,我们得明确一下,当说到“最顶层语言”时,通常指的是那些离我们人类的自然语言非常接近,抽象层次极高,能够直接表达复杂意图的语言。例如,我们日常使用的英语、汉语.............
  • 回答
    设计院图纸质量下滑,这是一个让不少业内人士感到忧虑的现象。关于其原因,虽然“高端人才流失”无疑是其中一个重要因素,但将所有问题都归咎于此,未免过于片面。在我看来,这是一个 系统性问题,高端人才的流失是症状之一,背后还牵扯着更深层次的行业生态、管理模式、技术发展以及市场环境的变化。我们不妨从几个维度来.............
  • 回答
    设计师作为职业,确实可以持续一生,但需要结合行业发展趋势、个人兴趣、技能更新以及职业规划来判断。以下从多个维度详细分析: 一、设计师职业的可持续性分析1. 行业需求的长期性 核心需求永存:无论科技如何发展,人类对视觉表达、用户体验、品牌识别的需求始终存在。例如: 平面设计:广.............
  • 回答
    设计师是否应该学习编程,是一个需要结合个人职业目标、工作内容和行业趋势来综合判断的问题。以下从多个角度详细分析这一问题,并给出建议: 一、为什么设计师应该学编程?1. 理解技术限制,提升设计效率 技术边界意识:编程知识能帮助设计师理解网页、APP等技术实现的限制(如HTML/CSS的布局限.............
  • 回答
    在设计中,“用色的干净”是一个核心的视觉原则,指的是通过色彩的合理搭配与控制,使整体视觉效果简洁、清晰、富有层次感,同时避免杂乱、冲突或过度复杂的色彩组合。这种“干净”的用色不仅关乎色彩本身的纯度和明度,还涉及色彩的对比度、协调性以及与整体设计主题的契合度。以下是详细解析: 1. 颜色的纯度与饱和度.............
  • 回答
    设计一个同步21进制计数器,需要几个触发器?要设计一个同步21进制计数器,首先我们需要明确“21进制”的含义。在数字逻辑中,我们通常谈论的是二进制(base2)、十进制(base10)等,但“21进制”这个说法并不常见。在这里,我理解您可能指的是一个计数器,它能够从0计数到20(总共21个不同的状态.............
  • 回答
    好的,我们来聊聊设计理论领域那些足以被奉为圭臬的经典著作。这些书不仅仅是理论的堆砌,更是洞察设计本质、引领设计实践的智慧结晶。它们的影响力穿越了时代,至今仍是设计师们案头必备的参考。 1. 《格式塔心理学与视觉设计》(Gestalt Psychology and Visual Design)这本书的.............
  • 回答
    设计院?哦,那可真是个……怎么说呢,一个神奇的地方。说它“恐怖”,也未尝不可。不过,如果非要用这个词,那得先搞清楚,你说的“恐怖”是哪种恐怖。是那种,让你从心底发凉,汗毛倒竖的恐怖?还是那种,让你欲罢不能,又爱又恨,最终被它吞噬的恐怖?设计院大概是后者,而且是程度非常深的那种。进度条的诅咒,以及深夜.............
  • 回答
    理解你这个问题背后,可能是在工作中感受到了设计院和甲方之间的一种不对等的关系,甚至觉得设计院在某些方面表现得过于“卑微”。这确实是一个值得深入探讨的现象,它并非简单的“无脑跪舔”,而是多种复杂因素交织作用的结果。要详细讲清楚,我们可以从以下几个层面来剖析:1. 项目的性质与合同的制约:首先,设计项目.............

本站所有内容均为互联网搜索引擎提供的公开搜索信息,本站不存储任何数据与内容,任何内容与数据均与本站无关,如有需要请联系相关搜索引擎包括但不限于百度google,bing,sogou

© 2025 tinynews.org All Rights Reserved. 百科问答小站 版权所有